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

Author Topic: Simple way to merge textures  (Read 10863 times)

0 Members and 1 Guest are viewing this topic.

luiscubal

  • Jr. Member
  • **
  • Posts: 58
    • View Profile
Simple way to merge textures
« on: October 06, 2011, 06:25:34 pm »
Apparently, the new SFML 2 Graphics API will allow things to "batch" multiple drawing calls, provided they use the same texture.

The trick I'm proposing is to have a new class, such as TexturePack, to "pack" many textures in a single one. These textures would have a bunch of shared properties(for instance, either they are all smooth or none of them are smooth).

The idea is that, internally, SFML would merge all textures into a single bigger one(with perhaps each texture having a border to ensure that smoothing wouldn't pick parts of the other textures). Internally, it would be a single texture so many calls using it could be batched. The public API would be like handling multiple textures.

Of course, using TexturePacks incorrectly would cause *worse* performance, so it really needs to be a separate class and not a built-in Texture feature. This could perhaps come in a later SFML version(such as 2.x), since it seems like the kind of thing that shouldn't be too hard to add once the basic graphics API is done.

What do you think?

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Simple way to merge textures
« Reply #1 on: October 06, 2011, 06:29:41 pm »
Haha, I just had the same idea. I already wrote my post, but now I deleted it. Here it is in its original form:

There have already been similar discussions. However, before sf::Image and sf::Texture have been split, it was not possible at all to load textures whose size exceed the size supported by the graphics card.

Laurent, I don't think you are going to implement automatic split functionality for big textures in SFML, are you? Otherwise, I think about an addition in Thor, since big background textures are still a relatively often-used feature.

The disadvantage when I implement it is that thor::LargeTexture won't integrate well with other parts of SFML, such as sf::Sprite. There would have to be a thor::LargeSprite as well, with a huge amount of code duplication ;)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Simple way to merge textures
« Reply #2 on: October 06, 2011, 06:32:24 pm »
It becomes hard to manage, when you have an object that depends on other external objects. How would the texture-pack handle a modification in one of its textures? How would it even know about it?

People should rather pack their textures manually with an image editor. It causes much less troubles in my opinion.
Laurent Gomila - SFML developer

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Simple way to merge textures
« Reply #3 on: October 06, 2011, 06:35:32 pm »
Quote
Haha, I just had the same idea

I don't think it's the same idea. Yours is about loading big images without explicitely splitting it into several textures. luiscubal's idea is (if I understand correctly) to define an API that would help gathering several separate textures into one, for performances reasons.

Quote
The disadvantage when I implement it is that thor::LargeTexture won't integrate well with other parts of SFML, such as sf::Sprite. There would have to be a thor::LargeSprite as well, with a huge amount of code duplication

Absolutely. If I could handle big images without modifying sf::Sprite and sf::Texture, it would already been done ;)

But since big images are usually displayed entirely, with a single sprite, I think it can be a good idea to create a dedicated class (that merges large sprite and large texture together) for that. And don't worry about duplicating sf::Sprite's code, with the new API it is ridiculously small.
Laurent Gomila - SFML developer

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Simple way to merge textures
« Reply #4 on: October 06, 2011, 06:41:25 pm »
Quote from: "Laurent"
Absolutely. If I could handle big images without modifying sf::Sprite and sf::Texture, it would already been done ;)
Well, at least sf::Texture would have to be modified anyway. If its implementation details are well encapsulated, it should theoretically be possible to leave sf::Sprite. But I don't know too much about SFML internals, so it's just an assumption.

Quote from: "Laurent"
And don't worry about duplicating sf::Sprite's code, with the new API it is ridiculously small.
Okay, this may indeed be true. But then I need to hack something manually together to fix this Airport bug as soon as possible :D
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

luiscubal

  • Jr. Member
  • **
  • Posts: 58
    • View Profile
Simple way to merge textures
« Reply #5 on: October 06, 2011, 06:51:29 pm »
Quote
luiscubal's idea is (if I understand correctly) to define an API that would help gathering several separate textures into one, for performances reasons.

Yes, that's it.

Quote
How would the texture-pack handle a modification in one of its textures? How would it even know about it?

Whichever way is easiest for the person who'd end up implementing that class.
One could say that the textures are copied(and so changes would be ignored), or maybe "lock" all base textures, or even say that it is undefined behavior.
Or maybe even the data would have to be all passed to the constructor directly, so there could be no way to even change the base textures.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Simple way to merge textures
« Reply #6 on: October 06, 2011, 07:04:56 pm »
Quote
One could say that the textures are copied(and so changes would be ignored), or maybe "lock" all base textures, or even say that it is undefined behavior.
Or maybe even the data would have to be all passed to the constructor directly, so there could be no way to even change the base textures.

