SFML community forums

Help => Graphics => Topic started by: deadmau5 on November 23, 2012, 05:02:46 pm

Title: sf::Image -> sf::Texture -> sf::Sprite slow process
Post by: deadmau5 on November 23, 2012, 05:02:46 pm
Why is it that loading textures from files is such a slow process.
I'm either doing something wrong, or SFML is just too slow for my needs.

I load each tile in a tilesheet into an sf::Image using a subRect. All goes well and is pretty fast too.
Now the real problem is getting it into a texture using texture.loadFromImage which well then be put into a sprite for rendering.

I need to use it this way because I need image.createMaskFromColor to filter a certain color.
Is there a way to avoid loadFromImage without removing the createMaskFromColor functionality?

(I'm using SFML 2.0)
Title: Re: sf::Image -> sf::Texture -> sf::Sprite slow process
Post by: FRex on November 23, 2012, 05:14:29 pm
What do you mean by slow?
Title: Re: sf::Image -> sf::Texture -> sf::Sprite slow process
Post by: pdinklag on November 23, 2012, 05:38:05 pm
Is there a way to avoid loadFromImage without removing the createMaskFromColor functionality?
Other than storing your tileset in a 32-bit color format that has an alpha channel (e.g. PNG), no.

Concerning the "slowness" - I second FRex' question. What exactly do you mean by slow?
Title: Re: sf::Image -> sf::Texture -> sf::Sprite slow process
Post by: masskiller on November 23, 2012, 05:38:07 pm
Quote
Is there a way to avoid loadFromImage without removing the createMaskFromColor functionality?

No there isn't. And simply using the loadFromImage function of textures won't make your program slow, there must be something else going on. If you do the loading from images within the main loop it will generate FPS decrease because passing from an image (RAM), to a texture(GPU) is expensive timewise, as explained in the doc. But if you do it outside of the loop the time it takes shouldn't affect your program at all.
Title: Re: sf::Image -> sf::Texture -> sf::Sprite slow process
Post by: Nexus on November 23, 2012, 05:40:05 pm
Is there a way to avoid loadFromImage without removing the createMaskFromColor functionality?
No. Even sf::Texture::loadFromFile() constructs a temporary sf::Image, it is just a convenience function.

Please give us a minimal and complete example (http://en.sfml-dev.org/forums/index.php?topic=5559.msg36368#msg36368).
Title: Re: sf::Image -> sf::Texture -> sf::Sprite slow process
Post by: deadmau5 on November 23, 2012, 05:42:31 pm
What do you mean by slow?
As in not fast..

Say my map contains 1800 tiles.
What I mean by slow, is that the loading time will take up to 5-20 seconds for the whole map to be loaded for rendering. I need a faster method for loading images to textures.
Title: Re: sf::Image -> sf::Texture -> sf::Sprite slow process
Post by: deadmau5 on November 23, 2012, 05:47:39 pm
Removed*
Title: Re: sf::Image -> sf::Texture -> sf::Sprite slow process
Post by: FRex on November 23, 2012, 05:48:57 pm
By map with 1800 you mean 1800 instances of THAT class?
Title: Re: sf::Image -> sf::Texture -> sf::Sprite slow process
Post by: masskiller on November 23, 2012, 05:51:10 pm
A reference is better than a pointer in the draw function. As I explained in my post the RAM to GPU passing is what makes it slow, it's not a problem with an average amount of textures, but if it grows too big it can generate bad time issues like the one you are experiencing it seems.

Quote
By map with 1800 you mean 1800 instances of THAT class?

If this is your case then it's bound to be slow. There are better ways to work around it, but that depends on what you need done with those 1800 textures...
Title: Re: sf::Image -> sf::Texture -> sf::Sprite slow process
Post by: deadmau5 on November 23, 2012, 06:02:50 pm
A reference is better than a pointer in the draw function. As I explained in my post the RAM to GPU passing is what makes it slow, it's not a problem with an average amount of textures, but if it grows too big it can generate bad time issues like the one you are experiencing it seems.

Quote
By map with 1800 you mean 1800 instances of THAT class?

If this is your case then it's bound to be slow. There are better ways to work around it, but that depends on what you need done with those 1800 textures...
Well, I need to render it to the screen. Care to provide an example of how it can be done better ?
Title: Re: sf::Image -> sf::Texture -> sf::Sprite slow process
Post by: FRex on November 23, 2012, 06:09:12 pm
Quote
Well, I need to render it to the screen. Care to provide an example of how it can be done better ?
Inheriting from sf::Drawable.

If you really have 1800 instances of that class Tile then it's bad.
You copy image in every tile for no apparent reason, run the mask on that copy, keep that copy and create texture from it for every single tile.
That's not how it should be done if you aim for max efficiency, you should load your tilesheet into image(or few, if your tilesheet is very large) once, run mask on it once, create texture out of it once, get rid of image and then pass texture references and use sprites' sub rects or vertex arrays.
Title: Re: sf::Image -> sf::Texture -> sf::Sprite slow process
Post by: masskiller on November 23, 2012, 06:12:30 pm
It does depend on the usage they will have. In my game I can perfectly have more than 2000 (I actually need the 2000 for collisions, point calculations and what-more) bullets moving around at calculated positions with no FPS drop because the textures are small and I never use more than 2 or 3 different textures for such a high amount of moving objects and so on.

However if you need to map something static that requires to use tons of different textures you can use a VertexArray. But then again, if you don't specify what you want with your tiles you'll get no definitive answer, but rather just a bunch of 'perhaps' issues. Just saying you'll render them gets you nowhere.
Title: Re: sf::Image -> sf::Texture -> sf::Sprite slow process
Post by: deadmau5 on November 23, 2012, 06:15:01 pm
I load a tilesheet, then subrect a tile from that tilesheet and store it in a new Tile instance. My problem is loading, not rendering.
EDIT: I think I get it now, thanks for helping me.