How to draw multiple objects of the same shape in SFML using VertexArray?

1 week ago 13
ARTICLE AD BOX

The practical approach would be using sf::RectangleShape per rectangle. sf::VertexArray with sf::Quads and sf::VertexBuffer

#include <SFML/Graphics.hpp> #include <vector> int main() { sf::RenderWindow window(sf::VideoMode(800, 800), "Rectangles"); // Create N rectangles std::vector<sf::RectangleShape> rects; const sf::Vector2f size(20.f, 10.f); for (int y = 0; y < 20; ++y) { for (int x = 0; x < 20; ++x) { sf::RectangleShape r(size); r.setPosition(100.f + x * 22.f, 100.f + y * 12.f); r.setFillColor(sf::Color::White); rects.push_back(r); } } // A moving probe to test collisions sf::RectangleShape probe({20.f, 10.f}); probe.setFillColor(sf::Color::Red); probe.setPosition(50.f, 50.f); while (window.isOpen()) { sf::Event e; while (window.pollEvent(e)) { if (e.type == sf::Event::Closed) window.close(); } // move the probe with arrow keys float speed = 200.f; float dt = 1.f/60.f; if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) probe.move(-speed*dt, 0); if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) probe.move( speed*dt, 0); if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) probe.move(0, -speed*dt); if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) probe.move(0, speed*dt); // Collision test: AABB intersects sf::FloatRect probeBounds = probe.getGlobalBounds(); bool colliding = false; for (auto& r : rects) { if (r.getGlobalBounds().intersects(probeBounds)) { colliding = true; break; } } probe.setFillColor(colliding ? sf::Color::Green : sf::Color::Red); window.clear(sf::Color(30,30,30)); for (auto& r : rects) window.draw(r); window.draw(probe); window.display(); } }

If your rectangles are static (or rarely change), put the vertex data into a GPU-side sf::VertexBuffer:

sf::VertexBuffer buffer(sf::Quads); buffer.create(va.getVertexCount()); buffer.update(&va[0], va.getVertexCount(), 0); window.draw(buffer);

Kindly prefer sf::Quads for better clarity.

Updated the answer based on the comment:

You can use VertexArray:

#include <SFML/Graphics.hpp> #include <vector> struct Rect { sf::FloatRect bounds; }; int main() { sf::RenderWindow window(sf::VideoMode(800, 800), "VertexArray Rectangles"); std::vector<Rect> rects; // Generate 400 rectangles (20 × 20 grid) for (int y = 0; y < 20; ++y) for (int x = 0; x < 20; ++x) rects.push_back({ sf::FloatRect(100.f + x*22.f, 100.f + y*12.f, 20.f, 10.f) }); // Build vertex array (static rectangles) sf::VertexArray vertices(sf::PrimitiveType::Triangles); vertices.resize(rects.size() * 6); for (std::size_t i = 0; i < rects.size(); ++i) { const auto& r = rects[i].bounds; sf::Vector2f A(r.left, r.top); sf::Vector2f B(r.left + r.width, r.top); sf::Vector2f C(r.left + r.width, r.top + r.height); sf::Vector2f D(r.left, r.top + r.height); vertices[i*6 + 0].position = A; vertices[i*6 + 1].position = B; vertices[i*6 + 2].position = D; vertices[i*6 + 3].position = B; vertices[i*6 + 4].position = C; vertices[i*6 + 5].position = D; for (int v = 0; v < 6; ++v) vertices[i*6+v].color = sf::Color::White; } // Collision test rectangle sf::RectangleShape probe({20.f, 10.f}); probe.setFillColor(sf::Color::Red); while (window.isOpen()) { sf::Event e; while (window.pollEvent(e)) if (e.is<sf::Event::Closed>()) window.close(); // Move probe float speed = 200.f; float dt = 1.f / 60.f; if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) probe.move(-speed*dt, 0); if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) probe.move( speed*dt, 0); if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) probe.move(0, -speed*dt); if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) probe.move(0, speed*dt); // Collision detection sf::FloatRect probeBounds = probe.getGlobalBounds(); bool colliding = false; for (auto& r : rects) { if (probeBounds.intersects(r.bounds)) colliding = true; } probe.setFillColor(colliding ? sf::Color::Green : sf::Color::Red); // Render window.clear(); window.draw(vertices); // single draw call! window.draw(probe); window.display(); } }

If rectangles never move, upload them to the GPU:

sf::VertexBuffer buffer(sf::PrimitiveType::Triangles); buffer.create(vertices.getVertexCount()); buffer.update(vertices.data(), vertices.getVertexCount(), 0);

Then draw: window.draw(buffer);

Hope it gives you clarity in understanding

Read Entire Article