git.lucas.co / cce-ui
GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git

commit978adda780b19f6bdada7167061ec1d0d2082fe0
parente955afb198
authorLucas Galante <[email protected]>
date2026-07-30 13:56
fix: scene light is azimuthal wrap-shaded — a vertical light anchors nothing

The first lighting pass chose a near-vertical light with a two-sided
|dot|: the resulting brightness pattern is latitude-dominated and
180-degree symmetric — INVARIANT under a yaw orbit — so it added a strong
shading cue that cannot move while orbiting, reading as the scene turning
with the camera in every mode (worse than unlit). The light is now
strongly azimuthal, wrap-shaded without |dot| (the fill pass culls to
front faces, so the derivative normal's sign is stable): the lit side is
pinned to a world azimuth the orbit visibly sweeps across.

Co-Authored-By: Claude Fable 5 <[email protected]>

 src/vk/scene3d.wgsl | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/src/vk/scene3d.wgsl b/src/vk/scene3d.wgsl
index 035451a..64cbc66 100644
--- a/src/vk/scene3d.wgsl
+++ b/src/vk/scene3d.wgsl
@@ -89,9 +89,16 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
     // the camera without it. Two-sided so unculled back faces stay sane.
     if (in.lit > 0.5) {
         let n = normalize(cross(dpdx(in.world), dpdy(in.world)));
-        let l = normalize(vec3f(-0.45, 0.8, 0.35));
-        let d = abs(dot(n, l));
-        rgb = rgb * (0.62 + 0.38 * d);
+        // A strongly AZIMUTHAL light, wrap-shaded. A near-vertical light (or a
+        // two-sided |dot|) yields a latitude-dominated / 180-degree-symmetric
+        // brightness pattern — invariant under a yaw orbit, which reads as the
+        // scene turning with the camera. The horizontal component pins the lit
+        // side to a world azimuth the orbit visibly sweeps across; the wrap
+        // term keeps a soft floor without |dot|'s ambiguity (the fill pass
+        // culls to front faces, so the derivative normal's sign is stable).
+        let l = normalize(vec3f(-0.55, 0.45, 0.7));
+        let d = clamp(dot(n, l) * 0.5 + 0.5, 0.0, 1.0);
+        rgb = rgb * (0.55 + 0.45 * d);
     }
     return vec4f(rgb, cov);
 }