-
Notifications
You must be signed in to change notification settings - Fork 136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Correctly handle disjoint bounding-box intersections in binning #335
Conversation
Added a test scene that demonstrates the clipping bugs reported in vello#286 and vello#333.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, and exciting to see a fix for this long-standing issue.
shader/binning.wgsl
Outdated
@@ -89,12 +89,18 @@ fn main( | |||
let bbox_raw = bbox_intersect(clip_bbox, pb); | |||
// TODO(naga): clunky expression a workaround for broken lhs swizzle | |||
let bbox = vec4(bbox_raw.xy, max(bbox_raw.xy, bbox_raw.zw)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You probably no longer need the max here, as everything downstream should be able to interpret x1 < x0 or y1 < y0 as an empty box.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Yes! This has been in my queue for a long time and I’ve been dreading hunting it down. I’m excited to test this on some Lottie scenes with known clipping artifacts. |
When the bounding boxes of a path and its clip are disjoint (i.e. they do not intersect) the result of their intersection is a negative rectangle. When calculating the intersection of the bboxes, the binning stage ensures that the bbox is non-negative. It then normalizes the coordinates to bin dimensions and rounds the top-left corner down to the neareast integer and the bottom-right corner up. However this rounding causes zero-area bounding boxes to have a non-zero area and sends the bottom-right corner to the placed in the next bin. This causes fully clipped out draw objects to be included in binning, with an incorrect clip bounding box that causes them to be erroneously drawn with partial clipping. `binning` now takes care around this logic to make sure that a zero-area intersected-bbox gets skipped and clipped out. `tile_alloc`, also takes care in its logic. Fixes linebender#286 and linebender#333
@dfrg Yes, please do! Let me know if this fixes the artifacts you've been seeing with lottie scenes. |
Basically ports #335, which aggressively culls empty bounding boxes.
Basically ports #335, which aggressively culls empty bounding boxes.
When the bounding boxes of a path and its clip are disjoint (i.e. they do not intersect) the result of their intersection is a negative rectangle.
When calculating the intersection of the bboxes, the binning stage ensures that the bbox is non-negative. It then normalizes the coordinates to bin dimensions and rounds the top-left corner down to the neareast integer and the bottom-right corner up.
However this rounding causes zero-area bounding boxes to have a non-zero area and sends the bottom-right corner to be placed in the next bin. This causes fully clipped out draw objects to be included in binning, with an incorrect clip bounding box that causes them to be erroneously drawn with partial clipping.
binning
now takes care around this logic to make sure that a zero-area intersected-bbox gets skipped and clipped out.tile_alloc
, also takes care in its own similar logic over intersected-bbox contents.Fixes #286 and #333