Hello guys,
I’m wondering what it’s the best way to display an animation of sprites
For now, I load all my sprites and I store them in a vector
But I think that will be better if I would load them in the GPU ?
Is that possible ?
Hello guys,
I’m wondering what it’s the best way to display an animation of sprites
For now, I load all my sprites and I store them in a vector
But I think that will be better if I would load them in the GPU ?
Is that possible ?
Hi,
You might want to take a look here.
There are a bunch of great ways to do it. Using a spritesheet is definitely one of them. An advantage of something like a spritesheet is that when openGL binds a texture, it only has to do it once per frame, and not multiple times for different textures. This is especially helpful if you have a lot of instances of the same sprite on screen at once.
In the past when I’ve needed to bind a lot of textures and needed great performance, I’ve used 2D sampler arrays. These will let you pass in “3D” arrays of textures, and I think on my system I can pass up to 2048. GL_TEXTURE_2D_ARRAY
is the thing to google. You’ll need to write a custom shader, and then in the texture lookup, you pass in a vec3 instead of a vec2, where the z
is an index for which texture you’re looking up.
Lastly, a while back I made a simple block for animated gifs. New block - ciAnimatedGif Depending on your app structure and performance needs, this can also work in a pinch.
TLDR: Try spritesheets, and gifs in that order. If you need performance, check out GL_TEXTURE_2D_ARRAY
.
Thanks for your answer,
I try to create a shader by myself, with the cinder’s guide but i don’t understand how to use shaders with my images, so do you have any tips ?
Take a look at the shader guide:
https://libcinder.org/docs/guides/opengl/part5.html
In the section of texture loading you can add more textures to your fragment shader.
uniform sampler2D uTex0;
uniform sampler2D uTex1;
....
uniform sampler2D uTexN;
The pass it like this
mGlsl->uniform( "uTex0", texture0->getId() );
mGlsl->uniform( "uTex1", texture1->getId() );
...
mGlsl->uniform( "uTexN", textureN->getId() );
I think you can upload the textures just once, but not sure.
You can also control wich texture to draw if you already have a vector of textures:
mGlsl->uniform( "uTex0", textures[id]->getId());
That’s incorrect. The uniform should be set to the texture unit the texture is bound to. So for instance:
texture0->bind( 10 ); // unit can be chosen freely up to a maximum
texture1->bind( 11 );
mGlsl->uniform( "uTex0", 10 );
mGlsl->uniform( "uTex1", 11 );
It’s better to do the following, though:
gl::ScopedTextureBind scpTex0( texture0, 10 );
gl::ScopedGlslProg scpGlsl( mGlsl );
mGlsl->uniform( "uTex0", 10 );
That way, the OpenGL state will be restored when you’re done drawing. It’s good to get into the habit of managing your state like that.
As @Xumo correctly pointed out, you only need to bind your textures once (if you’re not going to reuse that texture unit for something else), for example in your setup()
. And if you do, you also only need to set the uniform once.
-Paul