Backdrop scope implementation
This commit is contained in:
+90
-63
@@ -97,13 +97,32 @@ gaussian_blur :: proc() {
|
||||
// Both panels share rounded corners.
|
||||
panel_radii := draw.Rectangle_Radii{16, 16, 16, 16}
|
||||
|
||||
draw.gaussian_blur(
|
||||
base_layer,
|
||||
{60, 80, 320, 140},
|
||||
gaussian_sigma = 30,
|
||||
tint = draw.Color{170, 200, 240, 200}, // cool blue, strong mix
|
||||
radii = panel_radii,
|
||||
)
|
||||
// Both zone1 panels share one scope. Different sigmas still trigger separate blur
|
||||
// passes (cost scales with unique sigmas, not with backdrop count); the scope just
|
||||
// declares "these draws form one bracket." `backdrop_scope` is the RAII-style API:
|
||||
// `end_backdrop` fires automatically when the block exits.
|
||||
{
|
||||
draw.backdrop_scope(base_layer)
|
||||
draw.backdrop_blur(
|
||||
base_layer,
|
||||
{60, 80, 320, 140},
|
||||
gaussian_sigma = 30,
|
||||
tint = draw.Color{170, 200, 240, 200}, // cool blue, strong mix
|
||||
radii = panel_radii,
|
||||
)
|
||||
|
||||
// Panel B: lighter blur, warm amber tint. sigma=6.
|
||||
draw.backdrop_blur(
|
||||
base_layer,
|
||||
{420, 80, 320, 140},
|
||||
gaussian_sigma = 6,
|
||||
tint = draw.Color{255, 220, 160, 200}, // warm amber, strong mix
|
||||
radii = panel_radii,
|
||||
)
|
||||
}
|
||||
|
||||
// Text labels for the two panels. Drawn AFTER `end_backdrop` (which fires at the
|
||||
// scope-block exit above), so they composite on top of both panels.
|
||||
draw.text(
|
||||
base_layer,
|
||||
"sigma = 20, cool tint",
|
||||
@@ -112,15 +131,6 @@ gaussian_blur :: proc() {
|
||||
FONT_SIZE,
|
||||
color = draw.Color{30, 35, 50, 255},
|
||||
)
|
||||
|
||||
// Panel B: lighter blur, warm amber tint. sigma=6.
|
||||
draw.gaussian_blur(
|
||||
base_layer,
|
||||
{420, 80, 320, 140},
|
||||
gaussian_sigma = 6,
|
||||
tint = draw.Color{255, 220, 160, 200}, // warm amber, strong mix
|
||||
radii = panel_radii,
|
||||
)
|
||||
draw.text(
|
||||
base_layer,
|
||||
"sigma = 6, warm tint",
|
||||
@@ -130,10 +140,10 @@ gaussian_blur :: proc() {
|
||||
color = draw.Color{60, 40, 20, 255},
|
||||
)
|
||||
|
||||
// Pass-B verification: a rectangle drawn AFTER the backdrops in the same layer
|
||||
// Per the bracket scheduling model, this should render ON TOP of both panels above.
|
||||
// If you see this stripe behind the panels instead of in front, something is wrong with
|
||||
// the Pass B post-bracket path.
|
||||
// Post-bracket verification: a white stripe drawn AFTER `end_backdrop` in the same
|
||||
// layer. Should render ON TOP of both panels because the backdrop scope (and its
|
||||
// composite output) is now closed; any non-backdrop draw on this layer composites
|
||||
// with LOAD on top of whatever the bracket left in source_texture.
|
||||
draw.rectangle(base_layer, {WINDOW_W * 0.5 - 4, 70, 8, 160}, draw.Color{255, 255, 255, 230})
|
||||
|
||||
//----- Zone 2: second layer with its own backdrop --------------------------------
|
||||
@@ -151,14 +161,18 @@ gaussian_blur :: proc() {
|
||||
stripe_y := 320 + (math.sin(t * 0.05) * 0.5 + 0.5) * 200
|
||||
draw.rectangle(zone2, {30, stripe_y, WINDOW_W * 0.55 - 60, 18}, draw.Color{255, 100, 200, 200})
|
||||
|
||||
// Zone 2's frosted panel.
|
||||
draw.gaussian_blur(
|
||||
zone2,
|
||||
{60, 360, WINDOW_W * 0.55 - 120, 160},
|
||||
gaussian_sigma = 10,
|
||||
tint = draw.WHITE, // pure blur (white tint with any alpha is a no-op)
|
||||
radii = draw.Rectangle_Radii{24, 24, 24, 24},
|
||||
)
|
||||
// Zone 2's frosted panel. Single-panel scope; `backdrop_scope` keeps the begin/end
|
||||
// pair tied to the block.
|
||||
{
|
||||
draw.backdrop_scope(zone2)
|
||||
draw.backdrop_blur(
|
||||
zone2,
|
||||
{60, 360, WINDOW_W * 0.55 - 120, 160},
|
||||
gaussian_sigma = 10,
|
||||
tint = draw.WHITE, // pure blur (white tint with any alpha is a no-op)
|
||||
radii = draw.Rectangle_Radii{24, 24, 24, 24},
|
||||
)
|
||||
}
|
||||
draw.text(
|
||||
zone2,
|
||||
"Layer 2 backdrop",
|
||||
@@ -197,15 +211,44 @@ gaussian_blur :: proc() {
|
||||
)
|
||||
}
|
||||
|
||||
// Edge case 1: sigma = 0 "mirror" — sharp framebuffer sample, no blur. Should reproduce
|
||||
// the underlying pixels exactly through the SDF mask. Tinted slightly so it's visible.
|
||||
draw.gaussian_blur(
|
||||
zone3,
|
||||
{WINDOW_W * 0.55 + 30, 310, 150, 70},
|
||||
gaussian_sigma = 0,
|
||||
tint = draw.WHITE, // pure mirror (no blur, no tint)
|
||||
radii = draw.Rectangle_Radii{12, 12, 12, 12},
|
||||
)
|
||||
// All three Zone 3 backdrops share one scope. The sigma=0 mirror, then the two
|
||||
// contiguous sigma=8 panels. The sigma=8 pair stays contiguous in the sub-batch list,
|
||||
// so `append_or_extend_sub_batch` still coalesces them into a single instanced
|
||||
// composite draw — scope boundaries don't affect coalescing, only kind/sigma identity.
|
||||
{
|
||||
draw.backdrop_scope(zone3)
|
||||
|
||||
// Edge case 1: sigma = 0 "mirror" — sharp framebuffer sample, no blur. Should reproduce
|
||||
// the underlying pixels exactly through the SDF mask. Tinted slightly so it's visible.
|
||||
draw.backdrop_blur(
|
||||
zone3,
|
||||
{WINDOW_W * 0.55 + 30, 310, 150, 70},
|
||||
gaussian_sigma = 0,
|
||||
tint = draw.WHITE, // pure mirror (no blur, no tint)
|
||||
radii = draw.Rectangle_Radii{12, 12, 12, 12},
|
||||
)
|
||||
|
||||
// Edge case 2: two same-sigma panels submitted contiguously. The sub-batch coalescer
|
||||
// should merge these into a single instanced V-composite draw. Visually, both should
|
||||
// look identical (modulo position) — same blur radius, same tint.
|
||||
draw.backdrop_blur(
|
||||
zone3,
|
||||
{WINDOW_W * 0.55 + 30, 400, 150, 70},
|
||||
gaussian_sigma = 8,
|
||||
tint = draw.Color{160, 255, 160, 200}, // green tint, strong mix
|
||||
radii = draw.Rectangle_Radii{12, 12, 12, 12},
|
||||
)
|
||||
draw.backdrop_blur(
|
||||
zone3,
|
||||
{WINDOW_W * 0.55 + 200, 400, 150, 70},
|
||||
gaussian_sigma = 8,
|
||||
tint = draw.Color{160, 255, 160, 200}, // identical: tests sub-batch coalescing
|
||||
radii = draw.Rectangle_Radii{12, 12, 12, 12},
|
||||
)
|
||||
}
|
||||
|
||||
// Edge case 3: text drawn AFTER `end_backdrop` in the same layer. Composites on top of
|
||||
// the bracket's V-composite output and should appear sharply over the green panels.
|
||||
draw.text(
|
||||
zone3,
|
||||
"sigma=0 (mirror)",
|
||||
@@ -214,24 +257,6 @@ gaussian_blur :: proc() {
|
||||
FONT_SIZE,
|
||||
color = draw.Color{20, 20, 20, 255},
|
||||
)
|
||||
|
||||
// Edge case 2: two same-sigma panels submitted contiguously. The sub-batch coalescer
|
||||
// should merge these into a single instanced V-composite draw. Visually, both should
|
||||
// look identical (modulo position) — same blur radius, same tint.
|
||||
draw.gaussian_blur(
|
||||
zone3,
|
||||
{WINDOW_W * 0.55 + 30, 400, 150, 70},
|
||||
gaussian_sigma = 8,
|
||||
tint = draw.Color{160, 255, 160, 200}, // green tint, strong mix
|
||||
radii = draw.Rectangle_Radii{12, 12, 12, 12},
|
||||
)
|
||||
draw.gaussian_blur(
|
||||
zone3,
|
||||
{WINDOW_W * 0.55 + 200, 400, 150, 70},
|
||||
gaussian_sigma = 8,
|
||||
tint = draw.Color{160, 255, 160, 200}, // identical: tests sub-batch coalescing
|
||||
radii = draw.Rectangle_Radii{12, 12, 12, 12},
|
||||
)
|
||||
draw.text(
|
||||
zone3,
|
||||
"sigma=8 (coalesced pair)",
|
||||
@@ -240,12 +265,9 @@ gaussian_blur :: proc() {
|
||||
FONT_SIZE,
|
||||
color = draw.Color{20, 40, 20, 255},
|
||||
)
|
||||
|
||||
// Edge case 3: text drawn AFTER a backdrop in the same layer. Tests Pass B over a fresh
|
||||
// V-composite output. The text should appear sharply on top of the green panels above.
|
||||
draw.text(
|
||||
zone3,
|
||||
"Pass B text overlay",
|
||||
"Post-scope text overlay",
|
||||
{WINDOW_W * 0.55 + 38, 480},
|
||||
PLEX_SANS_REGULAR,
|
||||
FONT_SIZE,
|
||||
@@ -343,18 +365,23 @@ gaussian_blur_debug :: proc() {
|
||||
// THE PANEL UNDER TEST. Square, centered, large enough to cover multiple grid cells and
|
||||
// the circle row. Square shape makes any horizontal-vs-vertical asymmetry purely
|
||||
// renderer-driven (geometry can't introduce it).
|
||||
//
|
||||
// Uses the explicit begin/end form (instead of `backdrop_scope`) to exercise the
|
||||
// alternative API surface in the diagnostic harness.
|
||||
panel := draw.Rectangle{250, 150, 300, 300}
|
||||
draw.gaussian_blur(
|
||||
draw.begin_backdrop(base_layer)
|
||||
draw.backdrop_blur(
|
||||
base_layer,
|
||||
panel,
|
||||
gaussian_sigma = sigma,
|
||||
tint = draw.WHITE,
|
||||
radii = draw.Rectangle_Radii{20, 20, 20, 20},
|
||||
)
|
||||
draw.end_backdrop(base_layer)
|
||||
|
||||
// Pass B test: a bright rectangle drawn AFTER the backdrop in the same layer. Should
|
||||
// always render on top of the panel. If the panel ever shows a "ghost" of this rect
|
||||
// inside its blur, the V-composite is sampling the wrong texture state.
|
||||
// Post-scope test: a bright rectangle drawn AFTER `end_backdrop` in the same layer.
|
||||
// Should always render on top of the panel. If the panel ever shows a "ghost" of this
|
||||
// rect inside its blur, the V-composite is sampling the wrong texture state.
|
||||
if show_test_rect {
|
||||
draw.rectangle(base_layer, {380, 280, 40, 40}, draw.Color{0, 200, 0, 255})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user