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

Author Topic: sf::RenderTarget::display() not present?  (Read 7250 times)

0 Members and 1 Guest are viewing this topic.

Jonny

  • Full Member
  • ***
  • Posts: 114
    • View Profile
    • Email
sf::RenderTarget::display() not present?
« on: March 14, 2018, 12:21:33 am »
Is there a reason it's missing?

I'd like to use some polymorphism so I can switch between rendertexture and render window neatly, but currently I have to do this for the display step in clear/draw/display cycle:

       
if (dynamic_cast<sf::RenderWindow*>(m_renderTarget))
        dynamic_cast<sf::RenderWindow*>(m_renderTarget)->display();
if (dynamic_cast<sf::RenderTexture*>(m_renderTarget))
        dynamic_cast<sf::RenderTexture*>(m_renderTarget)->display();
 

Although there may be a better way, it seems logical for RenderTarget to declare the display() method?

edit: I'd also be curious why there isn't a setSize() to match getSize()?
« Last Edit: March 14, 2018, 07:39:16 pm by Jonny »

Arcade

  • Full Member
  • ***
  • Posts: 230
    • View Profile
Re: sf::RenderTarget::display() not present?
« Reply #1 on: March 14, 2018, 05:04:04 pm »
The RenderTarget display() question has been brought up on the forum several times. If you search around you can find the reasoning given for why that function doesn't exist. My attempt to summarize some of those answers:

  • sf::RenderWindow doesn't define display() directly. It gets it through inheritance of sf::Window.
  • There isn't a need for a display() function at the RenderTarget level. A RenderTarget doesn't necessarily need a call to indicate drawing is done. For example, unbuffered rendering.
  • RenderTexture::display() internally does different things than RenderWindow::display(). It just has the same name because the usage is similar.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11008
    • View Profile
    • development blog
    • Email
Re: sf::RenderTarget::display() not present?
« Reply #2 on: March 14, 2018, 06:15:58 pm »
* Using RenderTarget in a polymorphic way doesn't really make sense.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Jonny

  • Full Member
  • ***
  • Posts: 114
    • View Profile
    • Email
Re: sf::RenderTarget::display() not present?
« Reply #3 on: March 14, 2018, 07:28:27 pm »
* Using RenderTarget in a polymorphic way doesn't really make sense.

Care to elaborate? Should I be taking a different approach for my use case?

sf::RenderWindow doesn't define display() directly. It gets it through inheritance of sf::Window.

I see that, but I don't see how this relates? setActive is also declared in both sf::Window and sf::Rendertarget, why can't display() be?

There isn't a need for a display() function at the RenderTarget level. A RenderTarget doesn't necessarily need a call to indicate drawing is done. For example, unbuffered rendering.

Sure, that's why I'd propose it to be pure virtual, like the other methods which aren't necessarily needed at RenderTarget level?

RenderTexture::display() internally does different things than RenderWindow::display(). It just has the same name because the usage is similar.

Can you elaborate on why that's a problem? As I understand it many of the RenderWindow/RenderTexture functions are implemented differently, even if they are inherited?

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11008
    • View Profile
    • development blog
    • Email
Re: sf::RenderTarget::display() not present?
« Reply #4 on: March 14, 2018, 07:34:51 pm »
What's your use case?
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Jonny

  • Full Member
  • ***
  • Posts: 114
    • View Profile
    • Email
Re: sf::RenderTarget::display() not present?
« Reply #5 on: March 14, 2018, 07:38:40 pm »
I want to toggle between rendering to the window, or to a rendertexture, using the standard clear/draw/display cycle. For the most part this is easily done, using an sf::RenderTarget* which implements clear() and draw() amongst others. I just hit a block when I get to display(), at which point I need to mess around with casting to get it into the right type, even though both have display() implemented.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11008
    • View Profile
    • development blog
    • Email
Re: sf::RenderTarget::display() not present?
« Reply #6 on: March 14, 2018, 08:14:47 pm »
Why does this require a generic approach skewed towards render target?

Rendering (clear, draw, display) to a window is something you do once a cycle, while rendering to a render texture can happen many times in a cycle.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: sf::RenderTarget::display() not present?
« Reply #7 on: March 14, 2018, 08:20:25 pm »
Quote
I want to toggle between rendering to the window, or to a rendertexture
Sorry for still not answering your question, but may I ask why? (this is pure curiosity)
Laurent Gomila - SFML developer

Arcade

  • Full Member
  • ***
  • Posts: 230
    • View Profile
Re: sf::RenderTarget::display() not present?
« Reply #8 on: March 14, 2018, 08:27:08 pm »
By the way, my response to you was simply relaying answers from previous threads, such as this one and this (old) one. These are likely design decisions, not technical ones, so you may need to focus more on why a generic RenderTarget should have a display() function more so than the technical feasibility of the idea. I don't have much of the background knowledge on the topic, though, so I'll leave it to others in this thread to try and provide you more satisfying answers to your questions.

Jonny

  • Full Member
  • ***
  • Posts: 114
    • View Profile
    • Email
