Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: sf::RenderTexture not working properly  (Read 2372 times)

0 Members and 1 Guest are viewing this topic.

Sammy07

  • Newbie
  • *
  • Posts: 6
    • View Profile
    • Email
sf::RenderTexture not working properly
« on: March 31, 2022, 01:55:15 pm »
Hello,

I'm making a project that reads a big amount of small float data and I use this data to draw sort of a heat map.
Everything is working out great if I draw everything every frame straight into the sf::RenderWindow and I use a view to zoom in to my heat map and scroll around.

However if the data size is too big, drawing everything every frame as small triangles is too much and lags everything. So I decided to try to use sf::RenderTexture and render everything on it one time. And only update it if I zoom or if the data changes.

The problem is drawing things using small float data as coordinates into a sf::RenderTexture just doesn't work. But it works perfectly in a RenderWindow.

Is this intentional ? if so, is there another way to achieve what I'm trying to do ?

Here's a complete code example to show that drawing with float coordinates works on sf::RenderWindow but not on sf::RenderTexture

#include <SFML/Graphics.hpp>

//view size
#define L 6
#define H 6
//size of object to draw
#define RL 2.5
#define RH 1.5

int main()
{
    sf::RenderWindow window(sf::VideoMode(800, 800), "SFML works!");
    sf::View view;
    view.setSize(L,H);
    view.setCenter(L/2,H/2);
    window.setView(view);
    sf::RenderTexture texture;
    //texture.setView(view);
    sf::RenderTarget& target = texture; //case 1 window , case 2 texture
    texture.create(L,H);
    sf::Sprite sprite;


    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        window.clear(sf::Color::White);
        texture.clear(sf::Color::White);
        sf::RectangleShape rect(sf::Vector2f(RL/2, RH/2));

        rect.setPosition(0,0);
        rect.setFillColor(sf::Color::Red);
        target.draw(rect);

        rect.setPosition(RL/2,0);
        rect.setFillColor(sf::Color::Blue);
        target.draw(rect);


        rect.setPosition(0,RH/2);
        rect.setFillColor(sf::Color::Green);
        target.draw(rect);


        rect.setPosition(RL/2,RH/2);
        rect.setFillColor(sf::Color::Yellow);
        target.draw(rect);

        sprite.setTexture(texture.getTexture());


        sprite.setPosition(0,0);
        //window.draw(sprite); // uncomment this line for case 2
        window.display();
    }

    return 0;
}
 

fallahn

  • Sr. Member
  • ****
  • Posts: 492
  • Buns.
    • View Profile
    • Trederia
Re: sf::RenderTexture not working properly
« Reply #1 on: March 31, 2022, 05:31:49 pm »
A couple of things:
First I can't see where you call display() on the render texture, this could well be the problem. However it might also be worth doing the drawing with each target sequentially:

texture.clear();
....
texture.display();

window.clear();
....
window.display();
 

Also rather than use a reference to the active target, use a pointer, as it's possible you may end up copying something at some point, and SFML will create a new texture (and potentially even discard the old one) if a RenderTexture is copied, which could end up throwing things out of sync.

kojack

  • Sr. Member
  • ****
  • Posts: 314
  • C++/C# game dev teacher.
    • View Profile
Re: sf::RenderTexture not working properly
« Reply #2 on: March 31, 2022, 11:11:36 pm »
Your window is 800x800 pixels, but your render texture is 6x6 pixels (due to the texture.create(L,H); call).

Sammy07

  • Newbie
  • *
  • Posts: 6
    • View Profile
    • Email
Re: sf::RenderTexture not working properly
« Reply #3 on: April 01, 2022, 10:39:02 am »
Your window is 800x800 pixels, but your render texture is 6x6 pixels (due to the texture.create(L,H); call).

Thank you for the reply, I just tried setting the texture size to 800x800 same as the window size and I set the sprite position to (0 , -794) so it can be within the view and this doesn't change anything unfortunately.

Sammy07

  • Newbie
  • *
  • Posts: 6
    • View Profile
    • Email
Re: sf::RenderTexture not working properly
« Reply #4 on: April 01, 2022, 10:55:16 am »
A couple of things:
First I can't see where you call display() on the render texture, this could well be the problem. However it might also be worth doing the drawing with each target sequentially:


Thank you for the reply, I tried adding display() for the texture, and I tried to draw sequentially. This unfortunately doesn't change anything.


Also rather than use a reference to the active target, use a pointer, as it's possible you may end up copying something at some point, and SFML will create a new texture (and potentially even discard the old one) if a RenderTexture is copied, which could end up throwing things out of sync.

Yes, I used a reference in this sample code to easily switch between renderwindow and and rendertexture to demonstrate the issue. it is true that a pointer would've been more preferable. Either way, it's a sample code only and I don't use pointers or references in my project code.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10819
    • View Profile
    • development blog
    • Email
Re: sf::RenderTexture not working properly
« Reply #5 on: April 01, 2022, 03:33:26 pm »
In the code you're also rendering to the RT every frame, which I thought is what you wanted to prevent.
You've also commented out the drawing of the sprite, so the render texture, never gets drawn to the window.
And you may want to always pass true as second parameter to setTexture to ensure that the texture rect is resized correctly.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Sammy07

  • Newbie
  • *
  • Posts: 6
    • View Profile
    • Email
Re: sf::RenderTexture not working properly
« Reply #6 on: April 01, 2022, 05:29:41 pm »
In the code you're also rendering to the RT every frame, which I thought is what you wanted to prevent.

Thank you for your reply.
Yes, I want to prevent drawing to the RT every frame in my project. What I posted here is a quick sample code to demonstrate the problem which is drawing with small float data as coordinates.

this problem is independent from trying not to draw every frame which I will try to do in my project if the problem is fixed.



You've also commented out the drawing of the sprite, so the render texture, never gets drawn to the window.

yes, you have to uncomment it for case 2 (target = texture). you will see that what you get is not the correct dimensions specified for drawing. it seems that float coordinates are converted to int coordinates before drawing to RT which is very problematic to me since all of my data is small float values.

And you may want to always pass true as second parameter to setTexture to ensure that the texture rect is resized correctly.

I have tried this and unfortunately it doesn't change anything :(

Sammy07

  • Newbie
  • *
  • Posts: 6
    • View Profile
    • Email
Re: sf::RenderTexture not working properly
« Reply #7 on: April 03, 2022, 04:08:54 pm »
Hello again,

In case someone finds this in the future, I've managed to fix the lag without using sf::RenderTexture. I've read more on the SFML drawing API and it turns out the lag was not because of the data size but rather because of the high number of sf::RenderWindow::draw() calls.

What I did in my project code was a long "for" loop that sets 3 temporary sf::Vertex variables to desired coordinates and color and draw a single triangle using these vertices each iteration. This meant if there was 3000 triangles, draw() would be called 3000 times which was what caused the lag.

so the fix was to simply make a huge std::vector<sf::Vertex> and set up every single Vertex coordinate and color then pass this vector as the sf::Drawable argument in a single sf::RenderWindow::draw() call.

This still means the sf::RenderTexture is not working with float coordinates but thankfully I don't have to use it.

Thanks again everyone who answered. And thanks to SFML developers for the amazing library.