3
\$\begingroup\$

I'm currently worlking on a renderer for my projects and I want animate a sprite on screen. I've got a spritesheet but I don't know what is the the best way to update the texture coordinates for each vertex.

  • Update vertices then update vertex buffer. (Heavy ?)
  • Send to the shader my texture coordinates (It is possible ?)
  • Don't use VBO ?

By the way, I've got this structure : Object class with Geometry (Faces + Vertex + Buffer) and Material (Shader + other stuff ) properties, it is a good structure ?

Thanks!

\$\endgroup\$
2
  • \$\begingroup\$ Is the texture data interleaved with the other vertex data? If not it would easy to just update the texture data of a VBO, by just overwriting that part of the data. However, I don't know if that's a reasonable way to animate sprites, though I'm sure it would work. \$\endgroup\$
    – House
    Oct 10, 2012 at 21:51
  • \$\begingroup\$ @Byte56 : Yes, data is interleaved like that : { x, y, r, g, b, a, tx, ty }, I can eventually make a new material just for sprite object without interleaved data but I'm not sure it's a good idea. \$\endgroup\$
    – Dono
    Oct 10, 2012 at 21:55

2 Answers 2

4
\$\begingroup\$

IF you're using GLSL, pass a uniform or two into the fragment shader to say what x and y offsets you need to use to shift to the current frame / rect in the spritesheet / texture atlas, and then use those uniforms in the shader, to shift the texture coordinates appropriately. That's way better than having to reupload per-vertex data (i.e. texture coordinates) every frame.

I suppose it would be easier, too, if you set your GL_TEXTURE_WRAP_S and/or GL_TEXTURE_WRAP_T to mode GL_REPEAT rather than GL_CLAMP, since that would allow you to jump around the spritesheet more deftly. But it's not absolutely necessary, it's just the equivalent of using modulo in detecting where your next position should be so that you wrap to the next row of animation frames.

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

Create a VBO containing all of the sprite's frames, and make your glDrawArrays call with the appropriate (frameNumber * 4) in the first param.

If you want to get even more clever about it, you could make it a static VBO and do your billboarding formula in your vertex shader. The sprite origin would then become a shader uniform, as would the up and right (or left, as appropriate) vectors.

Sample vertex shader code:

uniform mat4 mvpMatrix;
uniform vec3 upVec;
uniform vec3 rightVec;
uniform vec3 spriteOrigin;

layout(location = 0) in vec2 position;
layout(location = 1) in vec2 texcoord;
.....
.....
gl_Position = mvpMatrix * vec4 (rightVec * position.y + (upVec * position.x + spriteOrigin), 1);

Filling the VBO (load-time only, adjust the indexes into framedata to suit the orientation of your texture):

framedata[0].positions[0] = frame->down;
framedata[0].positions[1] = frame->left;

framedata[0].texcoords[0] = // whatever
framedata[0].texcoords[1] = // whatever

framedata[1].positions[0] = frame->up;
framedata[1].positions[1] = frame->left;

framedata[1].texcoords[0] = // whatever
framedata[1].texcoords[1] = // whatever

framedata[2].positions[0] = frame->down;
framedata[2].positions[1] = frame->right;

framedata[2].texcoords[0] = // whatever
framedata[2].texcoords[1] = // whatever

framedata[3].positions[0] = frame->up;
framedata[3].positions[1] = frame->right;

framedata[3].texcoords[0] = // whatever
framedata[3].texcoords[1] = // whatever

glBufferSubData (
    GL_ARRAY_BUFFER,
    framenum * 4 * sizeof (spritevboframe),
    4 * sizeof (spritevboframe),
    framedata
);

Here, frame->up/down/left/right are just derived from the width and height of each frame; you could potentially double them up with the texcoords or it may be useful to keep them separate if you want to use different scalings.

Draw call:

glDrawArrays (GL_TRIANGLE_STRIP, frameNumber * 4, 4);

From here you can easily go more advanced and use instancing if you need to draw many sprites with the same frame; the uniform data above would become per-instance data. But that's a topic for another time.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .