8
\$\begingroup\$

I'm a newbie to modern OpenGL. I'm comfortable with the immediate OpenGL methodology, but I've never done any serious use of VBOs. My question is about animation. In immediate mode, to achieve animation you just have to stream different vertex positions (interpolated from keyframes) in object space.

How is this achieved in non-immediate OpenGL? Obviously, uploading fresh VBO data for each frame is sure going to hog the graphics bus. I haven't found any literature about the modern way to do it. Thinking about it, I came to several options:

  • Attributes: animation as a 3d offset. For each frame, a different (possible interpolated) offset attribute is passed for each vertex, applied to the same vertex each keyframe.
  • Indices: storing keyframes as absolute vertices and accesing them through indexing, using a different set of vertices for every keyframe. I find this approach impossible, since you can't access adjacent keyframes and therefore can't interpolate between them. Also, seems like a bad idea for procedural animation.
  • Texture: this might be very stretchy but sounds like a good solution for me. Again, animation is thought as an xyz offset for each vertex. Each keyframe can be stored in a 1D texture where the dimension maps to vertexID.If I'm not mistaken, in OpenGL 4.0 you can access textures from any shader, so you could read this texture from the vertex shader and apply each vertex transformation. A 2D texture could hold several frames. You still perform interpolation (and if interpolation works for textures outside of fragment shader, which I'm not sure of, you can linearly interpolate for free!) This could be applied to more complex animation systems like bone animation without much effort.

Am I overthinking this? Can anyone shed some light?

\$\endgroup\$

1 Answer 1

5
\$\begingroup\$

I haven't found any literature about the modern way to do it.

That's generally because the "modern way" to have character animation is to use skeletal bone weighing, not vertex blending.

However, if you insist on doing vertex blend-based animation, you can. The simplest way is to simply send the two keyframes you want to blend between as the attributes. You have position data for all of the various keyframes; just use glVertexAttribPointer (or glVertexPointer if you insist) to pick specific keyframes. Since each keyframe should have its position data stored in the same order (for corresponding positions), they can use the same index list for rendering.

The shader gets two "position" attributes, one for the keyframe in front of the current time and one for the keyframe after. You would also pass a uniform that specifies how much of a blend to do between them. You compute the new position as a blend between the two keyframes, and then do the usual transforms from there.

\$\endgroup\$
6
  • \$\begingroup\$ Do you have any recommended books or articles to read to get started on learning about writing code to handle skeletal bone weighing? \$\endgroup\$ Commented Dec 13, 2011 at 5:19
  • \$\begingroup\$ I was looking for the "how to move vertices" not how to do the actual animation. Well, it's not so different with skeletal bone weighting, after all, it comes down to vertices moving around, wether it's precomputed (vertex-blended) or on-the-fly bone weighted. Are attributes the only way to go still? Isn't the texture based approach still feasible, and faster than passing around a lot of data for each vertex every frame? (at least both keyframes per-bone and the blend factor) A texture can still encode bone rotation, and texture lookup is much faster than passing around attributes. \$\endgroup\$
    – kaoD
    Commented Dec 13, 2011 at 12:56
  • \$\begingroup\$ Also: "Since each keyframe should have its position data stored [...] they can use the same index list for rendering." Isn't that impossible? How could I access two indices to interpolate between? Isn't the vertex shader oblivious to each other vertex, and even more to other indices? \$\endgroup\$
    – kaoD
    Commented Dec 13, 2011 at 13:02
  • \$\begingroup\$ @kaoD: Impossible? Isn't that what you do currently to compute the new vertex position? For each position in each keyframe array, you blend them together and write them to the OpenGL. All I'm saying is that you provide those keyframe arrays to OpenGL and let the shader do the blending. As for texture lookups, in the hierarchy of "fast things in shaders", texture lookups are generally at the bottom. Attributes are, more or less free. \$\endgroup\$ Commented Dec 13, 2011 at 17:52
  • \$\begingroup\$ @NicolBolas: good to know that texture lookup is slower than I thought. What I mean with impossible is that, if I'm not mistaken, each vertex can only 'see' itself in the shader, and therefore can't index other vertices or access any other arrays (keyframes.) What I understand from your answer is that I have to pass these two keyframe positions as attribs for each vertex, along with a blend factor uniform, but then I would have no vertex array, would I? Although I just realized you can use current keyframe as the vertex array and the next frame as the attribute array, is this what you meant? \$\endgroup\$
    – kaoD
    Commented Dec 13, 2011 at 18:21

You must log in to answer this question.

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