diff options
Diffstat (limited to 'shaders')
| -rw-r--r-- | shaders/image.frag.glsl | 6 | ||||
| -rw-r--r-- | shaders/overlay.frag.glsl | 10 | ||||
| -rw-r--r-- | shaders/prebuilt/image.frag.glsl | 6 | ||||
| -rw-r--r-- | shaders/prebuilt/image.frag.spv | bin | 3684 -> 4200 bytes | |||
| -rw-r--r-- | shaders/prebuilt/overlay.frag.glsl | 10 | ||||
| -rw-r--r-- | shaders/prebuilt/overlay.frag.spv | bin | 444 -> 1008 bytes | |||
| -rw-r--r-- | shaders/prebuilt/ui.frag.glsl | 25 | ||||
| -rw-r--r-- | shaders/prebuilt/ui.frag.spv | bin | 4076 -> 4668 bytes | |||
| -rw-r--r-- | shaders/prebuilt/ui.vert.glsl | 9 | ||||
| -rw-r--r-- | shaders/prebuilt/ui.vert.spv | bin | 5468 -> 5468 bytes | |||
| -rw-r--r-- | shaders/ui.frag.glsl | 25 | ||||
| -rw-r--r-- | shaders/ui.vert.glsl | 9 |
12 files changed, 72 insertions, 28 deletions
diff --git a/shaders/image.frag.glsl b/shaders/image.frag.glsl index 2a3c2038..0cc1b2ee 100644 --- a/shaders/image.frag.glsl +++ b/shaders/image.frag.glsl @@ -1,6 +1,9 @@ #version 450 layout(set = 2, binding = 0) uniform sampler2D u_image; +layout(std140, set = 3, binding = 0) uniform UiUniforms { + float background_opacity; +} u_ui; layout(location = 0) in vec2 v_uv; layout(location = 1) in vec2 v_panel_uv; @@ -19,6 +22,9 @@ float cellNoise(uint serial, uint col, uint row) { void main() { vec4 source = texture(u_image, v_uv); + // Keep source coverage for destination subtraction; the pipeline scales + // source alpha by the same opacity through its alpha blend constant. + source.rgb *= clamp(u_ui.background_opacity, 0.0, 1.0); uint effect = v_effect.x & 0x7fffffffu; bool oldLayer = (v_effect.x & 0x80000000u) != 0u; float progress = clamp(uintBitsToFloat(v_effect.y), 0.0, 1.0); diff --git a/shaders/overlay.frag.glsl b/shaders/overlay.frag.glsl index 86c0188b..b5ac8d5a 100644 --- a/shaders/overlay.frag.glsl +++ b/shaders/overlay.frag.glsl @@ -1,9 +1,17 @@ #version 450 +layout(std140, set = 3, binding = 0) uniform UiUniforms { + float background_opacity; +} u_ui; + layout(location = 0) in vec4 v_color; layout(location = 0) out vec4 o_col; void main() { - o_col = v_color; + // Preserve shape coverage for destination subtraction. The pipeline uses + // the matching opacity blend constant for source alpha, so graphics laid + // over a background with the same opacity do not accumulate opaque seams. + // Text/cursor draw groups bind opacity 1 instead. + o_col = vec4(v_color.rgb * clamp(u_ui.background_opacity, 0.0, 1.0), v_color.a); } diff --git a/shaders/prebuilt/image.frag.glsl b/shaders/prebuilt/image.frag.glsl index 2a3c2038..0cc1b2ee 100644 --- a/shaders/prebuilt/image.frag.glsl +++ b/shaders/prebuilt/image.frag.glsl @@ -1,6 +1,9 @@ #version 450 layout(set = 2, binding = 0) uniform sampler2D u_image; +layout(std140, set = 3, binding = 0) uniform UiUniforms { + float background_opacity; +} u_ui; layout(location = 0) in vec2 v_uv; layout(location = 1) in vec2 v_panel_uv; @@ -19,6 +22,9 @@ float cellNoise(uint serial, uint col, uint row) { void main() { vec4 source = texture(u_image, v_uv); + // Keep source coverage for destination subtraction; the pipeline scales + // source alpha by the same opacity through its alpha blend constant. + source.rgb *= clamp(u_ui.background_opacity, 0.0, 1.0); uint effect = v_effect.x & 0x7fffffffu; bool oldLayer = (v_effect.x & 0x80000000u) != 0u; float progress = clamp(uintBitsToFloat(v_effect.y), 0.0, 1.0); diff --git a/shaders/prebuilt/image.frag.spv b/shaders/prebuilt/image.frag.spv Binary files differindex ac6a2682..c9511ad7 100644 --- a/shaders/prebuilt/image.frag.spv +++ b/shaders/prebuilt/image.frag.spv diff --git a/shaders/prebuilt/overlay.frag.glsl b/shaders/prebuilt/overlay.frag.glsl index 86c0188b..b5ac8d5a 100644 --- a/shaders/prebuilt/overlay.frag.glsl +++ b/shaders/prebuilt/overlay.frag.glsl @@ -1,9 +1,17 @@ #version 450 +layout(std140, set = 3, binding = 0) uniform UiUniforms { + float background_opacity; +} u_ui; + layout(location = 0) in vec4 v_color; layout(location = 0) out vec4 o_col; void main() { - o_col = v_color; + // Preserve shape coverage for destination subtraction. The pipeline uses + // the matching opacity blend constant for source alpha, so graphics laid + // over a background with the same opacity do not accumulate opaque seams. + // Text/cursor draw groups bind opacity 1 instead. + o_col = vec4(v_color.rgb * clamp(u_ui.background_opacity, 0.0, 1.0), v_color.a); } diff --git a/shaders/prebuilt/overlay.frag.spv b/shaders/prebuilt/overlay.frag.spv Binary files differindex 59bbb9d4..e296e99e 100644 --- a/shaders/prebuilt/overlay.frag.spv +++ b/shaders/prebuilt/overlay.frag.spv diff --git a/shaders/prebuilt/ui.frag.glsl b/shaders/prebuilt/ui.frag.glsl index 69cb63b9..3c366602 100644 --- a/shaders/prebuilt/ui.frag.glsl +++ b/shaders/prebuilt/ui.frag.glsl @@ -1,12 +1,16 @@ #version 450 // Sample the glyph atlas (R = coverage 0..1) and mix the cell's bg up to its fg -// by that coverage. Output is PREMULTIPLIED: an opaque cell is unchanged, and a -// cell whose background is the see-through ground (config.gui_transparent, a -// theme with no bg of its own) contributes only its ink, at the ink's own -// coverage, so the compositor keeps the rest. +// by that coverage. Output is PREMULTIPLIED: an opaque cell is unchanged. +// WindowOpacity changes only the ground's coverage, never the glyph's ink. +// A cell whose background is the see-through ground (config.gui_transparent, +// a theme with no bg of its own) still contributes only its ink, at the ink's +// own coverage, so the compositor keeps the rest. layout(set = 2, binding = 0) uniform sampler2D u_atlas; +layout(std140, set = 3, binding = 0) uniform UiUniforms { + float background_opacity; +} u_ui; layout(location = 0) in vec2 v_uv; layout(location = 1) in vec3 v_fg; @@ -29,11 +33,14 @@ float cellNoise(uint serial, uint col, uint row) { void main() { float a = texture(u_atlas, v_uv).r; bool oldLayer = (v_effect.x & 0x80000000u) != 0u; - // 0 where the cell's background IS the ground and the ground is nothing. - // src/gui/gui.zig sets that bit; the two flags above it are why the effect - // id is masked with 0x3fffffff here and in ui.vert.glsl. - float bgA = (v_effect.x & 0x40000000u) != 0u ? 0.0 : 1.0; - uint effect = v_effect.x & 0x3fffffffu; + // A block cursor is foreground chrome even though its fill occupies the + // cell background: keep it visible at WindowOpacity 0. Otherwise a clear + // theme ground has no coverage and ordinary backgrounds use the setting. + // The three high flags are shared with ui.vert.glsl and src/gui/gui.zig. + float bgA = (v_effect.x & 0x20000000u) != 0u ? 1.0 + : (v_effect.x & 0x40000000u) != 0u ? 0.0 + : clamp(u_ui.background_opacity, 0.0, 1.0); + uint effect = v_effect.x & 0x1fffffffu; float progress = clamp(uintBitsToFloat(v_effect.y), 0.0, 1.0); uint cellCol = v_effect.w & 0xffffu; uint cellRow = v_effect.w >> 16; diff --git a/shaders/prebuilt/ui.frag.spv b/shaders/prebuilt/ui.frag.spv Binary files differindex 4eb9993e..120438e7 100644 --- a/shaders/prebuilt/ui.frag.spv +++ b/shaders/prebuilt/ui.frag.spv diff --git a/shaders/prebuilt/ui.vert.glsl b/shaders/prebuilt/ui.vert.glsl index 5ec596fe..d23b609c 100644 --- a/shaders/prebuilt/ui.vert.glsl +++ b/shaders/prebuilt/ui.vert.glsl @@ -14,9 +14,10 @@ layout(location = 3) in vec3 a_bg; layout(location = 4) in vec4 a_panel_rect; layout(location = 5) in vec4 a_present_rect; // effect id, eased-progress float bits, pane serial, local row/column packed -// into one uint. The TWO high effect bits are flags — the frozen-old cell -// layer and a see-through cell background — so the id is what is left below -// them; integer transport preserves the exact cross-backend hash. +// into one uint. The THREE high effect bits are flags — the frozen-old cell +// layer, a see-through cell background and an opaque block-cursor fill — so +// the id is what is left below them; integer transport preserves the exact +// cross-backend hash. layout(location = 6) in uvec4 a_effect; layout(location = 0) out vec2 v_uv; @@ -55,7 +56,7 @@ void main() { v_cell_uv = vec2(0.0, 1.0); } - uint effect = a_effect.x & 0x3fffffffu; + uint effect = a_effect.x & 0x1fffffffu; if (effect == 1u || effect == 2u || effect == 5u) { // NDC y points up, so a top-left/bottom-right box has a NEGATIVE y // delta. Preserve that sign or every local y is mirrored/outside. diff --git a/shaders/prebuilt/ui.vert.spv b/shaders/prebuilt/ui.vert.spv Binary files differindex 08e81e42..659049dd 100644 --- a/shaders/prebuilt/ui.vert.spv +++ b/shaders/prebuilt/ui.vert.spv diff --git a/shaders/ui.frag.glsl b/shaders/ui.frag.glsl index 69cb63b9..3c366602 100644 --- a/shaders/ui.frag.glsl +++ b/shaders/ui.frag.glsl @@ -1,12 +1,16 @@ #version 450 // Sample the glyph atlas (R = coverage 0..1) and mix the cell's bg up to its fg -// by that coverage. Output is PREMULTIPLIED: an opaque cell is unchanged, and a -// cell whose background is the see-through ground (config.gui_transparent, a -// theme with no bg of its own) contributes only its ink, at the ink's own -// coverage, so the compositor keeps the rest. +// by that coverage. Output is PREMULTIPLIED: an opaque cell is unchanged. +// WindowOpacity changes only the ground's coverage, never the glyph's ink. +// A cell whose background is the see-through ground (config.gui_transparent, +// a theme with no bg of its own) still contributes only its ink, at the ink's +// own coverage, so the compositor keeps the rest. layout(set = 2, binding = 0) uniform sampler2D u_atlas; +layout(std140, set = 3, binding = 0) uniform UiUniforms { + float background_opacity; +} u_ui; layout(location = 0) in vec2 v_uv; layout(location = 1) in vec3 v_fg; @@ -29,11 +33,14 @@ float cellNoise(uint serial, uint col, uint row) { void main() { float a = texture(u_atlas, v_uv).r; bool oldLayer = (v_effect.x & 0x80000000u) != 0u; - // 0 where the cell's background IS the ground and the ground is nothing. - // src/gui/gui.zig sets that bit; the two flags above it are why the effect - // id is masked with 0x3fffffff here and in ui.vert.glsl. - float bgA = (v_effect.x & 0x40000000u) != 0u ? 0.0 : 1.0; - uint effect = v_effect.x & 0x3fffffffu; + // A block cursor is foreground chrome even though its fill occupies the + // cell background: keep it visible at WindowOpacity 0. Otherwise a clear + // theme ground has no coverage and ordinary backgrounds use the setting. + // The three high flags are shared with ui.vert.glsl and src/gui/gui.zig. + float bgA = (v_effect.x & 0x20000000u) != 0u ? 1.0 + : (v_effect.x & 0x40000000u) != 0u ? 0.0 + : clamp(u_ui.background_opacity, 0.0, 1.0); + uint effect = v_effect.x & 0x1fffffffu; float progress = clamp(uintBitsToFloat(v_effect.y), 0.0, 1.0); uint cellCol = v_effect.w & 0xffffu; uint cellRow = v_effect.w >> 16; diff --git a/shaders/ui.vert.glsl b/shaders/ui.vert.glsl index 5ec596fe..d23b609c 100644 --- a/shaders/ui.vert.glsl +++ b/shaders/ui.vert.glsl @@ -14,9 +14,10 @@ layout(location = 3) in vec3 a_bg; layout(location = 4) in vec4 a_panel_rect; layout(location = 5) in vec4 a_present_rect; // effect id, eased-progress float bits, pane serial, local row/column packed -// into one uint. The TWO high effect bits are flags — the frozen-old cell -// layer and a see-through cell background — so the id is what is left below -// them; integer transport preserves the exact cross-backend hash. +// into one uint. The THREE high effect bits are flags — the frozen-old cell +// layer, a see-through cell background and an opaque block-cursor fill — so +// the id is what is left below them; integer transport preserves the exact +// cross-backend hash. layout(location = 6) in uvec4 a_effect; layout(location = 0) out vec2 v_uv; @@ -55,7 +56,7 @@ void main() { v_cell_uv = vec2(0.0, 1.0); } - uint effect = a_effect.x & 0x3fffffffu; + uint effect = a_effect.x & 0x1fffffffu; if (effect == 1u || effect == 2u || effect == 5u) { // NDC y points up, so a top-left/bottom-right box has a NEGATIVE y // delta. Preserve that sign or every local y is mirrored/outside. |
