fusedDrawTiles function
Splits a fused draw into disjoint rectangles, each carrying only the shapes that can change a pixel inside it.
Returns null when the split is refused as too fine (maxTiles); the caller
then draws the one quad it always could. An empty list means there was
nothing to draw.
Why the area can shrink at all. The fold is bounded below by
min_i d_i - delta(n) * k (_foldDepression), so the silhouette lies
inside the union of the members' own boxes each grown by reach — not
inside the bounding box of all of them grown by the same. On a clustered
layout the two are nearly the same rectangle; on a scattered one the second
is the screen and the first is twelve panels' worth of it.
Why a shape can be dropped from a tile, exactly. A shape farther than
(1 + 2 * delta(n)) * k from the tile — cullMargin — cannot change one
bit of any fragment in it, and that is arithmetic rather than a tolerance.
Run the fold in the order the uniforms are in. Before the first near shape
is folded the running d is at least min_far - delta(n) * k, which that
margin puts at (1 + delta(n)) * k or more; a near shape sits at
delta(n) * k or less wherever the draw is not already transparent, so
|d_i - d| >= k, h is exactly zero, and the fold leaves min(d_i, d)
with mix(n, n_i, 0) — the near shape's own distance and its own normal,
which is what it would have found had the far ones never been there. After
that first near shape d <= delta(n) * k, so every later far one is
k away or more and is skipped for the same reason. The shader's own
uCullK branch is this same identity spent on speed, which is why the two
are independent: dropping a shape here is exact whether or not the branch
runs.
Why the rectangles must not overlap. The draw is translucent
(vec4(col, 1) * coverage), so a pixel covered twice composites twice and
the seam is visible. The decomposition below is a partition by construction
— vertical slabs at every box edge, disjoint y-intervals inside each — and
the draws go out with antialiasing off, so the rasterizer's own rule gives
each device pixel to exactly one of two tiles that share an edge.
Implementation
List<GlassFusedTile>? fusedDrawTiles({
required List<Rect> boxes,
required double reach,
required double cullMargin,
int maxTiles = kMaxFusedTiles,
}) {
final int n = boxes.length;
if (n == 0) {
return const <GlassFusedTile>[];
}
final covers = <Rect>[for (final Rect b in boxes) b.inflate(reach)];
// One decomposition per connected run of overlapping boxes, and that is the
// difference between a dozen rectangles and forty. A single sweep over all of
// them splits every box at every other box's edges — including the edges of
// one on the far side of the screen, which shares no pixel with it and cannot
// change what is drawn there. Boxes that do not overlap are already disjoint
// rectangles, so their decompositions cannot collide and each can be taken on
// its own. Measured on the corpus: twelve scattered panels fall into 14-21
// rectangles this way and into 39-55 without it, for the same area.
final rects = <Rect>[];
for (final List<int> part in _overlapping(covers)) {
final slice = <Rect>[for (final int i in part) covers[i]];
// Every x where the set of boxes in force can change, so a slab between two
// of them is spanned by the same boxes from top to bottom.
final xs = <double>{
for (final Rect r in slice) ...<double>[r.left, r.right],
}.toList(growable: false)..sort();
// The run of slabs whose y-intervals are identical, so a single box comes
// back as a single rectangle rather than as one per edge in the layout.
List<double>? run;
double runLeft = 0;
for (var j = 0; j + 1 < xs.length; j++) {
final List<double> intervals = _slabIntervals(slice, xs[j], xs[j + 1]);
if (run != null && _sameSpans(run, intervals)) {
continue;
}
if (run != null) {
_emitSpans(rects, runLeft, xs[j], run);
}
run = intervals.isEmpty ? null : intervals;
runLeft = xs[j];
}
if (run != null) {
_emitSpans(rects, runLeft, xs.last, run);
}
if (rects.length > maxTiles) {
return null;
}
}
return <GlassFusedTile>[
for (final Rect rect in rects)
GlassFusedTile(rect, <int>[
for (var i = 0; i < n; i++)
if (_within(boxes[i], cullMargin, rect)) i,
]),
];
}