The only solution is indeed to keep copy the textures and don't care about what happens then to the original ones. But then you don't need a special class for this, you can use Image::Copy to build your texture-pack at init-time and just use it directly.
Laurent Gomila - SFML developer

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Simple way to merge textures
« Reply #7 on: October 06, 2011, 07:29:09 pm »
By the way, the BigSprite class could really be easy to implement.

Code: [Select]
class BigSprite : public sf::Transformable, public sf::Drawable
{
public:

    BigSprite(const sf::Image& source)
    {
        unsigned int size = sf::Texture::GetMaximumSize();
        for (unsigned int i = 0; i < source.GetWidth(); i += size)
            for (unsigned int j = 0; j < source.GetHeight(); j += size)
            {
                sf::Texture texture;
                texture.LoadFromImage(source, sf::IntRect(i, j, size, size));
                myTextures.push_back(texture);

                sf::Sprite sprite(myTextures.back());
                sprite.SetPosition(i, j);
                mySprites.push_back(sprite);
            }
    }

    // set/get smooth...

private:

    void Draw(sf::RenderTarget& target) const
    {
        for (std::list<sf::Sprite>::const_iterator it = mySprites.begin(); it != mySprites.end(); ++it)
        {
            // combine self's transform with the current sprite's transform (API not defined yet)
            target.Draw(*it);
        }
    }

    std::list<sf::Sprite> mySprites;
    std::list<sf::Texture> myTextures;
};
Laurent Gomila - SFML developer

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Simple way to merge textures
« Reply #8 on: October 06, 2011, 07:56:26 pm »
Thank you! I was already implementing something similar with the old API. And of course, my for loop and indexing was unnecessarily complicated :D

Wouldn't you split it into LargeSprite and LargeTexture, like in SFML? Then the code becomes more complicated, but is more flexible... The question is whether thor::LargeSprite and thor::LargeTexture should be drop-in replacements for sf::Sprite and sf::Texture, or if they (or one class) should be specialized to the most common use case.

Other functionality like SetSubRect() is getting ugly anyway, if it is provided.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Simple way to merge textures
« Reply #9 on: October 06, 2011, 08:10:11 pm »
Quote
Wouldn't you split it into LargeSprite and LargeTexture, like in SFML? Then the code becomes more complicated, but is more flexible...

Like I said, I don't know what kind of flexibility we would need there. I think that its use case is very specific (load and display, nothing fancy), so its API should be limited to the minimum. Adding SetSubRect etc. would make no sense -- split the original image if you have several "sprites" in it, and use the regular sf::Sprite/sf::Texture.
Laurent Gomila - SFML developer

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Simple way to merge textures
« Reply #10 on: October 06, 2011, 09:04:23 pm »
I agree in some points you mention, and SetSubRect() is probably really not appropriate. However copy semantics are much more elegant and faster with separated sprite and texture.

In Airport, you may have noticed that the background is also used in the main menu, but darkened. I achieve this in the following way:
Code: [Select]
// in game
sf::Sprite background(GetBackgroundTexture());
...
window.Draw(background);

// in menu
sf::Sprite background(GetBackgroundTexture());
background.SetColor(darkGray);
...
window.Draw(background);

With one monolithic BigSprite, I either have to keep twice the exactly same texture in memory, or change a single object all the time. The latter introduces side effects and prevents const.
It's a little bit like the sf::Music class, but for music, a separate resource and user-frontend class don't make much sense because of the stream nature.

And I need to implement copy constructor and assignment operator myself to ensure the sprites refer to the correct textures. Or directly make the class noncopyable...

Additionally, it would be easier to port existing code to big textures if the big-texture API were similar to SFML.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Simple way to merge textures
« Reply #11 on: October 06, 2011, 10:32:02 pm »
Hehe yes you're right ;)

I didn't really think about it deeply, that was just an idea while writing my answer.

Anyway, that won't be integrated to SFML, but I think it will be a good addition to Thor.

But... I think we are far away from the original feature request now ;)
Laurent Gomila - SFML developer

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Simple way to merge textures
« Reply #12 on: October 06, 2011, 10:38:32 pm »
Thanks for the inspiration and discussion! I'm currently implementing it in Thor since I need it anyway to fix the Airport bug. Furthermore I think the changes won't be huge if the new SFML graphics API is ready, and they will probably only concern the implementation.

And sorry for the thread-hijacking. Don't hesitate to split our discussion into another thread if you think it's better like this ;)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

 

anything