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.
Answer
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.)
No comments:
Post a Comment