rickomax / psxprev

PSXPREV - Playstation (PSX) Files Previewer/Extractor
BSD 2-Clause "Simplified" License
200 stars 10 forks source link

Texture UVs are slightly offset, at least for HMD #83

Closed trigger-segfault closed 1 year ago

trigger-segfault commented 1 year ago

I noticed this issue when implementing texture tiling, because I was wondering whether texture wrap size needed to be divided by 256 instead of 255 (and also have 1 added). When I changed all UV coordinates to be divided by 256f instead of 255f, I noticed that the alignment issues were no longer present (with some exceptions). All alignment issues seem to be an issue of off-by-1 pixel, usually only in one direction. This is a very confusing issue, and it's likely that this either A) won't be fixed, or B) can't be fixed because of limitations and GPU behavior that differ between modern computers on the PS1. Part of the issue with just changing all division to 256f is that you get texture glitching near pixel boundaries.

Screenshots:

Figure A: Showcasing issues with the LRR Tunnel Transport *Figure A-1. Textures as seen in the original game.* ![PSXPrev_TextureUVOffsetIssueA1](https://github.com/rickomax/psxprev/assets/9752430/b2f703ad-2794-4f80-afa4-8ce0cf8e851b) *Figure A-2. Textures as currently seen in PSXPrev.* ![PSXPrev_TextureUVOffsetIssueA2](https://github.com/rickomax/psxprev/assets/9752430/c939b919-153a-46b9-b0c1-07267ee90d1f) *Figure A-3. Textures in PSXPrev with the 256f fix.* ![PSXPrev_TextureUVOffsetIssueA3](https://github.com/rickomax/psxprev/assets/9752430/80fbef28-73a4-498a-a6e7-3c5edbeeb396)
Figure B: Showcasing issues with the LRR Crystal Refinery *Figure B-1. Textures as seen in the original game.* ![PSXPrev_TextureUVOffsetIssueB1](https://github.com/rickomax/psxprev/assets/9752430/0acd0c1c-93d4-4c02-9597-ba31cec44ed4) *Figure B-2. Textures as currently seen in PSXPrev.* ![PSXPrev_TextureUVOffsetIssueB2](https://github.com/rickomax/psxprev/assets/9752430/8f455275-a4af-4928-9a33-0b0ab84dd88e) *Figure B-3. Textures in PSXPrev with the 256f fix. Issues that still persist are highlighted in lime green.* ![PSXPrev_TextureUVOffsetIssueB3](https://github.com/rickomax/psxprev/assets/9752430/3f900816-7446-4585-bc11-c14f3cf0828e)

Figure C. Glitching that appears near pixel boundaries with the 256f fix. PSXPrev_TextureUVOffsetIssueC

trigger-segfault commented 1 year ago

So this issue occurs when a face has UVs where either all U coordinates or all V coordinates are identical, effectively making it a 1D line. It's possible to use the 256f fix and prevent this tearing by checking individual triangles for identical U/V coordinates, and if they are all identical, then increment one of them by 1f / 256f.

void Correct1DUV(Triangle triangle)
{
    for (var c = 0; c < 2; c++)
    {
        if (triangle.Uv[0][c] == triangle.Uv[1][c] && triangle.Uv[1][c] == triangle.Uv[2][c])
        {
            triangle.Uv[2][c] += 1f / 256f;
        }
    }
}