New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Software: Handle texture wrapping more accurately #9921
Conversation
bca5b9d
to
a839ab4
Compare
This comment has been minimized.
This comment has been minimized.
| coord = coord % (imageSize + 1); | ||
| coord = (coord < 0) ? imageSize + coord : coord; | ||
| // Per YAGCD's info on TX_SETMODE1_I0 (et al.), mirror "requires the texture size to be a power | ||
| // of two. (wrapping is implemented by a logical AND (SIZE-1))". So though this doesn't wrap | ||
| // nicely for non-power-of-2 sizes, that's how hardware does it. | ||
| coord = coord & (image_size - 1); | ||
| coord = (coord < 0) ? image_size - 1 + coord : coord; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The (coord < 0) case is no longer needed, as the bitwise and will always result in a positive value.
I suspect that this is also responsible for all of the rendering differences I mentioned above (and initially incorrectly attributed to size + 1), which should also bring the software renderer in line with the hardware renderers.
d85f035
to
f53ddfa
Compare
|
Hardware test results: These were done by editing object 306 in the hardware fifo player, editing Height = 191Leave 00119e8a unchanged as
Height = 192Change 00119e8a to
Height = 96Change 00119e8a to
*Repeat had some unusual behavior where one row changed each time it drew. Here's another image of it. The actual texture being drawn seems the same, apart from the places where no texture is drawn at all, so I think the wrapping logic is correct. It's important to note that the original issue I was trying to fix was from a mod that unintentionally had texture wrapping enabled when it should have been disabled; the buggy-looking wrapped appearance is what they should have gotten in Dolphin (and got when they later tested it on actual hardware). |
f53ddfa
to
bbf2c03
Compare
|
Notable differences (apart from just texture shifting):
|
This fixes various texture offsetting issues with negative texture coordinates (bringing the software renderer in line with the hardware renderers). It also handles the invalid wrap mode accurately (as was done for the hardware renderers in the previous commit). Lastly, it handles wrapping with non-power-of-2 texture sizes in a hardware-accurate way (which is somewhat broken looking, as games aren't supposed to use wrapping with non-power-of-2 sizes); this has not been done for the hardware renderers.
bbf2c03
to
fa9c43c
Compare
|
FifoCI detected that this change impacts graphical rendering. Here are the behavior differences detected by the system:
automated-fifoci-reporter |
|
It's important to note that Mirrored with height=96 produces a quite different result on hardware. |
|
Here are some additional images from the hardware fifoplayer: WrongTitle_191_192.7z.zip WrongTitle_96.7z.zip With height=96, when repeat is used there does seem to be some randomness (though it still matches the pattern behind it, as I found). With mirror, it seems to be consistent (though the different pattern from what Dolphin shows still exists). |
























See https://bugs.dolphin-emu.org/issues/12408. When texture wrapping is enabled, the texture size should be a power of two per libogc; yagcd mentions (near bp register 0x80) that repeat and mirror "[require] the texture size to be a power of two. (wrapping is implemented by a logical AND (SIZE-1))".
Although I initially targeted this at the the non-power-of-2 issue, it also impacts the software renderer when wrapping textures in negative coordinates (https://dolp.in/i11834/6 is an example). This is probably due to the modulus operator
%returning negative numbers for negative inputs (e.g.-1 % 4is-1), while using&gives positive values (e.g.-1 & (4-1)is3).I haven't implemented the non-power-of-2 stuff in the hardware backends, as the graphics APIs themselves handle texture wrapping in the sampling process. Dolphin could handle it manually in the pixel shader, but I suspect there would be a performance cost to it for something that basically no games do (though I haven't tried it and the performance impact may be minimal or it might even be faster due to allowing silly behavior for non-power-of-2 sizes). One other possible complication to implementing it on the hardware backends is custom textures, as those might not be a power-of-2 size and using a bitwise and might also get rid of fractional parts of coordinates which would break higher resolution textures (though these too may not be issues).
I did also find that setting the wrap mode to 3 (which is invalid) seems to behave the same as setting it to 0 (clamp). Dolphin previously treated it the same as 1 (repeat) instead; I've fixed that for both the hardware and software backends.