1
\$\begingroup\$

I want to generate a background, which is used in the game, on every instance of the game based on certain conditions. To do so, I'm using a sf::RenderTexture and a sf::Texture like this:

sf::RenderTexture image;
std::vector<sf::Texture> textures;
sf::Texture texture;
// instantiating the vector of textures and the image not shown here
for (int i = 0; i < certainSize; ++i)
{
    if(certainContition)
    {
        texture.setTexture("file");
        texture.setPosition(pos1, pos2);
    } else
    {
        ...
    }
image.draw(texture);
}

The point here is that I draw single textures on a sf::RenderTexture, but because textures always are on the graphic cards memory, I can't exceed a certain map size which I have to.
I also considered using an sf::Image, but I can't find a way to draw an image (i.e. a texture) to it.
The third way I found was using an sf::VertexArray, but this seems to be a bit too low-level for my rather simple purposes.
So is there a common way to dynamically generate a background image based on other existing images?

\$\endgroup\$
  • \$\begingroup\$ Of course you can repeat the image, if you have a seamless texture (otherwise you would have to generate it in code). The easiest way of rendering would be to set it to GL_REPEAT and just render it to screen based on the coordinates of the viewport. \$\endgroup\$ – danijar Nov 21 '13 at 7:37
1
\$\begingroup\$

I had the exact same problem and this is how I solved it.

I am not sure exactly what limit you are hitting. It could be that you are using only one sf::RenderTexture and are hitting the max texture size, or you are using more than one sf::RenderTexture and are hitting the graphics card memory limit.

If it is the first, you might consider using more than one texture and creating a tiled background image. You would split your background into a 256x256 or 512x512 (or maybe higher) grid and then render each tile that is currently in the view.

Something like:

//---BACKGROUND CREATION---//
std::vector<std::vector<sf::RenderTexture*>> background;
std::vector<std::Sprite*> sprites;
for(int x = 0; x < MAP_TILE_WIDTH; ++x)
{
    for(int y = 0; y < MAP_TILE_HEIGHT; ++y)
    {
        background[x][y] = new sf::RenderTexture(TILE_WIDTH, TILE_HEIGHT);
        background[x][y]->create(TILE_WIDTH, TILE_HEIGHT);
        background[x][y]->setView(sf::FloatRect(x * TILE_WIDTH, 
                                                y * TILE_HEIGHT, 
                                                TILE_WIDTH,
                                                TILE_HEIGHT));
    }
}
for(sf::Sprite *sprite : sprites)
{
    const sf::Vector2f &position = sprite->getPosition();
    background[position->x / TILE_WIDTH][position->y / TILE_HEIGHT]->draw(*sprite);
}

//---BACKGROUND RENDERING---//
sf::RenderWindow *window; // initialized somewhere else
const sf::Vector2f topLeft = window->mapPixelToCoords(sf::Vector2f(0,0));
const sf::Vector2f bottomRight = window->mapPixelToCoords(window->getView().getSize());
for(int x = topLeft.x / TILE_WIDTH; x <= bottomRight.x / TILE_WIDTH; ++x)
{
    for(int y = topLeft.y / TILE_HEIGHT; y <= bottomRight.y / TILE_HEIGHT; ++y)
    {
        window->draw(background[x][y]->getTexture());
    }
}

If your sprites are sized right and aligned well, this will work nicely. If your sprites can be across tile boundaries then you have to draw the sprites on all the tiles they are positioned over.

This works until you fill GPU memory with all your render textures then you have to move on to method 2 which is some type of streaming system. Tiles close to the view are loaded into an sf::Texture via the sf::Texture::loadFromImage() function while tiles farther away from the view are copied into an sf::Image for storing in system memory via the sf::Texture::copyToImage() function. This might cause some performance slowdown due to the copying back and forth from gpu memory but it is the only alternative to reducing the resolution of your images so they fit in GPU memory.

\$\endgroup\$
-1
\$\begingroup\$

what image format are you using as your backgroud images. some format such as png support transparency. here is a way of creating background image.

\$\endgroup\$
  • 1
    \$\begingroup\$ Hi @aclink, you didn't really answer this question. Although the question itself is unclear, it does not seem to be asking how to apply transparency. Also, if you link to a tutorial, try to also include the link's important content to avoid future dead link problems. And lastly, the question asks about using the C library SMFL, so a VB.net tutorial is unlikely to be helpful. \$\endgroup\$ – Seth Battin Oct 22 '13 at 5:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.