17cupsofcoffee / tetra

🎮 A simple 2D game framework written in Rust
MIT License
907 stars 63 forks source link

Mesh non deterministic glitch #303

Open davideGiovannini opened 2 years ago

davideGiovannini commented 2 years ago

Summary

I apologize for the lack of details, I'm still trying to find a way to reliably reproduce this.


Setup

I'm using a ScreenScaler, a Texture atlas to draw tiles and entities and Mesh to draw particles and debug graphic.

        let mut particle_mesh =
            Mesh::rectangle(ctx, ShapeStyle::Fill, Rectangle::new(0.0, 0.0, 1.0, 1.0))?;
        particle_mesh.set_backface_culling(false);

        ...

        for particle in particles{
            particle_mesh.draw(ctx, particle);
        }

This works fine, except that randomly the screen glitches and 1 frame is drawn at a huge scale.

https://user-images.githubusercontent.com/14345181/144098815-39bc43fc-71e2-49b5-8f8c-8e6add2dc1bf.mp4

Glitched frame

glitched_frame

So far after some testing this seems to happen only if I draw Mesh objects. I have not found any pattern yet, sometime it happens only 1 or 2 times after a lot of time, while more rarely it happens for longer bursts.

If I had to guess it looks like a possible buffer overflow.

Steps to Reproduce

I will update this once I manage to reproduce it in a small example.

Additional Info

No response

17cupsofcoffee commented 2 years ago

That's extremely weird!

My hunch would be that the Mesh drawing code is leaving something in OpenGL in an inconsistent state - Mesh::draw sidesteps the sprite rendering code and calls directly into the GL layer, so it's feasible the issue could be happening when sprite rendering picks up where it left off. I'll have to do a bit of investigating - if you do find a way to replicate the issue, that'd be immensely helpful.

As an aside, if you just want to draw colored rectangles, you might want to try the technique mentioned in the FAQ (i.e. creating a 1x1 texture and then using DrawParams to transform it) - this will allow you to take advantage of Tetra's built-in sprite batching. Mesh drawing does not do any batching for you, so calling Mesh::draw for a small mesh lots of times in a loop can be quite slow.

davideGiovannini commented 2 years ago

As an aside, if you just want to draw colored rectangles, you might want to try the technique mentioned in the FAQ ...

Thanks for the reminder, it was in my TODO list but I had forgot the part about batching, I will do it asap for particles :smile:

I think I will still spend some time trying to investigate this during the week. I am using meshes in the code for drawing 2d shadows and I suspect that it's also happening there

so it's feasible the issue could be happening when sprite rendering picks up where it left off.

This is an overview of the render fn

set canvas
render tiles
render entities
render particles

draw canvas to scaler
draw scaler to screen