fix(render): transparency toggle also governs hatches, text and fills

Only the wire shaders read transparency_enable; hatch (solid, gradient
and pattern), text and 3D/fill-triangle fragments always drew the
entity's alpha, so turning Show Transparency off left them see-through.

Fixes #1529

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hakan SevenandClaude Opus 5.5 committed 2026-09-29 09:09:42 +03:00
1 parent 5e8b86df65
commit 80372abf2c
6 files changed
+24 -14

No files matched your search

+1 -1
View File
@@ -41,5 +41,5 @@ fn vs_main(v: VertexIn) -> VertexOut {
@fragment @fragment
fn fs_main(in: VertexOut) -> @location(0) vec4<f32> { fn fs_main(in: VertexOut) -> @location(0) vec4<f32> {
return in.color; return vec4<f32>(in.color.rgb, select(1.0, in.color.a, u.transparency_enable > 0.5));
} }
+1 -1
View File
@@ -72,5 +72,5 @@ fn fs_main(in: VertOut) -> @location(0) vec4<f32> {
if alpha <= 0.0 { if alpha <= 0.0 {
discard; discard;
} }
return vec4<f32>(in.color.rgb, in.color.a * alpha); return vec4<f32>(in.color.rgb, select(1.0, in.color.a, u.transparency_enable > 0.5) * alpha);
} }
+1 -1
View File
@@ -50,5 +50,5 @@ fn vs_main(v: VertexIn) -> VertexOut {
@fragment @fragment
fn fs_main(in: VertexOut) -> @location(0) vec4<f32> { fn fs_main(in: VertexOut) -> @location(0) vec4<f32> {
return in.color; return vec4<f32>(in.color.rgb, select(1.0, in.color.a, u.transparency_enable > 0.5));
} }
+10 -5
View File
@@ -218,6 +218,11 @@ fn check_family(
// ── Fragment shader ────────────────────────────────────────────────────── // ── Fragment shader ──────────────────────────────────────────────────────
// Entity transparency shows only while transparency display is on.
fn shown(color: vec4<f32>) -> vec4<f32> {
return vec4<f32>(color.rgb, select(1.0, color.a, u.transparency_enable > 0.5));
}
@fragment fn fs_main(v: VOut) -> @location(0) vec4<f32> { @fragment fn fs_main(v: VOut) -> @location(0) vec4<f32> {
// Taken here, in uniform control flow — see check_family. // Taken here, in uniform control flow — see check_family.
let ddx_xz = dpdx(v.xz); let ddx_xz = dpdx(v.xz);
@@ -227,7 +232,7 @@ fn check_family(
// Mode dispatch. // Mode dispatch.
if inst.mode == 1u { if inst.mode == 1u {
return inst.color; return shown(inst.color);
} else if inst.mode == 2u { } else if inst.mode == 2u {
let proj = v.xz.x * inst.grad_cos + v.xz.y * inst.grad_sin; let proj = v.xz.x * inst.grad_cos + v.xz.y * inst.grad_sin;
var t = clamp((proj - inst.grad_min) / inst.grad_range, 0.0, 1.0); var t = clamp((proj - inst.grad_min) / inst.grad_range, 0.0, 1.0);
@@ -241,7 +246,7 @@ fn check_family(
if (inst.grad_kind & 16u) != 0u { if (inst.grad_kind & 16u) != 0u {
t = 1.0 - t; t = 1.0 - t;
} }
return mix(inst.color, inst.color2, t); return shown(mix(inst.color, inst.color2, t));
} else if inst.mode == 3u { } else if inst.mode == 3u {
// Radial gradient: centre is (grad_cos, grad_sin), radius is grad_range. // Radial gradient: centre is (grad_cos, grad_sin), radius is grad_range.
let d = length(v.xz - vec2<f32>(inst.grad_cos, inst.grad_sin)); let d = length(v.xz - vec2<f32>(inst.grad_cos, inst.grad_sin));
@@ -255,7 +260,7 @@ fn check_family(
} }
// Radial stops run OUTSIDE-IN: colour 1 at the rim, colour 2 at the // Radial stops run OUTSIDE-IN: colour 1 at the rim, colour 2 at the
// centre; the INV bit above swaps them back. // centre; the INV bit above swaps them back.
return mix(inst.color2, inst.color, t); return shown(mix(inst.color2, inst.color, t));
} }
// Pattern LOD. Keep every family visible until all family spacings // Pattern LOD. Keep every family visible until all family spacings
@@ -274,7 +279,7 @@ fn check_family(
} }
} }
if all_families_subpixel { if all_families_subpixel {
return inst.color; return shown(inst.color);
} }
// Pattern evaluation. // Pattern evaluation.
@@ -283,7 +288,7 @@ fn check_family(
for (var i = 0u; i < inst.family_count; i++) { for (var i = 0u; i < inst.family_count; i++) {
let fam = families[inst.family_offset + i]; let fam = families[inst.family_offset + i];
if check_family(v.xz, ddx_xz, ddy_xz, fam, cos_off, sin_off, inst.scale) { if check_family(v.xz, ddx_xz, ddy_xz, fam, cos_off, sin_off, inst.scale) {
return inst.color; return shown(inst.color);
} }
} }
discard; discard;
+10 -5
View File
@@ -200,6 +200,11 @@ fn check_family(
// ── Fragment shader ──────────────────────────────────────────────────────── // ── Fragment shader ────────────────────────────────────────────────────────
// Entity transparency shows only while transparency display is on.
fn shown(color: vec4<f32>) -> vec4<f32> {
return vec4<f32>(color.rgb, select(1.0, color.a, u.transparency_enable > 0.5));
}
@fragment fn fs_main(v: VOut) -> @location(0) vec4<f32> { @fragment fn fs_main(v: VOut) -> @location(0) vec4<f32> {
// Taken here, in uniform control flow — see check_family. // Taken here, in uniform control flow — see check_family.
let ddx_xz = dpdx(v.xz); let ddx_xz = dpdx(v.xz);
@@ -209,7 +214,7 @@ fn check_family(
let gk = (h.mode >> 8u) & 15u; let gk = (h.mode >> 8u) & 15u;
let ginv = ((h.mode >> 8u) & 16u) != 0u; let ginv = ((h.mode >> 8u) & 16u) != 0u;
if base_mode == 1u { if base_mode == 1u {
return h.color; return shown(h.color);
} else if base_mode == 2u { } else if base_mode == 2u {
let proj = v.xz.x * h.grad_cos + v.xz.y * h.grad_sin; let proj = v.xz.x * h.grad_cos + v.xz.y * h.grad_sin;
var t = clamp((proj - h.grad_min) / h.grad_range, 0.0, 1.0); var t = clamp((proj - h.grad_min) / h.grad_range, 0.0, 1.0);
@@ -222,7 +227,7 @@ fn check_family(
if ginv { if ginv {
t = 1.0 - t; t = 1.0 - t;
} }
return mix(h.color, h.color2, t); return shown(mix(h.color, h.color2, t));
} else if base_mode == 3u { } else if base_mode == 3u {
// Radial gradient: centre is (grad_cos, grad_sin), radius is grad_range. // Radial gradient: centre is (grad_cos, grad_sin), radius is grad_range.
let d = length(v.xz - vec2<f32>(h.grad_cos, h.grad_sin)); let d = length(v.xz - vec2<f32>(h.grad_cos, h.grad_sin));
@@ -234,7 +239,7 @@ fn check_family(
t = 1.0 - t; t = 1.0 - t;
} }
// Radial stops run outside-in (colour 2 at the centre) — see hatch.wgsl. // Radial stops run outside-in (colour 2 at the centre) — see hatch.wgsl.
return mix(h.color2, h.color, t); return shown(mix(h.color2, h.color, t));
} }
// Keep every family visible until all family spacings project below 2 px, // Keep every family visible until all family spacings project below 2 px,
@@ -252,7 +257,7 @@ fn check_family(
} }
} }
if all_families_subpixel { if all_families_subpixel {
return h.color; return shown(h.color);
} }
let cos_off = cos(h.angle_offset); let cos_off = cos(h.angle_offset);
@@ -260,7 +265,7 @@ fn check_family(
for (var i = 0u; i < h.n_families; i++) { for (var i = 0u; i < h.n_families; i++) {
let fam = load_family(i); let fam = load_family(i);
if check_family(v.xz, ddx_xz, ddy_xz, fam, cos_off, sin_off, h.scale) { if check_family(v.xz, ddx_xz, ddy_xz, fam, cos_off, sin_off, h.scale) {
return h.color; return shown(h.color);
} }
} }
discard; discard;
+1 -1
View File
@@ -82,5 +82,5 @@ fn fs_main(in: VertOut) -> @location(0) vec4<f32> {
if alpha <= 0.0 { if alpha <= 0.0 {
discard; discard;
} }
return vec4<f32>(in.color.rgb, in.color.a * alpha); return vec4<f32>(in.color.rgb, select(1.0, in.color.a, u.transparency_enable > 0.5) * alpha);
} }