SFML / SFML

Simple and Fast Multimedia Library
https://www.sfml-dev.org/
zlib License
10.14k stars 1.71k forks source link

Proposal: Vertex Batch #1801

Open deltanedas opened 3 years ago

deltanedas commented 3 years ago

Everyone has tried to use our good friend sf::Sprite for a game, then it gets out of hand when a few hundred/thousand cripple performance. Then you ask around on the forums and try out sf::VertexArray and your cool tilemap draws instantly! Now you want to draw more dynamic things, and you're back to lots of draw calls or manually building VertexArrays which quickly becomes painful. You can't add other drawables to a VertexArray.

I think that VertexArray/Buffer are fantastic, but their greatest limitation is that they can only be used to (easily) batch individual vertices. You can't do something like this:

sf::VertexArray array;
sf::Sprite sprite;
array.append(sprite); // nope

This is where VertexBatch comes in. VertexBatch is a thin wrapper over a VertexArray that when drawn to, simply appends the "drawn" vertices to be actually drawn later. It would be both a Drawable (it has to be drawn somewhere) and a RenderTarget (why bother with it at all if you have to use a special set of drawSprite/drawArray/etc methods, when the RenderTarget::draw(Drawable) relationship already exists?) Example code using it:

sf::RenderWindow window(...);
// Create a batch that wraps around a window (can be any RenderTarget, even another VertexBatch!)
sf::VertexBatch batch(window);

// Start of frame, clear old vertices
window.clear();
batch.clear();

// Queue some stuff to be drawn, won't actually draw it yet.
sf::CircleShape ellipse(10, 20);
ellipse.setPosition({200, 200});
// Transforms can be used too, but they'll be done on the CPU in batch.draw()
sf::Transform transform;
transform.scale(1, 0.5);
batch.draw(ellipse, transform);
sf::Text("i am very text", someFontHere);
batch.draw(text);

// Actually draw it! This just uses a few commands to transfer vertices to gpu, set gl states, draw them
window.draw(batch);
window.display();

Limitations:

Currently writing an implementation of this.

winsvega commented 4 weeks ago

This can actually be worked around quite easily. If you want sprites, you make a tilemap and calculate vertexes manually, and then you can draw many different sprites in one batch.

The issue is if you use blend mode and it overlaps.