Triangle LED Hero
Analytic edge-glow triangle with LED emitters, floor radiance, and interactive color deploy. Canvas-scoped pointer input drives the lighting while an accessible mode selector chooses highlighted edges.
index.tsxcontrols.tsxtypes.tsrenderer.tsscene-renderer.tslight-sources-raw.tslight-sources-pass.tsled-buffer.tssettings.tshero-frame-state.tsdirect-triangle-raycast.tsvalue-noise.tstriangle-hit.tssim-sizing.tsshaders/light-sources.wgslshaders/led-emitters.wgslshaders/direct-triangle-raycast.wgslshaders/floor-noise.wgslshaders/color-utils.wgslshaders/geometry.wgslshaders/floor-falloff.wgslshaders/hash.wgslshaders/themes/dark/main-scene-floor.wgslshaders/themes/light/main-scene-floor.wgsl
struct Config {
resolution: vec2f,
time: f32,
floor_albedo: f32,
brush: vec4f,
colour: vec4f,
tunables: vec4f,
triangle: vec4f,
options: vec4f,
led_clip: vec4f,
};
struct Led {
pos_brightness: vec4f,
color: vec4f,
};
@group(0) @binding(0) var<uniform> cfg: Config;
@group(0) @binding(1) var<storage, read> leds: array<Led>;
struct VSOut { @builtin(position) pos: vec4f };
const LED_COUNT: u32 = 72u;
// Keep the black occluder safely inside the visible triangle mesh.
const OCCLUDER_INSET_PX: f32 = 4.0;
@vertex fn vs_main(@builtin(vertex_index) vi: u32) -> VSOut {
var p = array<vec2f, 3>(vec2f(-1.0, -3.0), vec2f(-1.0, 1.0), vec2f(3.0, 1.0));
var out: VSOut; out.pos = vec4f(p[vi], 0.0, 1.0); return out;
}
fn signed_triangle_area(a: vec2f, b: vec2f, p: vec2f) -> f32 {
let edge = b - a;
return edge.x * (p.y - a.y) - edge.y * (p.x - a.x);
}
fn inside_triangle(p: vec2f, a: vec2f, b: vec2f, c: vec2f) -> bool {
let side0 = signed_triangle_area(a, b, p);
let side1 = signed_triangle_area(b, c, p);
let side2 = signed_triangle_area(c, a, p);
return (side0 <= 0.0 && side1 <= 0.0 && side2 <= 0.0) || (side0 >= 0.0 && side1 >= 0.0 && side2 >= 0.0);
}
fn segment_distance(p: vec2f, a: vec2f, b: vec2f) -> f32 {
let pa = p - a;
let ba = b - a;
let h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
return length(pa - ba * h);
}
fn triangle_sdf(p: vec2f, a: vec2f, b: vec2f, c: vec2f) -> f32 {
let edge_dist = min(segment_distance(p, a, b), min(segment_distance(p, b, c), segment_distance(p, c, a)));
return select(edge_dist, -edge_dist, inside_triangle(p, a, b, c));
}
@fragment fn fs_main(in: VSOut) -> @location(0) vec4f {
let pixel = in.pos.xy;
let top = vec2f(cfg.triangle.x, cfg.triangle.y - cfg.triangle.z);
let left = vec2f(cfg.triangle.x - cfg.triangle.w, cfg.triangle.y + cfg.triangle.z * 0.5);
let right = vec2f(cfg.triangle.x + cfg.triangle.w, cfg.triangle.y + cfg.triangle.z * 0.5);
let tri_dist = triangle_sdf(pixel, top, left, right);
// Optionally fill the canonical triangle interior as a black non-emissive surface/occluder.
// LED RGB is overlaid by the generated emitter mesh after this SDF prepass.
let render_black_occluder = cfg.options.x > 0.5;
var best_led_dist = 1e6;
for (var i = 0u; i < LED_COUNT; i = i + 1u) {
let led = leds[i].pos_brightness;
let delta = pixel - led.xy;
let edge_dir = vec2f(cos(led.w), sin(led.w));
let edge_normal = vec2f(-edge_dir.y, edge_dir.x);
let led_local = vec2f(dot(delta, edge_dir), dot(delta, edge_normal));
let led_half_length = cfg.options.z;
let led_half_thickness = cfg.options.w;
let led_dist = max(
abs(led_local.x) - led_half_length,
abs(led_local.y) - led_half_thickness
);
// triangle_sdf is negative inside; positive inset moves only the LED SDF boundary inward.
let led_clip_dist = tri_dist + cfg.led_clip.y;
best_led_dist = min(best_led_dist, max(led_dist, led_clip_dist));
}
// triangle_sdf is negative inside; adding 4px moves only the black occluder boundary inward.
let inset_occluder_dist = tri_dist + OCCLUDER_INSET_PX;
let occluder_dist = select(1e6, inset_occluder_dist, render_black_occluder);
let best_dist = min(best_led_dist, occluder_dist);
// The fullscreen pass initializes the SDF/occluder contract. LED RGB is
// written afterward by the generated emitter mesh, including split corner caps
// that meet on each triangle-vertex bisector.
return vec4f(vec3f(0.0), best_dist);
}