diff --git a/src/duskpsp/display/render/renderpsp.c b/src/duskpsp/display/render/renderpsp.c index 23667285..aaf4049f 100644 --- a/src/duskpsp/display/render/renderpsp.c +++ b/src/duskpsp/display/render/renderpsp.c @@ -225,10 +225,16 @@ static void draw3DQuad(const ropquad3d_t *q) { : &pspTexTable[0]; uint32_t abgr = toABGR(q->tint); /* UV in 0-255 range → scale to texel coords the same way draw2DSprite does. */ - float u0 = (q->uvX / 255.0f) * (float)e->w; - float v0 = (q->uvY / 255.0f) * (float)e->h; - float u1 = ((q->uvX + q->uvW) / 255.0f) * (float)e->w; - float v1 = ((q->uvY + q->uvH) / 255.0f) * (float)e->h; + /* PSP GU in GU_TRANSFORM_3D treats UV as normalized: 1.0 = declared texture + * image width (the power-of-2 size passed to sceGuTexImage). Scale our + * [0, logicalW] UV range down to [0, logicalW/declaredW] so the full logical + * texture maps across the quad without tiling. */ + float texWf = (float)texturePow2Height(e->w); + float texHf = (float)texturePow2Height(e->h); + float u0 = (q->uvX / 255.0f) * ((float)e->w / texWf); + float v0 = (q->uvY / 255.0f) * ((float)e->h / texHf); + float u1 = ((q->uvX + q->uvW) / 255.0f) * ((float)e->w / texWf); + float v1 = ((q->uvY + q->uvH) / 255.0f) * ((float)e->h / texHf); float cx = (float)q->cx, cy = (float)q->cy, cz = (float)q->cz; float rx = (float)q->rx, ry = (float)q->ry, rz = (float)q->rz;