fix: guard shader pow() bases so a NaN pixel can no longer black out the frame
This commit is contained in:
@@ -236,14 +236,19 @@ export function createTraffic(
|
||||
float core = exp(-pow(abs(c.x) * 2.3, 6.0) - pow(abs(c.y) * 2.4, 6.0));
|
||||
float r = length(c * vec2(1.0, 1.6));
|
||||
float glow = core * 2.4 + exp(-r * r * 22.0) * 1.2 + exp(-r * r * 5.0) * 0.3;`);
|
||||
// Every pow() base is clamped: interpolation can land a fragment a hair
|
||||
// outside 0..1 (a quad edge-on or clipped by the near plane), and pow() of a
|
||||
// negative base is NaN. One NaN pixel in the HDR target is spread by the
|
||||
// bloom blurs and the lens streak over the whole frame: a one-frame black
|
||||
// flash (tests/unit/shader-pow-safety.test.ts).
|
||||
// Trails: thin, brightest at the lamp, fading over their length.
|
||||
const trailMaterial = additive(`
|
||||
float across = exp(-pow((vUv.x - 0.5) * 5.0, 2.0));
|
||||
float glow = across * pow(vUv.y, 1.6) * 0.8;`);
|
||||
float across = exp(-pow(abs(vUv.x - 0.5) * 5.0, 2.0));
|
||||
float glow = across * pow(clamp(vUv.y, 0.0, 1.0), 1.6) * 0.8;`);
|
||||
// Wet-road pools: long and soft, brightest at the vehicle.
|
||||
const poolMaterial = additive(`
|
||||
float across = exp(-pow((vUv.x - 0.5) * 3.2, 2.0));
|
||||
float glow = across * pow(vUv.y, 2.2) * 0.2;`);
|
||||
float across = exp(-pow(abs(vUv.x - 0.5) * 3.2, 2.0));
|
||||
float glow = across * pow(clamp(vUv.y, 0.0, 1.0), 2.2) * 0.2;`);
|
||||
|
||||
// Bodies: near-black coachwork that reads as a silhouette against the
|
||||
// horizon, with the fog glow on the roof, the reader's headlights on the
|
||||
@@ -321,12 +326,12 @@ export function createTraffic(
|
||||
? `// Rear window: glass reflects a lavender band of sky.
|
||||
float glass = rear * step(1.12, vLocal.y) * step(vLocal.z, -0.9);
|
||||
color = mix(color, vec3(0.05, 0.05, 0.12) + uSheen * 0.22 * smoothstep(1.2, 1.55, vLocal.y), glass);
|
||||
float lampBand = exp(-pow((vLocal.y - 0.92) / 0.18, 2.0));`
|
||||
float lampBand = exp(-pow(abs(vLocal.y - 0.92) / 0.18, 2.0));`
|
||||
: `// Box doors: a centre seam and two lock bars.
|
||||
float seam = 1.0 - smoothstep(0.02, 0.05, abs(vLocal.x));
|
||||
float bars = 1.0 - smoothstep(0.03, 0.06, abs(abs(vLocal.x) - 0.42));
|
||||
color *= 1.0 - rear * max(seam * 0.6, bars * 0.35);
|
||||
float lampBand = exp(-pow((vLocal.y - 1.3) / 0.2, 2.0));
|
||||
float lampBand = exp(-pow(abs(vLocal.y - 1.3) / 0.2, 2.0));
|
||||
// The under-run bar is a reflector strip: it answers the beam from far off.
|
||||
float bar = rear * step(0.42, vLocal.y) * step(vLocal.y, 0.56);
|
||||
color += vec3(1.0, 0.34, 0.22) * bar * headlightCone(vWorld) * smoothstep(18.0, 50.0, beamDistance) * (1.0 - smoothstep(180.0, 420.0, beamDistance)) * (0.2 + 1.4 * lift);`
|
||||
|
||||
Reference in New Issue
Block a user