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

Author Topic: Rendering problem with RenderTexture.getTexture()  (Read 2958 times)

0 Members and 1 Guest are viewing this topic.

andywood

  • Newbie
  • *
  • Posts: 6
    • View Profile
Rendering problem with RenderTexture.getTexture()
« on: June 18, 2016, 02:41:43 am »
I have code like this:

sf::Sprite sprite(myRenderTexture.getTexture());
myRenderTarget.draw(sprite);

It renders incorrectly. I'm not sure where the bits are coming from, but it's drawing the wrong bits. However if I simply introduce one intermediate texture:

sf::Texture texture = myRenderTexture.getTexture();
sf::Sprite sprite(texture);
myRenderTarget.draw(sprite);

Then it renders correctly. The second version is acceptable, but the seemingly needless copy is bothering me. It also makes me think there is something going on in SFML that I don't understand. Also, there is another part in my code (the rendering of the main surface to the window, in fact) that works like the first example, and it's fine. I've rearranged things a few different ways and made sure object lifetime isn't an issue, but every time I remove that texture copy, I get the same bad render (the bad result is always the same, not random).

dabbertorres

  • Hero Member
  • *****
  • Posts: 506
    • View Profile
    • website/blog
Re: Rendering problem with RenderTexture.getTexture()
« Reply #1 on: June 18, 2016, 06:40:38 am »
You need to use sf::RenderTexture::clear() and sf::RenderTexture::display(), just like with a window.

andywood

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: Rendering problem with RenderTexture.getTexture()
« Reply #2 on: June 18, 2016, 07:10:55 am »
Am definitely doing that, before the getTexture().

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10846
    • View Profile
    • development blog
    • Email
AW: Rendering problem with RenderTexture.getTexture()
« Reply #3 on: June 18, 2016, 07:45:10 am »
Provide a complete and minimal code example and define what the wrong and right bits are.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Hapax

  • Hero Member
  • *****
  • Posts: 3360
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Rendering problem with RenderTexture.getTexture()
« Reply #4 on: June 18, 2016, 10:40:52 pm »
You need to use sf::RenderTexture::clear() and sf::RenderTexture::display(), just like with a window.
Am definitely doing that, before the getTexture().
The clear() should be indeed before the draw but the display() should be after the draw.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Rendering problem with RenderTexture.getTexture()
« Reply #5 on: June 18, 2016, 10:52:00 pm »
Quote
The clear() should be indeed before the draw but the display() should be after the draw.
Not after he draws the content of the render-texture to the window. Don't confuse myRenderTarget and myRenderTexture in his code ;)
Laurent Gomila - SFML developer

andywood

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: Rendering problem with RenderTexture.getTexture()
« Reply #6 on: June 18, 2016, 11:59:51 pm »
After much experimenting, I think that maybe I understand what's happening here. Maybe someone can confirm. This is slightly unexpected, but I can understand if this is the way it works. First, an expanded outline of what I'm doing:

sf::RenderTexture finalTexture;
finalTexture.create(32, 32);
finalTexture.clear();

sf::RenderTexture tempTexture;
tempTexture.create(16, 16);

for (int i = 0; i < 4; ++i)
{
    tempTexture.clear();
    // draw varied stuff in tempTexture here
    tempTexture.display();

    sf::Sprite sprite(tempTexture.getTexture());    // sf::Sprite sprite(sf::Texture(tempTexture.getTexture())); here would fix the problem
    sprite.setPosition((i % 2) * 16, (i / 2) * 16);
    finalTexture.draw(sprite);

    // alternately, finalTexture.display(); here would also fix the problem
}

finalTexture.display();
 

So, I am guessing that finalTexture.draw() is actually deferred until finalTexture.display(). Whatever command-list kind of system is used for the deferral, it must store a reference to tempTexture's texture, rather than a copy of its contents at the time the draw call happened. This is why explicitly making copies of tempTexture's texture solves the problem, but also forcing the draw to happen each iteration also solves the problem.

Is this right?
« Last Edit: June 19, 2016, 09:31:28 am by Laurent »

dabbertorres

  • Hero Member
  • *****
  • Posts: 506
    • View Profile
    • website/blog
Re: Rendering problem with RenderTexture.getTexture()
« Reply #7 on: June 19, 2016, 01:40:31 am »
Your code given doesn't describe what your problem exactly, because this works for me:
#include <SFML/Graphics.hpp>

int main()
{
        sf::RenderWindow win{{800, 600}, "Render Textures"};

        sf::RenderTexture rt1;
        rt1.create(200, 200);

        sf::RenderTexture rt2;
        rt2.create(500, 500);

        while(win.isOpen())
        {
                sf::Event ev;
                while(win.pollEvent(ev))
                {
                        switch(ev.type)
                        {
                                case sf::Event::Closed:
                                        win.close();
                                        break;

                                default:
                                        break;
                        }
                }

                rt2.clear(sf::Color::Green);

                for(int i = 0; i < 4; ++i)
                {
                        auto r = rt1.getSize().x / 4.f;
                        sf::CircleShape cir{r};
                        cir.setFillColor(sf::Color::Red);
                        cir.setOrigin(r, r);
                        cir.setPosition(rt1.getSize().x / 2.f, rt1.getSize().y / 2.f);

                        rt1.clear(sf::Color::Blue);
                        rt1.draw(cir);
                        rt1.display();

                        auto s = rt2.getSize().x / 2;
                        auto b = s / 10;

                        sf::Sprite rs1{rt1.getTexture()};
                        rs1.setPosition((i % 2) * s + b, (i / 2) * s + b);

                        rt2.draw(rs1);
                }

                rt2.display();

                sf::Sprite rs2{rt2.getTexture()};
                rs2.setOrigin(rt2.getSize().x / 2.f, rt2.getSize().y / 2.f);
                rs2.setPosition(win.getSize().x / 2.f, win.getSize().y / 2.f);

                win.clear();
                win.draw(rs2);
                win.display();
        }

        return 0;
}

(click to show/hide)
« Last Edit: June 19, 2016, 01:46:47 am by dabbertorres »

andywood

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: Rendering problem with RenderTexture.getTexture()
« Reply #8 on: June 19, 2016, 01:56:53 am »
According to my theory, your code works because you always draw the same thing into rt1. If you draw something different in rt1 on each iteration, then I suspect that upon rt2.display(), rt2 will be covered in whatever the last thing you drew into rt1, rather than what was in rt1 at the time of each call to rt2.draw().

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10846
    • View Profile
    • development blog
    • Email
AW: Rendering problem with RenderTexture.getTexture()
« Reply #9 on: June 19, 2016, 02:28:05 am »
You're correct in your observation. Think of a texture as a block of video memory. When you call draw(), you merely tell what memory block you intent to copy. However the actual copy only happens once you call display(). If between draw() and display() the "to copy memory block" is changed, the changes will finally be copied.

(Yes, this is just an illustration and not how OpenGL really acts)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

andywood

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: Rendering problem with RenderTexture.getTexture()
« Reply #10 on: June 19, 2016, 02:36:23 am »
Cool! Mystery solved. Thank you.