Files
psxrecomp/runtime
Matthew Stanley e86099f46e gpu gl/vk: fix mirrored-2D uv sampling (MMX6 sprite slivers)
Modern-GPU center-sampled interpolation vs the PS1 DDA's top-left-corner
latch: the sample-grid shift (u_shift = 0.5/S - 1/64) makes floor(uv) land
on the exact PS1 texel for FORWARD axis-aligned mappings, but MIRRORED ones
(u or v decreasing along their screen axis - X/Y-flipped 2D sprites, e.g.
right-facing MMX entity quads whose cels are stored facing left) interpolate
1/64 short of each integer and floor one texel LOW. That painted the cel's
never-sampled edge column/row (opaque body texels) as detached 1px slivers
at quad seams: stray sprite-colored lines right of X when facing right, a
pink line under the rolling wheel mechaniloids. The old tri_uv_limits
comment explicitly 'accepted' this.

Fix = the Beetle-PSX / parallel-psx Calc_UVOffsets_Adjust_Verts model:
bump the prim's uv by +1 along the decreasing axis (tri_uv_mirror_offset,
applied in the GL and VK poly paths before limits are derived). This also
puts the max-uv vertex back on the exclusive raster edge, so the existing
unconditional max back-off in tri_uv_limits is correct for both directions.
Forward mappings are untouched (no regression surface for the original
Tomba seam fix). The software renderer's native DDA truncates exactly like
the PS1 and needs no compensation; its limits function only feeds the
bilinear neighbour clamp (comment clarified).

Verified on MMX6 attract demo (deterministic boot): pre-fix GL showed
detached X-palette 1px columns at quad seam x=173/175/179/181 (frames
~2088/2250) while software was clean; post-fix GL matches software and
user-confirmed clean live. Residual detector hits classified via GP0 ring
dumps as legit charge-spark effect tiles.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 15:40:32 -07:00
..