Hello!
First of, I have tried to find the answer to these question in the forums, I can find a lot of people talking around the subject, but no-one that actually answers the questions more then touching the subjects. If there are, please give me the link(s) :-)
I'm playing around with different rendering techniques in SFML and from what I can understand drawing VertexArrays directly would be the most efficient way without resorting to writing yourself in opengl?
When I tried VertexArrays it was a lot quicker than sprites/shapes, but I feel that I cant really grasp what the maximum capability is. So I decided to test this.
Here is my minimal test-code for testing with 1 million particles where each particle is a square or quad:
#include "SFML/Graphics.hpp"
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
//Create objects
sf::RenderWindow window;
window.create(sf::VideoMode(1024, 768), "Test");
//One million rectangle particles are 4 million vertices
sf::VertexArray particles(sf::Quads, 4000000);
sf::Clock clock;
int microsecondsInSecond = 1000000;
sf::Text text;
sf::Font font;
//Change this to an actual font location
font.loadFromFile("content/VeraMono.ttf");
text.setFont(font);
text.setCharacterSize(24);
text.setFillColor(sf::Color::Red);
while (window.isOpen())
{
// handle events
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
//simulate updating the position and color of the particles
for (int i = 0; i < 1000000; i++)
{
particles[i * 4].position = sf::Vector2f(100, 100);
particles[i * 4 + 1].position = sf::Vector2f(200, 100);
particles[i * 4 + 2].position = sf::Vector2f(200, 200);
particles[i * 4 + 3].position = sf::Vector2f(100, 200);
for (int j = i * 4; j < i * 4 + 4; j++)
{
particles[i].color.r = static_cast<sf::Uint8>(255);
particles[i].color.g = static_cast<sf::Uint8>(255);
particles[i].color.b = static_cast<sf::Uint8>(255);
particles[i].color.a = static_cast<sf::Uint8>(255);
}
}
//clear window with black
window.clear(sf::Color::Black);
//Draw
window.draw(particles);
window.draw(text);
window.display();
//Print current aproximate fps
std::string fps("fps: " + std::to_string((microsecondsInSecond / clock.restart().asMicroseconds())));
text.setString(fps);
}
}
On a pretty decent desktop computer this gives me an approximate fps of around 7-8. That seems way to low :-/
With 100 000 particles I get around 70.
So three questions:
- Did I make some mistake in my code that makes it slow?
- Is there some other way in SFML to make it even faster?
- Am I naive to think that a million particles each frame should be doable? (I recall people mentioning "drawing millions of vertices" in other threads, but I could have misunderstood)
- Is one million particles unreasonable in any way? Should I try to rewrite my particle effects so that they use fewer particles?
For a naive example when drawing a circle of light, that could be for example 360 triangles to form up the circle, 360 * 3= 1080. If 100 000 particles is the limit for keeping above 60 fps, that means I could only keep 100 lights on screen at the same time? That seems low...