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

Author Topic: RenderTexture Help  (Read 1304 times)

0 Members and 1 Guest are viewing this topic.

SFMLNewGuy

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
RenderTexture Help
« on: April 22, 2020, 05:35:01 am »
Hello,

Had a quick question about RenderTexture, which I'm trying to understand better (off screen drawing).

I have a initialize class where I do this

 

init() {
...
 if (!renderTexture.create(50*32, 50*32)) {
        std::cout << "Error: creating renderTexture\n";
    }

    renderTexture.clear();

    for (auto i = 0; i < 50; i++) {
        for (auto j = 0; j < 50; j++) {
            tiles[j][i].sprite.setPosition(tiles[j][i].pos);
            renderTexture.draw(tiles[j][i].sprite);
        }
    }

    renderTexture.display();
}
 

    In my draw function, I have...
void draw(){
    const sf::Texture& tex = renderTexture.getTexture();

    m_window.clear();
    m_window.draw(sf::Sprite(tex));
    m_window.draw(m_player);
    m_window.display();
}
 


Now here is the part it is messing up. I added a space key to change tile[10][10] to a red tile and try to update it all and it creates all the tiles (50x50 Map/32x32 Tiles) white (losing the texture) except the 10x10 tile.


 
void handleInput(){
...
   if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space)) {
        // drawing uses the same functions
        if (!renderTexture.create(50 * 32, 50 * 32)) {   // may not need this?
            std::cout << "error\n";
        }
        renderTexture.clear();
        for (auto i = 0; i < 50; i++) {
            for (auto j = 0; j < 50; j++) {
                tiles[j][i].sprite.setPosition(tiles[j][i].pos);
                if (i == 10 && j == 10)
                    tiles[j][i].sprite.setColor(sf::Color::Red);

                renderTexture.draw(tiles[j][i].sprite);
            }
        }
         

          renderTexture.display();
     }
}
    }

Any help would be appreciated, I'm just trying to learn how to use this more in this example since a few times I feel this concept would have been handy to know. I understand that it would be better to just put a red color sprite on top since this seems to be demanding to constantly run except the initial part.
« Last Edit: April 22, 2020, 05:38:35 am by SFMLNewGuy »

SFMLNewGuy

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
Re: RenderTexture Help
« Reply #1 on: April 24, 2020, 01:52:04 am »
Sorry to bump this, but I still haven't found any answer or have solved this. Whatever I do I just get a blank white screen with a red square (not a red-colored tile) once I try to redraw to it. I wish I could find more tutorials involving RenderTexture. There seems to be a huge lack of information. It's not a serious problem, I was just making an example to better understand it.

I know longer have my example, but I was wondering if setting the window.clear() to sf::Color::Transparent. It would have been my next thing to try. It basically just becomes a huge white square with a red square where the tile was. So I was wondering if it's underneath it.

PS: Any more complex example than the one on the SFML page would be appreciated. Thanks

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: RenderTexture Help
« Reply #2 on: April 24, 2020, 08:37:48 am »
I can't see anything wrong in your code. However, your example was lacking important parts (especially the declaration and initialization of tiles).

A complete and minimal example is always the best way to get quick and relevant answers --we don't want to guess what happens in the code that you don't show ;)
Laurent Gomila - SFML developer

SFMLNewGuy

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
Re: RenderTexture Help
« Reply #3 on: April 24, 2020, 08:47:57 pm »
Okay!  :)   I recreated the program and I have the same problem.

Game.h
{

struct Tile{ sf::Sprite sprite; sf::Vector2f pos; }
...
private:
sf::RenderTexture m_renderTexture;
std::vector<std::vector<Tile> m_TileMap;
}
Here is the Game.cpp code.


#include "Game.h"
#include <iostream>


const sf::Time Game::TimePerFrame = sf::seconds(1.f / 60.f);
const float TILE_SIZE = 32;
int MAP_WIDTH = 15;
int MAP_HEIGHT = 15;

Game::Game()
    : m_window({WINDOW_SIZE.x,WINDOW_SIZE.y},"RenderTexture Example")

