Skip to content
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

Proposal: Vertex Batch #1801

Open
deltanedas opened this issue Jun 13, 2021 · 0 comments
Open

Proposal: Vertex Batch #1801

deltanedas opened this issue Jun 13, 2021 · 0 comments

Comments

@deltanedas
Copy link

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:

  • Only one RenderStates can be applied to the batch as a whole (1 texture, 1 shader) but we're used to this with VertexArray.
  • No VertexBuffers since the cost of copying them into CPU memory would outweigh the benefit of batched drawing, might upset someone if they don't expect batch.draw(someVertexBuffer) to draw immediately.
  • Shapes with thousands of vertices will have to be transformed one-by-one on the CPU instead of on the GPU, but they should be using VertexBuffer anyways.

Currently writing an implementation of this.

@deltanedas deltanedas mentioned this issue Jun 13, 2021
6 tasks
deltanedas added a commit to deltanedas/SFML that referenced this issue Jun 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants