The check ANDs every CLUT entry, but took any common bit as proof that no
alpha is zero, so a white palette with alphas 0, 0x10, ... lost its alpha
test. Only the alpha bits count now. Ace Combat's subtitles become bit exact
against the PSP.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The auto level is the largest of the four UV gradients (du/dx, du/dy, dv/dx,
dv/dy) in texels per pixel, taken from the s and t planes, minus the pixel's
q, both through the GE's float-bits log2 (gpu/probe exp92: exact for affine
mappings at any rotation and anisotropy). Before, only du/dx and dv/dy from a
2x2 quad's differences counted. Under perspective (exp93) about 14% of
pixels are still a sixteenth of a level off.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
With separate specular lighting and color doubling, the GE doubles the
secondary color as well (gpu/probe exp86, exact for modulate, add and
replace).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A perspective u = s * R(q) keeps 24 significant bits, truncated, instead of
a float24's 16 (gpu/probe exp82: large UVs from a texture matrix, as NFS Most
Wanted uses). Through-mode points keep 15 bits of their UVs, as the UV planes
do for triangles (exp83, exp84).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The 8-bit fog of each vertex goes through the same plane as depth and color.
Bit exact on gpu/probe exp21 (all 9 cases, from 94-98%).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A pixel is lit when the line passes through its diamond and doesn't end inside
it, with points on the top corner, its two edges and the left corner counting
as inside (also where the line only touches the diamond). Exact for 313 of 320
random lines on gpu/probe exp72; a few ties at line ends still differ.
PPSSPP's DDA matched about 20%.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The texture matrix is summed like a position row, and projected texture
coordinates go through the same s, t, q planes as perspective ones, with q
the texture matrix's q over w. Points use the planes too. Bit exact on
gpu/probe exp64-65, except the normalized normal source, whose normalization
isn't matched.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Per pixel, from the interpolated q = 1/w: 16 + log2(slope) - log2(q), both
with the same float-bits log2, plus the bias. Bit exact on gpu/probe
exp58-60, including nearest level rounding.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sprites interpolate UVs with the same fixed point planes as triangles, and
texture coordinates become texels at 1/16 texel, truncated toward zero, also
in the sampler JIT. Bit exact on gpu/probe exp57 (through mode and transform
mode sprites, nearest and bilinear).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Both use the GE's fixed point depth plane. Color is screen-linear, also in
transform mode, with 8-bit channels as the plane values (gpu/probe exp54). For
perspective UVs, s = u * R(w), t and q = R(w) become 15-bit integers at the
triangle's largest exponent, go through the plane, and u = s * R(q) per pixel
(exp55-56, bit exact at 1/16 texel).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Bit exact against the PSP on every pixel of gpu/probe exp36-41 (over a million
pixels of large, small, steep and slanted triangles):
- Per triangle, the doubled area's 16-bit significand indexes a 256-segment
reciprocal table, linear over each segment's low 8 bits (measured for all
inputs; not the z/w table).
- The x and y depth gradients are fixed point, 14 fractional bits per
subpixel, from the exact edge cross products times that reciprocal.
- The plane is anchored at the leftmost vertex, or the rightmost when the long
edge (top to bottom) is strictly the right side of the triangle.
- Each pixel takes the plane at its center, floored.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
X and Y now go through the same float24 math as Z: clip coordinates from the
combined matrix (also when lighting needs the world position), the GE's
reciprocal, and the viewport offset added without guard bits, which around
2048 lands on the 1/16 subpixel grid. The 12.4 conversion truncates instead of
rounding up at 10/16.
Triangles are sampled exactly at pixel centers, not 1/16 before them, with left
and top edges inclusive. Sprites start at (x + 6) >> 4 horizontally and
(y + 7) >> 4 vertically and end at (v + 7) >> 4, and their 2x2 loop no longer
treats ties differently by pixel parity. Measured with gpu/probe; against PSP
replays, Coded Arms goes from MSE 33 to 26 and the Test Drive map from 17 to 7.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The GE converts the fog factor to 8 bits per vertex, min(floor(256 * f), 255),
and interpolates that linearly in screen space. Clamping after interpolation
instead was up to 127 levels off on triangles that cross the fog range.
Measured with gpu/probe; points and wacky values still match exactly.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Without SSE or NEON, triangle pixels got the secondary color in place of
the primary one plus it, so lit triangles came out black. It showed as
the "unexplained" known failures on riscv64 and loongarch64, and broke
the new gpu/lighting/shademap there. Reproduced on arm64 by building
without NEON.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Blending is slow, and often games do effects like smoke, sun, etc. that
has a lot of zero alpha in them. Many games do this with alpha testing
off, which is cheap compared to blending.
Since we're already checking the CLUT, we can tell if it doesn't contain
zero alpha, in which case a != 0 test will never fail. This is actually
pretty common, even when texture alpha is not always FF.
Might be some other ways, like doing this directly in a vertex reader.
Also am thinking about doing things regarding UVs or positions.
Flags not yet used, keeping separate for perf checks.