{

    m_window.setPosition({ m_window.getPosition().x, 0 });
    m_window.setVerticalSyncEnabled(true);

    MAP_WIDTH = m_window.getSize().x / TILE_SIZE;
    MAP_HEIGHT = m_window.getSize().y / TILE_SIZE;

    sf::Texture tex;
    tex.loadFromFile("media/grass.png");

    m_renderTexture.create(MAP_WIDTH * TILE_SIZE, MAP_HEIGHT * TILE_SIZE);


    for (auto i = 0; i < MAP_HEIGHT; i++) {
        m_tileMap.emplace_back();
        for (auto j = 0; j < MAP_WIDTH; j++) {
            auto newTile = new Tile;
            newTile->sprite.setTexture(tex);
            newTile->pos = sf::Vector2f{ j * TILE_SIZE ,i * TILE_SIZE };
            m_tileMap[i].push_back(*newTile);
        }
    }
    m_renderTexture.clear();

    for (auto& tile : m_tileMap) {
        for (auto& it : tile) {
            it.sprite.setPosition(it.pos);
            m_renderTexture.draw(it.sprite);
        }
   }

    m_renderTexture.display();
   

}

void Game::run()
{
    sf::Clock clock;
    sf::Time timeSinceLastUpdate = sf::Time::Zero;

     while (m_window.isOpen()) {
            const sf::Time elapsedTime = clock.restart();
        timeSinceLastUpdate += elapsedTime;

     while(timeSinceLastUpdate > TimePerFrame) {
               timeSinceLastUpdate -= TimePerFrame;
     
                processEvents();
                update(TimePerFrame);
        }
 
        render();
    }
}

void Game::processEvents()
{
    sf::Event event{};
    while (m_window.pollEvent(event)) {
        switch (event.type) {
            case sf::Event::KeyPressed:
                  handlePlayerInput(event.key.code, true);
                if(event.key.code == sf::Keyboard::Escape)
                    m_window.close();
            break;

            case sf::Event::KeyReleased:
                handlePlayerInput(event.key.code, false);
            break;

            case sf::Event::Closed:
                if(event.type == sf::Event::Closed)
                    m_window.close();
            break;
            default: break;
        }
    }

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space)) {
 

        m_tileMap[5][5].sprite.setColor(sf::Color::Red);
        m_renderTexture.clear();

        for (auto& tile : m_tileMap) {
            for (auto& it : tile) {
                it.sprite.setPosition(it.pos);
               
                m_renderTexture.draw(it.sprite);
            }
        }

        m_renderTexture.display();
    }
}


void Game::update(sf::Time elapsedTime)
{
 
}

void Game::render()
{
    m_window.clear();
 
    auto& texture = m_renderTexture.getTexture();

    m_window.draw(sf::Sprite(texture));

    m_window.display();
}

void Game::handlePlayerInput(const sf::Keyboard::Key key, const bool isPressed) {

}

EDIT: And just to tell you the problem again. When I hit space to set tileMap[5][5] sprite color to red. The screen goes all white where the tiles once were and a red square (not tile sprite) shows up.

SOLVED: Okay, I just set the texture to a member variable and added it in the "keypressed(space)" section and I got it to work. I'd like to ask an additional question. Because I realized this worked without ever using m_renderTexture.clear() and m_renderTexture.display(). When exactly would I need to use this? I thought I used it every time I draw to a sf::RenderTexture?
« Last Edit: April 24, 2020, 08:57:49 pm by SFMLNewGuy »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: RenderTexture Help
« Reply #4 on: April 24, 2020, 09:35:21 pm »
Quote
Because I realized this worked without ever using m_renderTexture.clear() and m_renderTexture.display(). When exactly would I need to use this? I thought I used it every time I draw to a sf::RenderTexture?
clear() is optional, it's just a shorcut for filling the whole texture and avoid leftovers from a previous frame. But if you want to keep the old content on purpose, or if you cover the entire texture with the entities you draw, then you don't need it.
display() is mandatory, on some platforms it does nothing, but on others you may end up with a flipped texture (for example).
Laurent Gomila - SFML developer