mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 18:25:35 -04:00
gpu gl/vk: mirrored-2D uv compensation for the RECT path too
Thee86099ffix put the Beetle Calc_UVOffsets mirrored-uv bump in the textured-POLY path only — but gpu.c's axis-aligned-quad fast path converts mirrored quads (X/Y-flipped 2D sprites, e.g. every right-facing MMX entity cel) into gr_draw_textured_rect_scaled calls with u0>u1 / v0>v1, so they enter gpu_textured_rect and never see the poly compensation. That is why the sprite slivers persisted on X (worst facing right / crouching) aftere86099f: the visible producers were all rect-path prims. Fix: same +1 bump along each decreasing uv axis in gpu_textured_rect (GL and VK), with the sampling bounds tightened to [min, max-1] post-bump (max is the exclusive edge in both directions). Forward rects are unaffected (bump is a no-op; bounds identical to before). Frame-exact verification (deterministic attract, frame 2850, X idle facing right): pre-fix GL vs software full-frame diff = 3707 px spread across the sprite area; post-fix = 0 px in the entire gameplay area (the only remaining diff is the attract logo overlay blink-phase offset caused by the known GL blend-rounding timeline fork, tracked separately). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1548,12 +1548,23 @@ static void gpu_textured_rect(int x,int y,int w,int h,
|
||||
if (w <= 0 || h <= 0) return;
|
||||
float mr=s_mod_r/255.0f, mg=s_mod_g/255.0f, mb=s_mod_b/255.0f;
|
||||
float col[9]={mr,mg,mb, mr,mg,mb, mr,mg,mb};
|
||||
/* uv sampling bounds: forward mappings sample [u0, u1-1] (u1 is the
|
||||
* exclusive edge); mirrored ones keep the full inclusive range. Crossing
|
||||
* a 256 boundary means page wrap — widen to the full page. */
|
||||
/* Mirrored-2D compensation, rect form (Beetle Calc_UVOffsets model —
|
||||
* see tri_uv_mirror_offset). gpu.c routes axis-aligned MIRRORED quads
|
||||
* (X/Y-flipped 2D sprites, e.g. right-facing MMX entities) through THIS
|
||||
* path as scaled rects with u0>u1 / v0>v1 — they never reach the poly
|
||||
* path. Center-sampled interpolation with the -1/64 grid shift floors
|
||||
* one texel LOW along a decreasing axis (the PS1 DDA latches the
|
||||
* top-left corner value), painting the cel's never-sampled edge texels
|
||||
* as detached slivers at cell seams. Bump the uv range +1 along each
|
||||
* decreasing axis so floor() lands on the exact PS1 texel. */
|
||||
if (u1 < u0) { u0++; u1++; }
|
||||
if (v1 < v0) { v0++; v1++; }
|
||||
/* uv sampling bounds: post-bump, the max-uv end is the exclusive edge
|
||||
* in BOTH directions — sample range is [min, max-1]. Crossing a 256
|
||||
* boundary means page wrap — widen to the full page. */
|
||||
int lim[4];
|
||||
lim[0] = u0 < u1 ? u0 : u1; lim[2] = u0 < u1 ? u1 - 1 : u0;
|
||||
lim[1] = v0 < v1 ? v0 : v1; lim[3] = v0 < v1 ? v1 - 1 : v0;
|
||||
lim[0] = u0 < u1 ? u0 : u1; lim[2] = (u0 < u1 ? u1 : u0) - 1;
|
||||
lim[1] = v0 < v1 ? v0 : v1; lim[3] = (v0 < v1 ? v1 : v0) - 1;
|
||||
if (lim[2] < lim[0]) lim[2] = lim[0];
|
||||
if (lim[3] < lim[1]) lim[3] = lim[1];
|
||||
if ((lim[0] >> 8) == (lim[2] >> 8)) { lim[0] &= 255; lim[2] &= 255; }
|
||||
|
||||
@@ -2633,9 +2633,15 @@ static void gpu_textured_rect(int x,int y,int w,int h, int u0,int v0,int u1,int
|
||||
if (w <= 0 || h <= 0) return;
|
||||
float mr = s_mod_r/255.0f, mg = s_mod_g/255.0f, mb = s_mod_b/255.0f;
|
||||
float col[9] = { mr,mg,mb, mr,mg,mb, mr,mg,mb };
|
||||
/* Mirrored-2D compensation, rect form — see the GL backend's
|
||||
* gpu_textured_rect: axis-aligned mirrored quads arrive here as scaled
|
||||
* rects with u0>u1 / v0>v1 and floor one texel low under center-sampled
|
||||
* interpolation; bump the range +1 along each decreasing axis. */
|
||||
if (u1 < u0) { u0++; u1++; }
|
||||
if (v1 < v0) { v0++; v1++; }
|
||||
int lim[4];
|
||||
lim[0] = u0 < u1 ? u0 : u1; lim[2] = u0 < u1 ? u1 - 1 : u0;
|
||||
lim[1] = v0 < v1 ? v0 : v1; lim[3] = v0 < v1 ? v1 - 1 : v0;
|
||||
lim[0] = u0 < u1 ? u0 : u1; lim[2] = (u0 < u1 ? u1 : u0) - 1;
|
||||
lim[1] = v0 < v1 ? v0 : v1; lim[3] = (v0 < v1 ? v1 : v0) - 1;
|
||||
if (lim[2] < lim[0]) lim[2] = lim[0];
|
||||
if (lim[3] < lim[1]) lim[3] = lim[1];
|
||||
if ((lim[0] >> 8) == (lim[2] >> 8)) { lim[0] &= 255; lim[2] &= 255; } else { lim[0] = 0; lim[2] = 255; }
|
||||
|
||||
Reference in New Issue
Block a user