Skip to content

Develop a general (convex or concave) path SDF renderer #183959

Open
0 of 1 issue completed
Open

Description

@flar

Impeller is adding many shape-specific renderers that will enable higher quality antialiasing on low-resolution devices like desktop screens, but we will also need a general solution that can render all paths.

Activity

  1. added
    engineflutter/engine related. See also e: labels.
    e: impellerImpeller rendering backend issues and features requests
    on Mar 23, 2026
  2. added
    P2Important issues not at the top of the work list
    c: new featureNothing broken; request for a new capability
    on Mar 23, 2026
  3. jonahwilliams commented on Mar 30, 2026

    @jonahwilliams
    Contributor

    Interestingly I'm working on a fairly similar problem. my thoughts are roughly:

    1. For simple convex shapes, do a basic triangulation then use loop-blinn for curves. For conic, cubic, chop into quads.
    2. For simple concave shapes, do ear clipping then similar loop blinn approach for exterior
    3. For self intersecting ... I'm not sure yet. I was actually thinking about applying the slug algorithm. Not sure how well it will perform.

    Besides the shapes themselves, once you start using SDFs the simple approach to blend modes Impeller was using no longer works. For example, BlendMode::clear will clear pixels that aren't "covered" by the SDF unless you're also using discard. But if you use discard then no AA.

  4. flar commented on Mar 30, 2026

    @flar
    ContributorAuthor

    Besides the shapes themselves, once you start using SDFs the simple approach to blend modes Impeller was using no longer works. For example, BlendMode::clear will clear pixels that aren't "covered" by the SDF unless you're also using discard. But if you use discard then no AA.

    In software we used to apply the blend mode before we applied the AA/SDF factor. That's not possible with shader code directly (no access to destination pixels). A 2-pass approach can provide the original destination pixels as an input to the shader, though.

  5. flar commented on Mar 30, 2026

    @flar
    ContributorAuthor

    Besides the shapes themselves, once you start using SDFs the simple approach to blend modes Impeller was using no longer works. For example, BlendMode::clear will clear pixels that aren't "covered" by the SDF unless you're also using discard. But if you use discard then no AA.

    In software we used to apply the blend mode before we applied the AA/SDF factor. That's not possible with shader code directly (no access to destination pixels). A 2-pass approach can provide the original destination pixels as an input to the shader, though.

    Also, DstIn could be used for Clear and be compatible with the AA/SDF factor.

  6. gaaclarke commented on Mar 30, 2026

    @gaaclarke
    Member

    Inigo Quilez has the math for sdf polygons in https://iquilezles.org/articles/distfunctions2d/

    It seems to show self intersecting edges. I'm not sure if this is something worth looking into.

  7. flar commented on Mar 30, 2026

    @flar
    ContributorAuthor

    Inigo Quilez has the math for sdf polygons in https://iquilezles.org/articles/distfunctions2d/

    It seems to show self intersecting edges. I'm not sure if this is something worth looking into.

    Working through the math on it. It links to a shader toy that describes the line that computes c as dealing with the winding count, but it doesn't explain it. It includes a link on the subject that doesn't resolve for me.

    The results for the shadertoy seem to indicate that it is performing even-odd winding calculations.

  8. flar commented on Mar 30, 2026

    @flar
    ContributorAuthor

    One thing to note about that library of SDF snippets is that they are only concerned with getting the sign of the return value correct. They don't necessarily produce a value that can be immediately used to determine an AA gradient at the edge or applying a (half) stroke width for stroked versions. More work needs to be done on them to get those values.

  9. jonahwilliams commented on Mar 31, 2026

    @jonahwilliams
    Contributor

    Having the library of functions is nice, I'm using a round rect sdf and stroked round rect sdf and that is usually 95% of what is needed. Doesn't solve the general path case though, and I don't want to use subdivision × tessellation for quality reasons

  10. flar commented on Mar 31, 2026

    @flar
    ContributorAuthor

    Having the library of functions is nice, I'm using a round rect sdf and stroked round rect sdf and that is usually 95% of what is needed. Doesn't solve the general path case though, and I don't want to use subdivision × tessellation for quality reasons

    It's a great library if you rely on MSAA which we do for most devices, but for desktop we are investigating them for computational AA and then you need to worry about not just which side of the border you're on, but how far you are in pixel (or local) distances. The library gives you distances in whatever space you deliver the geometry in, but we have conflicting needs:

    • stroke widths are computed in local coordinates
    • the "AA gradient" (i.e. whether you are within half a pixel from the border) is computed in device coordinates
    • preventing stroke dropouts when the stroke width is smaller than a device pixel also needs to be evaluated in device coordinates.
  11. flar commented on Apr 16, 2026

    @flar
    ContributorAuthor

    One thing to note about that library of SDF snippets is that they are only concerned with getting the sign of the return value correct. They don't necessarily produce a value that can be immediately used to determine an AA gradient at the edge or applying a (half) stroke width for stroked versions. More work needs to be done on them to get those values.

    At the bottom they describe use of those shaders for stroking. The only missing piece of that puzzle is making sure hairlines don't disappear or "grow beyond hairline-size" on primitives in an odd coordinate transform.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listc: new featureNothing broken; request for a new capabilitye: impellerImpeller rendering backend issues and features requestsengineflutter/engine related. See also e: labels.team-engineOwned by Engine teamtriaged-engineTriaged by Engine team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions