SFML community forums

Help => Graphics => Topic started by: Naofu on August 05, 2019, 04:41:03 pm

Title: Drawing one time is slower than 100 times.
Post by: Naofu on August 05, 2019, 04:41:03 pm
Hello, I'm new to SFML and also to C++.
This question is similar to previous one but I also stuck with this problem.

#include <SFML\Graphics.hpp>
#include <iostream>

class Block
{
public:
        Block();
        ~Block();
        void Allocate(sf::Vector2f position, sf::Vector2f size);
        sf::VertexArray GetShape() { return shape; }
        bool CheckAlive() { return alive; }
private:
        sf::VertexArray shape;
        bool alive;
};

Block::Block()
{
}

Block::~Block()
{
}

void Block::Allocate(sf::Vector2f position, sf::Vector2f size)
{
        shape = sf::VertexArray(sf::Quads, 4);
        shape[0].position = position;
        shape[1].position = { position.x + size.x, position.y };
        shape[2].position = { position.x + size.x, position.y + size.y };
        shape[3].position = { position.x, position.y  + size.y};
        shape[0].color = sf::Color::Red;
        shape[1].color = sf::Color::Blue;
        shape[2].color = sf::Color::Green;
        shape[3].color = sf::Color::Yellow;
        alive = true;
}

int main()
{
        sf::RenderWindow window(sf::VideoMode(400, 400), "TEST");
        Block block[100];
        for (int i = 0; i < 10; i++)
                for (int j = 0; j < 10; j++)
                        block[j + 10 * i].Allocate(sf::Vector2f(40.f * j, 40.f * i), sf::Vector2f(40.f, 40.f));
        sf::VertexArray bunchOfShapes(sf::Quads, 0);
        sf::Clock clock;
        float frameTime = 0.f;
        float timer = 0.f;
        int fps = 0;
        while (window.isOpen())
        {
                frameTime = clock.restart().asSeconds();
                sf::Event e;
                while (window.pollEvent(e))
                {
                        if (e.type == sf::Event::Closed)
                                window.close();
                }
                timer += frameTime;
                fps++;
                if (timer >= 1.f)
                {
                        std::cout << fps << std::endl;
                        fps = 0;
                        timer = 0.f;
                }

                window.clear();
                // draw every shapes 100 times.
                for (int i = 0; i < 100; i++)
                        if (block[i].CheckAlive())
                                window.draw(block[i].GetShape());
                // draw one big shape.
                /*for (int i = 0; i < 100; i++)                                                                                
                        if (block[i].CheckAlive())
                                for (int j = 0; j < block[i].GetShape().getVertexCount(); j++)
                                        bunchOfShapes.append(block[i].GetShape()[j]);
                window.draw(bunchOfShapes);*/


                window.display();
        }
}

 

I expected drawing one time is faster but turned to be much worse. Each of those blocks has a state and it is to be changed frequently in game, so this one big shape has to be updated in every frame. This code is definitely wrong but I can't figure out.
Title: Re: Drawing one time is slower than 100 times.
Post by: Laurent on August 05, 2019, 08:18:42 pm
The single draw code is a lot less efficient because you allocate, deallocate and copy much more than necessary. You should allocate the memory for everything once, and then just update stuff in-place.
Title: Re: Drawing one time is slower than 100 times.
Post by: Naofu on August 06, 2019, 01:41:28 am
Thanks for your reply. I still don't understand pointers, memories,,,etc. I gotta study hard.
In this case I'm bothered with discarding vertices of vanished entities.
Fairly improved by this way but still be defeated by drawing 100 times.

#include <SFML\Graphics.hpp>
#include <iostream>
#include <vector>

class Block
{
public:
        Block();
        ~Block();
        sf::Vertex* GetShape() { return shape; }
        void Allocate(sf::Vector2f position, sf::Vector2f size);
        bool CheckAlive() { return alive; }
        int GetVertexCount() { return vertexCount; }
private:
        sf::Vertex shape[8];
        bool alive;
        int vertexCount;
};

Block::Block()
{
}

Block::~Block()
{
}

void Block::Allocate(sf::Vector2f position, sf::Vector2f size)
{
        shape[0] = sf::Vertex(position, sf::Color::Red);
        shape[1] = sf::Vertex({ position.x + size.x, position.y }, sf::Color::Blue);
        shape[2] = sf::Vertex({ position.x + size.x, position.y + size.y}, sf::Color::Green);
        shape[3] = sf::Vertex({ position.x, position.y + size.y }, sf::Color::Yellow);
        alive = true;
        vertexCount = 4;
}

int main()
{
        sf::RenderWindow window(sf::VideoMode(400, 400), "TEST");
        Block block[100];
        for (int i = 0; i < 10; i++)
                for (int j = 0; j < 10; j++)
                        block[j + 10 * i].Allocate(sf::Vector2f(40.f * j, 40.f * i), sf::Vector2f(40.f, 40.f));
        sf::Clock clock;
        float frameTime = 0.f;
        float timer = 0.f;
        int fps = 0;
        while (window.isOpen())
        {
                frameTime = clock.restart().asSeconds();
                sf::Event e;
                while (window.pollEvent(e))
                {
                        if (e.type == sf::Event::Closed)
                                window.close();
                }
                timer += frameTime;
                fps++;
                if (timer >= 1.f)
                {
                        std::cout << fps << std::endl;
                        fps = 0;
                        timer -= 1.f;
                }

                window.clear();
                // draw every shapes 100 times.
                /*for (int i = 0; i < 100; i++)
                        if (block[i].CheckAlive())
                                window.draw(block[i].GetShape(), block[i].GetVertexCount(), sf::Quads);*/

                // draw one big shape.
                std::vector<sf::Vertex> vertices(0);
                int totalVertexCount = 0;
                for (int i = 0; i < 100; i++)
                        if (block[i].CheckAlive())
                                for (int j = 0; j < block[i].GetVertexCount(); j++)
                                {
                                        vertices.emplace_back(block[i].GetShape()[j]);
                                        totalVertexCount++;
                                }
                window.draw(&vertices[0], totalVertexCount, sf::Quads);

                window.display();
        }
}

 
Title: Re: Drawing one time is slower than 100 times.
Post by: Geheim on August 06, 2019, 05:44:19 pm
That is because you are most likely running in Debug mode, try it with Release and it will be faster.
Title: Re: Drawing one time is slower than 100 times.
Post by: Laurent on August 06, 2019, 10:35:36 pm
Quote
Thanks for your reply. I still don't understand pointers, memories,,,etc. I gotta study hard.
Studying that first, and then trying to figure out what you wrote by yourself, is honestly the best advice I can give. I could write an efficient solution for you but you wouldn't understand memory management better ;)