rust3ds / citro3d-rs

Rust bindings and safe wrappers for citro3d
https://rust3ds.github.io/citro3d-rs
12 stars 10 forks source link

Texenvs need to stay alive until they're drawn #36

Open ian-h-chamberlain opened 6 months ago

ian-h-chamberlain commented 6 months ago

Yeah, I saw that a little while ago. Unfortunately, the main bit of rendering a model it doesn't touch, textures, is the bit I'm having difficulty with. I've successfully got a shape with a texture, but I find myself hopelessly lost trying to understand how the texture pipeline is supposed to work and I had to go a fair bit against my understanding of how it should work in order to get two faces with two different textures. Please enjoy this square, which took me about 9 hours to get textured:

https://github.com/rust3ds/citro3d-rs/assets/24824597/c7a0e319-23b7-452a-8ef5-7a2f3179dece

(Sorry for the terrible recording quality. I should have turned down my screen brightness first.) The problem I'm having is that the texture pipeline seems to persist state across draw calls (Instance::draw_arrays calls, really), even when I think it shouldn't be - first, enabling textures for only the first face and resetting the TexEnv pipeline for the second did nothing, giving me a lovely yellow square (texture coordinates (0.0, 0.0) on Bowser's face) on the back; and second, using two separate textures for the two sides gave me Peach on both sides, for some reason (the Peach texture got used for both sides instead of only the second side, as if the GPU were batching the draws and preserving only the last-written texture). I worked around the issue by merging the textures into one, using it for both draw calls, and adjusting the texture coordinates to match. I suppose I can technically deal with this by merging all the textures for everything that's supposed to be drawn on one frame into one giant texture and using that for every shape that frame, but it feels like I'm misunderstanding something fundamental about how textures are supposed to work. Either that or it's a bug. (By the way, having a safe wrapper for draw_elements would be pretty handy in the future for optimising the number of vertices.)


My friend figured it out, and in retrospect it's sort of obvious - textures have to be alive until they're drawn, and if they're freed before the end of the frame, strange things happen. TexEnvs still don't work how I think they do, but at least I can draw more than one texture at a time now.

Originally posted by @Jhynjhiruu in https://github.com/rust3ds/citro3d-rs/issues/35#issuecomment-1871732945

newdev8 commented 3 months ago

Hey @ian-h-chamberlain, could you please share the source code for this? I am REALLY struggling to draw a simple image to screen using the GPU.

EDIT: I see this is from @Jhynjhiruu, already contacted him through the original issue