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

commitace940dcf0d7bf2abc62f33ae79bb93a32018fd7
parent790dcd5a9d
authorLucas Galante <[email protected]>
date2026-08-25 12:28
droplet: continuous dome shading and a bottom-weighted rim caustic

The drop's normal now comes from a spherical-cap height field over the
silhouette (h = sqrt(2u - u²): vertical at the rim, flattening toward
the interior) instead of the plate roll's skirt-only tilt — the
diffuse rolls from lit shoulder to shaded belly across the ENTIRE
body, so the middle stops reading as a flat face inside a shaded
band. The fresnel rim crest is now weighted toward the bottom edge
(0.3x at the attach and sides, up to 1.5x on the lower arc): the
caustic line a hanging drop concentrates along its bottom, with a
quiet attach line.

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

 src/vk/shader2d.wgsl | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/src/vk/shader2d.wgsl b/src/vk/shader2d.wgsl
index d016ff5..76f080a 100644
--- a/src/vk/shader2d.wgsl
+++ b/src/vk/shader2d.wgsl
@@ -429,10 +429,21 @@ fn plate_shade(frag: vec2f, vcol: vec4f) -> vec4f {
         let t2 = max(rrect_clip.p_light.w, 0.001);
         let u = clamp(din / t2, 0.0, 1.0);
         let f = 1.0 - u;
-        let sv = g * roll_slope(f) * dome;
+        // Continuous dome: the drop is a spherical-cap height field over the
+        // silhouette — h = sqrt(2u - u²), vertical at the rim, flattening
+        // toward the interior — so the normal varies over the ENTIRE body
+        // and the diffuse rolls from lit shoulder to shaded belly instead of
+        // reading as a flat face inside a shaded band (the old roll_slope
+        // treatment, which only tilted the skirt).
+        let hdome = sqrt(max(2.0 * u - u * u, 1e-4));
+        let sv = g * ((1.0 - u) / hdome * dome);
         let n = normalize(vec3f(sv, 1.0));
         let diff = PLATE_AMBIENT + (1.0 - PLATE_AMBIENT) * max(dot(n, l), 0.0);
-        let extra = rrect_clip.p_mat.w * f * f * f;
+        // Rim crest weighted toward the BOTTOM edge (g.y > 0, y-down): a
+        // hanging drop concentrates transmitted light into a caustic along
+        // its lower arc, while the attach line stays quiet.
+        let down = clamp(g.y, 0.0, 1.0);
+        let extra = rrect_clip.p_mat.w * f * f * f * (0.3 + 1.2 * down * down);
         let shade = 1.0 + (diff / flat_shade - 1.0 + extra) * strength;
         let spec = roll_spec(sv);
         // Thin edges are clearer water; the deep interior densifies by the