Re: sf::RenderTarget::display() not present?
« Reply #9 on: March 14, 2018, 08:33:12 pm »
I have the commonly used "Game" class, which takes care of the main loop. I'm implementing an in-game editor, which when activated, shows the game view in a preview window, so I'd like to just switch the Game class so it renders to a RenderTexture,. When the editor is disabled, it switches back to rendering directly to the window.

I'm sure there are alternative ways, and I'm not definitively saying that this is the perfect thing to do, it just seems like a logical addition with little-to-no negative effects, and I was curious what the reason would be for not having it.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: sf::RenderTarget::display() not present?
« Reply #10 on: March 15, 2018, 08:19:48 am »
I have nothing to add to what Arcade said about the existing answers in other threads.

Back to your use case. When you switch your editor on/off, you don't just switch between RenderTexture and RenderWindow, right? Once you have your game screen rendered to a RenderTexture, I suppose you do more specific stuff with it (most likely, using it to draw some sprite later)? So why can't the call to display() be part of this specific stuff that happens after drawing?

Moreover, in most architectures that I've seen, calling display() is part of the higher-level logic, ie. it happens after the call to game.draw(sf::RenderTarget&), not inside it.
Laurent Gomila - SFML developer

Jonny

  • Full Member
  • ***
  • Posts: 114
    • View Profile
    • Email
Re: sf::RenderTarget::display() not present?
« Reply #11 on: March 15, 2018, 07:46:52 pm »
Correct, the rendertexture is drawn to an imgui window. There's no particular reason why I couldn't call display on the rendertexture from the editor code, I'd just like to keep the game loop as consistent as possible, whether it's being edited or not.

I guess Ill need to put together an example to show you more clearly. In the meantime, any response on why there's no setSize()?

AlexAUT

  • Sr. Member
  • ****
  • Posts: 396
    • View Profile
Re: sf::RenderTarget::display() not present?
« Reply #12 on: March 16, 2018, 10:24:30 pm »
any response on why there's no setSize()?

Have a look at this example:

//render scene into rendertexture and apply some post processing
renderTexture.setSize({1920, 1080});
drawNormalScene(renderTexture);
applyPostProcessing(renderTexture);
window.draw(renderTexture);
//now draw minimap
renderTexture.setSize({320,320});
drawMinimap(renderTexture);
applyBlur(renderTexture);
window.draw(renderTexture);

This code looks fine, we even reuse the rendertexture which should be great, or is it?
This code would perform horribly in comparison to just having 2 rendertextures.

RenderTextures are the heaviest resources SFML does offer (except of the window and maybe sounds?) and setSize() would not express the implications of such a call. It would have to generate at least 1 new texture, 3 at worst. Also what happens to the current content? Scale down/up to the new resolution, clip it at the borders or discard it completely? Copying the content to the new texture may need a copy to userspace and back to the new texture on the GPU...



AlexAUT

Jonny

  • Full Member
  • ***
  • Posts: 114
    • View Profile
    • Email
Re: sf::RenderTarget::display() not present?
« Reply #13 on: March 17, 2018, 10:48:04 pm »
I was just curious why there's a getter but no setter, that's all. Not terribly concerned with the performance/implementation details of a derived class, just seems a strange bit of asymmetry.

Jonny

  • Full Member
  • ***
  • Posts: 114
    • View Profile
    • Email
Re: sf::RenderTarget::display() not present?
« Reply #14 on: March 18, 2018, 11:43:14 pm »
Here's some rough example code:

#include <SFML/Graphics.hpp>

int main(int argc, char const** argv)
{
    // create a window and an off screen buffer
    sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window");
   
    sf::RenderTexture buffer;
    buffer.create(800,600);
    sf::Sprite bufferSprite(buffer.getTexture());
    bufferSprite.setColor(sf::Color::Red);
   
    // Start using the window directly
    sf::RenderTarget* currentTarget = &window;

    // Load a sprite to display
    sf::Texture texture;
    if (!texture.loadFromFile("cute_image.jpg")) {
        return EXIT_FAILURE;
    }
    sf::Sprite sprite(texture);
   
    auto draw = [&sprite, &currentTarget]()
    {
        currentTarget->clear();
        currentTarget->draw(sprite);
       
        // Would like to just do target->display();
        auto rt = dynamic_cast<sf::RenderTexture*>(currentTarget);
        auto rw = dynamic_cast<sf::RenderWindow*>(currentTarget);
        if (rt) rt->display();
        else if (rw) rw->display();
    };

    bool use_window = true;
   
    // Start the game loop
    while (window.isOpen())
    {
        // Process events
        sf::Event event;
        while (window.pollEvent(event))
        {
            // Close window: exit
            if (event.type == sf::Event::Closed) {
                window.close();
            }

            // Escape pressed: exit
            if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Space) {
                use_window = !use_window;
                if (use_window)
                    currentTarget = &window;
                else
                    currentTarget = &buffer;
            }
        }
       
        draw();
        if (!use_window)
        {
            window.clear();
            window.draw(bufferSprite);
            window.display();
        }
    }

    return EXIT_SUCCESS;
}
 

Furthermore, Why don't the reasons (of which there haven't really been any clear ones...) for not doing this apply to getSize()? or setActive()?
« Last Edit: March 19, 2018, 12:10:27 am by Jonny »