Orgnaization & cleanup
This commit is contained in:
@@ -1,19 +1,18 @@
|
||||
#version 450 core
|
||||
|
||||
// Unified backdrop blur fragment shader.
|
||||
// Handles both H-blur (mode 0, blurs the ¼-resolution downsample texture into
|
||||
// the ¼-resolution h_blur texture) and V-blur+composite (mode 1, blurs h_blur
|
||||
// vertically, masks via RRect SDF, applies tint, composites outline, and writes
|
||||
// to the main render target with premultiplied alpha).
|
||||
// Handles both the 1D separable blur passes (mode 0, used for BOTH the H-pass and V-pass;
|
||||
// `direction` picks the axis) and the composite pass (mode 1, reads the fully-blurred
|
||||
// working texture, masks via RRect SDF, applies tint, and writes to source_texture with
|
||||
// premultiplied-over blending). Working textures are sized at the full swapchain resolution;
|
||||
// downsampled content occupies only a sub-rect at downsample factor > 1 (set via viewport).
|
||||
//
|
||||
// Following RAD's pattern, V-mode replaces a separate composite pass: the SDF
|
||||
// discard limits V-blur work to the masked region, and the per-primitive tint
|
||||
// is folded in. Output blends with the main render target via the standard
|
||||
// premultiplied-over blend state (ONE, ONE_MINUS_SRC_ALPHA).
|
||||
// The composite blends with source_texture via the standard premultiplied-over blend state
|
||||
// (ONE, ONE_MINUS_SRC_ALPHA).
|
||||
//
|
||||
// Backdrop primitives are tint-only — there is no outline. A specialized edge
|
||||
// effect (e.g. liquid-glass-style refraction outlines) would be implemented
|
||||
// as a dedicated primitive type with its own pipeline.
|
||||
// Backdrop primitives are tint-only — there is no outline. A specialized edge effect
|
||||
// (e.g. liquid-glass-style refraction outlines) would be implemented as a dedicated
|
||||
// primitive type with its own pipeline.
|
||||
//
|
||||
// Two modes, structurally distinct:
|
||||
//
|
||||
@@ -30,11 +29,11 @@
|
||||
// (gl_FragCoord.xy * inv_downsample_factor) * inv_working_size.
|
||||
// No kernel is applied here — the blur is already complete.
|
||||
//
|
||||
// Splitting V-blur out of the composite pass (an earlier version combined them) was needed
|
||||
// to avoid a horizontal-vs-vertical asymmetry artifact: when the V-blur sampled the H-blur
|
||||
// output through the bilinear-upsample/SDF-mask/tint pipeline in one shader invocation,
|
||||
// horizontal source features ended up looking sharper than vertical ones. Running V-blur as
|
||||
// its own working→working pass (matching H's structure exactly) restores symmetry.
|
||||
// V-blur is run as its own working→working pass rather than folded into the composite. The
|
||||
// folded variant produced a horizontal-vs-vertical asymmetry artifact: when V-blur sampled
|
||||
// the H-blur output through the bilinear-upsample/SDF-mask/tint pipeline in one shader
|
||||
// invocation, horizontal source features ended up looking sharper than vertical ones.
|
||||
// Matching V's structure exactly to H's restores symmetry.
|
||||
|
||||
const uint MAX_KERNEL_PAIRS = 32;
|
||||
|
||||
@@ -140,16 +139,16 @@ void main() {
|
||||
vec2 uv = (gl_FragCoord.xy * inv_downsample_factor) * inv_working_size;
|
||||
vec3 color = texture(blur_input_tex, uv).rgb;
|
||||
|
||||
// Tint composition (Option B semantics): inside the masked region the panel is fully
|
||||
// opaque — it completely hides the original framebuffer content, just like real frosted
|
||||
// glass and like iOS UIBlurEffect / CSS backdrop-filter. f_color.rgb specifies the tint
|
||||
// color; f_color.a specifies the tint *mix strength* (NOT panel opacity). At alpha=0 we
|
||||
// see the pure blur; at alpha=255 we see the blur fully multiplied by the tint color.
|
||||
// Tint composition: inside the masked region the panel is fully opaque — it completely
|
||||
// hides the original framebuffer content, just like real frosted glass and like iOS
|
||||
// UIBlurEffect / CSS backdrop-filter. f_color.rgb specifies the tint color; f_color.a
|
||||
// specifies the tint *mix strength* (NOT panel opacity). At alpha=0 we see the pure
|
||||
// blur; at alpha=255 we see the blur fully multiplied by the tint color.
|
||||
//
|
||||
// Output is premultiplied to match the ONE, ONE_MINUS_SRC_ALPHA blend state. Coverage
|
||||
// (the SDF mask's edge AA) modulates only the alpha channel, never the panel-vs-source
|
||||
// blend; that way edge pixels still feather correctly without re-introducing the bug
|
||||
// where mid-panel pixels became semi-transparent.
|
||||
// blend; that way edge pixels still feather correctly while mid-panel pixels stay fully
|
||||
// opaque.
|
||||
mediump vec3 tinted = mix(color, color * f_color.rgb, f_color.a);
|
||||
mediump float coverage = sdf_alpha(d_n, h_n);
|
||||
out_color = vec4(tinted * coverage, coverage);
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
#version 450 core
|
||||
|
||||
// Unified backdrop blur vertex shader.
|
||||
// Handles both H-blur (fullscreen triangle, mode 0) and V-blur+composite (instanced
|
||||
// unit-quad over Backdrop_Primitive storage buffer, mode 1) for the second PSO of
|
||||
// the backdrop bracket. The first PSO (downsample) uses backdrop_fullscreen.vert.
|
||||
// Handles both the 1D separable blur passes (fullscreen triangle, mode 0; used for
|
||||
// BOTH the H-pass and V-pass) and the composite pass (instanced unit-quad over
|
||||
// Backdrop_Primitive storage buffer, mode 1) for the second PSO of the backdrop bracket.
|
||||
// The first PSO (downsample) uses backdrop_fullscreen.vert.
|
||||
//
|
||||
// No vertex buffer for either mode. Mode 0 uses gl_VertexIndex 0..2 for a single
|
||||
// fullscreen triangle; mode 1 uses gl_VertexIndex 0..5 for a unit-quad (two
|
||||
// triangles, TRIANGLELIST topology) and gl_InstanceIndex to select the primitive.
|
||||
//
|
||||
// Mode 0 viewport+scissor are CPU-set per layer-bracket to the work region (union
|
||||
// AABB of backdrop primitives + 3*max_sigma, clamped to swapchain bounds). Mode 1
|
||||
// renders into the main render target with the screen-space orthographic projection;
|
||||
// the per-primitive bounds drive the quad in screen space.
|
||||
// Mode 0 viewport+scissor are CPU-set per sigma group to the work region (union AABB
|
||||
// of that group's backdrop primitives + halo, clamped to swapchain bounds). Mode 1
|
||||
// renders into source_texture with the screen-space orthographic projection; the
|
||||
// per-primitive bounds drive the quad in screen space.
|
||||
//
|
||||
// Backdrop primitives have NO rotation — backdrop sampling is in screen space, so
|
||||
// a rotated mask over a stationary blur sample would look wrong.
|
||||
@@ -46,11 +47,11 @@ layout(set = 1, binding = 0) uniform Uniforms {
|
||||
// vec2 and scalar tail packs tight to land the struct at a clean 48-byte
|
||||
// stride (a multiple of 16, so the array stride needs no rounding either).
|
||||
// Field semantics match the CPU-side Backdrop_Primitive declared in
|
||||
// levlib/draw/pipeline_2d_backdrop.odin; keep both in sync.
|
||||
// levlib/draw/backdrop.odin; keep both in sync.
|
||||
//
|
||||
// Backdrop primitives are tint-only in v1: outline is intentionally absent.
|
||||
// Future specialized effects (e.g. liquid-glass-style edges) would be a
|
||||
// dedicated primitive type with its own pipeline rather than a flag bit here.
|
||||
// Backdrop primitives are tint-only: outline is intentionally absent. Specialized
|
||||
// edge effects (e.g. liquid-glass-style refraction outlines) would be a dedicated
|
||||
// primitive type with its own pipeline rather than a flag bit here.
|
||||
struct Backdrop_Primitive {
|
||||
vec4 bounds; // 0-15: min_xy, max_xy (world-space)
|
||||
vec4 radii; // 16-31: per-corner radii (physical px)
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
// Backdrop downsample fragment shader.
|
||||
// Reads source_texture (full-resolution snapshot of pre-bracket framebuffer contents) and
|
||||
// writes a downsampled copy at factor 1, 2, 4, 8, or 16. The output is the working texture
|
||||
// (sized at full swapchain resolution); larger factors only fill a sub-rect of it via the
|
||||
// CPU-set viewport. See backdrop.odin for the factor selection table (Flutter-style).
|
||||
// writes a downsampled copy at factor 1, 2, or 4. The output is the working texture (sized
|
||||
// at full swapchain resolution); larger factors only fill a sub-rect of it via the CPU-set
|
||||
// viewport. See backdrop.odin for the factor selection table (Flutter-style).
|
||||
//
|
||||
// Shader paths by factor:
|
||||
//
|
||||
@@ -15,15 +15,12 @@
|
||||
// factor=2: each output covers a 2×2 source block. Single bilinear tap at the shared
|
||||
// corner reads all 4 source pixels with 0.25 weight.
|
||||
//
|
||||
// factor>=4: each output covers a (factor)×(factor) source block. We use 4 bilinear taps,
|
||||
// each at the shared corner of a (factor/2)×(factor/2) sub-block. Each tap reads
|
||||
// 4 source pixels uniformly; combined, the 4 taps sample 16 source pixels arranged
|
||||
// uniformly across the block. This is an approximation of a true (factor)² box
|
||||
// filter — exact at factor=4 (16 pixels = full coverage), undersampled at factor=8
|
||||
// (16 pixels of 64) and factor=16 (16 of 256). Flutter uses a richer 13-tap COD-
|
||||
// style downsample shader at high factors; we accept the simpler 4-tap pattern
|
||||
// for now since the high-factor cases come with large kernels that mask any
|
||||
// residual aliasing.
|
||||
// factor=4: each output covers a 4×4 source block. We use 4 bilinear taps, each at the
|
||||
// shared corner of a 2×2 sub-block. Each tap reads 4 source pixels uniformly;
|
||||
// combined, the 4 taps sample 16 source pixels arranged uniformly across the
|
||||
// block (full coverage at factor=4). The factor>=4 path is structured so the
|
||||
// same shader code would extend to factor=8 (16 pixels of 64) or factor=16 (16
|
||||
// of 256) if the CPU-side cap is ever raised, though the current cap is 4.
|
||||
//
|
||||
// The viewport+scissor are set by the CPU to limit output to the layer's work region in
|
||||
// working-texture coords (work_region_phys / factor), clamped to the texture bounds.
|
||||
|
||||
@@ -45,7 +45,7 @@ layout(std430, set = 0, binding = 0) readonly buffer Base_2D_Primitives {
|
||||
// ---------- Entry point ----------
|
||||
void main() {
|
||||
if (mode == 0u) {
|
||||
// ---- Mode 0: Tessellated (legacy) ----
|
||||
// ---- Mode 0: Tessellated (used for text and arbitrary user geometry) ----
|
||||
f_color = v_color;
|
||||
f_local_or_uv = v_uv;
|
||||
f_params = vec4(0.0);
|
||||
|
||||
Reference in New Issue
Block a user