RT: abs() the projection term -- Y-flip made it negative and the guard ate it
RAY_FOOTPRINT_X/Y were ~1e6 too large, so every textureGrad in a custom hit group
took the coarsest mip. Measured on map_dc_level against the rasterizer (real
derivatives, correct by construction): median LOD 6.000 at the clamp ceiling,
where raster selects 0.494.
float rt_px = 2.0 * rt_t / max(projection_matrix[1][1] * read_viewport_size.y, 1e-6);
projection_matrix[1][1] is NEGATIVE under Vulkan. update_ubo builds
projection = correction * cam_projection, and Projection::set_depth_correction
sets columns[1][1] = flip_y ? -1 : 1 (projection.cpp:796), so the term is about
-1/tan(fovy/2). The product goes negative, max(negative, 1e-6) returns the
epsilon, and the footprint explodes. The guard was meant to stop a divide by
zero; instead it silently replaced a valid input.
This is why hyper-games #11 §4.6 saw the ray-cone change over-blur every Quake
texture, and why that session was right to revert it: the idea was sound, the
input was garbage. It also explains the probe that read "P11 not populated" in
BOTH renderers -- a > 0.001 test on a legitimately negative number.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
234159eac78db1c354a364a1e1ff060f63a5a668
by plankatron <fleeky@gmail.com> · 2026-07-31T21:58:13.000Z