mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-27 18:52:11 -04:00
9b3c38a379
Adds a GL_ALWAYS override (pgxp_depth always=1) that keeps depth WRITES but
never rejects a fragment. That separates "the test is discarding this geometry"
from "this geometry never got drawn", which no amount of staring at a depth
readout settles.
Ship coverage over the same six sampled frames:
depth OFF mean 1.41
depth ON, LEQUAL mean 0.52
depth ON, GL_ALWAYS mean 1.40
GL_ALWAYS restores the ship exactly to the depth-off result, so the geometry is
drawn and the depth is written; only the comparison differs. Something writes
NEARER depth at the ship's own pixels before it draws.
The cause is the interpolation, not the values. These vertices are already in
screen space, so gl_Position carries w = 1, and the rasteriser therefore
interpolates z LINEARLY across the triangle in screen space. Perspective depth
is hyperbolic. On a ground-plane triangle at a glancing angle -- exactly what a
race track is -- the linearly-interpolated interior reads far nearer than it
really is and swallows anything standing on it. This also explains why the
per-vertex numbers looked right all along: at znear=64 the ship's median depth
is 219 against 227 for the track around it, correctly nearer, because the
VERTICES are fine and only the triangle interior is wrong.
The fix is to give each vertex a real w -- the view-space Z the census already
proves we have -- and emit gl_Position = vec4(xyz * w, w), so the hardware
interpolates 1/w and depth comes out hyperbolic. That is the view-space Z
reconstruction this needed from the start. It is not a drop-in: the perspective-
UV path does its own manual correction via a_q precisely BECAUSE w is 1 today,
so both have to move together or UVs get corrected twice.
Depth stays OFF until that lands.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>