Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

If I wanted to store extra data in a VBO for skinning (indices for indexing into an array of matrices of bones and floats for applying weights to those bones) How would I go about accessing that data in GLSL? I already know how to put the data in the buffer, interleaved with the rest of the data.

For example I want each vertex for a model to contain:

Vec3 position;
Vec3 normal;
Vec4 color;
Vec2 texCoords;
int boneCount;
int[3] boneIndex;
float[3] boneWeight;

Then drawing like:

bind(vertexBufferID);
glVertexPointer(3, GL11.GL_FLOAT, stridePlus, 0 * 4);
glNormalPointer(GL11.GL_FLOAT, stridePlus, 3 * 4);
glColorPointer(4, GL11.GL_FLOAT, stridePlus, (3 + 3) * 4);
glTexCoordPointer(2, GL11.GL_FLOAT, stridePlus, (3 + 3 + 4) * 4);
glVertexPointer(7, GL11.GL_FLOAT, stridePlus, (3 + 3 + 4 + 2) * 4);
glDrawArrays(GL11.GL_TRIANGLES, 0, VPNCTEnd);

Then in my vertex shader I want:

 //Get indices of bones
 //Get weights of bones
 //Get bone transforms
 //for each bone transform, apply it to gl_Position at the specified weight

What is the GLSL required for the last part of the process? It seems like I need to set a attribute pointer to the data somehow, but I'm not sure where to do that when the data is stored in the VBO.

share|improve this question
add comment

1 Answer

up vote 5 down vote accepted

First of all, you probably want to use glVertexAttribPointer on the application side to specify all the components, including the bone stuff, rather than the deprecated glVertexPointer and friends. Something like:

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, 0 * 4);  // Position
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, 3 * 4);  // Normals
// etc.
glVertexAttribPointer(4, 3, GL_INT, GL_FALSE, stride, (3 + 3 + 4 + 2) * 4);  // Bone indices
glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, stride, (3 + 3 + 4 + 2 + 3) * 4);  // Bone weights

You don't need a separate attribute for the bone count, since you can just zero the weights of unused slots (and set the index to 0 or something). The first argument to glVertexAttribPointer is the attribute index, and each attribute can store up to 4 values.

You'll also need to use glEnableVertexAttribArray to tell OpenGL which attributes you're using.

In the GLSL shader, you then access these by declaring them as attribute variables, like:

attribute vec3 Position;
attribute vec3 Normal;
// etc.
attribute vec3 BoneIndices;
attribute vec3 BoneWeights;

Finally, you can control which variables are mapped to which attribute by using glBindAttribLocation. You'd insert a bunch of these calls before linking the shader, which will tell OpenGL the desired correspondence between the variables and the attribute indices used in the glVertexAttribPointer calls. (There are also other ways to set up this mapping; a more in-depth discussion is at this StackOverflow question.)

share|improve this answer
    
Yeah, whenever I post any of my OpenGL code I hear how outdated it is :) When it comes to the graphics I usually just go with the first thing that works. I'll try out the more up-to-date calls :) I guess I might as well allow 4 bones for each vertex since I can stuff 4 values in the attribute anyway. –  Byte56 Aug 18 '12 at 0:36
    
I see your shader code is Cg code? Do you know how to access the attributes in GLSL code instead of Cg? –  Byte56 Aug 18 '12 at 3:45
    
@Byte56 Oops. You're right. Fixed! –  Nathan Reed Aug 18 '12 at 3:59
    
Thanks, this works great. –  Byte56 Aug 20 '12 at 17:41
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.