shader: collapse palm chip background pass and refine dot rendering

This commit is contained in:
lenn
2026-07-07 16:35:19 +08:00
parent a04b903e96
commit 1e3cfdcf21

View File

@@ -582,48 +582,9 @@ fn vs_hand_palm_chip(vertex: DotVertexInput, instance: DotInstanceInput) -> Hand
@fragment @fragment
fn fs_hand_palm_chip(in: HandPalmChipVertexOutput) -> @location(0) vec4f { fn fs_hand_palm_chip(in: HandPalmChipVertexOutput) -> @location(0) vec4f {
// Inactive palm matrix: only independent dots, with no filled patch underneath. // The live palm-dot pass draws every chip cell, including the idle dots.
let panel = rounded_rect_alpha(in.local, 0.16, 0.050); // Keeping this background pass transparent prevents a second offset dot grid.
let inner = rounded_rect_alpha(in.local * vec2f(1.03, 1.03), 0.13, 0.062); return output_color(vec3f(0.0, 0.0, 0.0), 0.0);
let uv = clamp(in.local * 0.5 + vec2f(0.5, 0.5), vec2f(0.0, 0.0), vec2f(1.0, 1.0));
let patch_mask = smoothstep(0.0, 0.36, inner) * panel;
let grid = max(in.grid * 1.42, vec2f(1.0, 1.0));
let cell_uv = fract(uv * grid) - vec2f(0.5, 0.5);
let dot_dist = length(cell_uv);
let dot_aa = max(fwidth(dot_dist) * 1.5, 0.008);
let dots = 1.0 - smoothstep(0.135 - dot_aa, 0.135 + dot_aa, dot_dist);
let dot_glow = 1.0 - smoothstep(0.14, 0.28, dot_dist);
let visible_dots = dots * patch_mask;
let visible_glow = dot_glow * patch_mask;
// Synthetic low-level pressure only changes nearby dots; it does not fill the patch.
let horizontal = step(in.grid.y, in.grid.x);
let pressure_center = mix(vec2f(0.0, 0.0), vec2f(-0.10, 0.0), horizontal);
let pressure_scale = mix(vec2f(1.00, 0.82), vec2f(0.82, 1.00), horizontal);
let pressure_dist = length((in.local - pressure_center) * pressure_scale);
let pressure = (1.0 - smoothstep(0.06, 0.32, pressure_dist)) * patch_mask;
let pressure_hot = (1.0 - smoothstep(0.02, 0.14, pressure_dist)) * patch_mask;
let idle_dot_color = vec3f(0.18, 0.32, 0.38);
let active_dot_color = idle_dot_color;
let hot_dot_color = idle_dot_color;
let dot_color = mix(idle_dot_color, active_dot_color, pressure);
let color = dot_color * visible_dots * 1.25
+ hot_dot_color * visible_dots * pressure_hot * 0.85
+ active_dot_color * visible_glow * pressure * 0.14;
let alpha = clamp(
visible_dots * (0.46 + pressure * 0.38)
+ visible_dots * pressure_hot * 0.22
+ visible_glow * pressure * 0.045,
0.0,
0.96,
);
return output_color(color, alpha);
} }
@vertex @vertex
@@ -631,9 +592,8 @@ fn vs_hand_palm_dot(vertex: DotVertexInput, instance: DotInstanceInput) -> DotVe
let intensity = saturate(instance.style.x); let intensity = saturate(instance.style.x);
let shaped = smoothstep(0.0, 1.0, intensity); let shaped = smoothstep(0.0, 1.0, intensity);
// Palm chip pixels are deliberately smaller than fingertip beads so they read as a chip matrix.
let center = hand_image_uv_to_clip(instance.world_position.xy); let center = hand_image_uv_to_clip(instance.world_position.xy);
let pixel_size = u.glyph.x * mix(0.16, 0.30, shaped); let pixel_size = u.glyph.x * mix(0.22, 0.34, shaped);
let ndc_offset = vertex.local * vec2f(pixel_size / u.viewport.x, pixel_size / u.viewport.y) * 2.0; let ndc_offset = vertex.local * vec2f(pixel_size / u.viewport.x, pixel_size / u.viewport.y) * 2.0;
var out: DotVertexOutput; var out: DotVertexOutput;
@@ -646,17 +606,16 @@ fn vs_hand_palm_dot(vertex: DotVertexInput, instance: DotInstanceInput) -> DotVe
@fragment @fragment
fn fs_hand_palm_dot(in: DotVertexOutput) -> @location(0) vec4f { fn fs_hand_palm_dot(in: DotVertexOutput) -> @location(0) vec4f {
let intensity = saturate(in.intensity); let intensity = saturate(in.intensity);
let pixel = chip_pixel_alpha(in.local, 0.52, 0.070);
let glow = circle_alpha(in.local, 0.95, 0.22) * intensity * 0.36;
let cold = vec3f(0.070, 0.340, 0.360); let core = circle_alpha(in.local, 0.48, 0.07);
let halo = circle_alpha(in.local, 0.74, 0.14) * (0.10 + intensity * 0.26);
let idle = vec3f(0.060, 0.250, 0.320);
let gradient = sample_range_color(intensity); let gradient = sample_range_color(intensity);
let color = mix(cold, gradient, smoothstep(0.0, 0.20, intensity)) let color = mix(idle, gradient, smoothstep(0.0, 0.18, intensity))
* (0.58 + intensity * 1.04) * mix(0.78, 1.18, intensity);
+ gradient * glow * 0.72;
let alpha = max(pixel * (0.20 + intensity * 0.76), glow); return output_color(color, max(core, halo));
return output_color(color, alpha);
} }
@vertex @vertex