WoW骨骼动画的GLSL实现收藏
在OpenGL.org论坛上不幸被告知VERTEX_BLEND_ARB扩展不属OpenGL核心标准,被ARB卡查掉了,Nvidia也不实现了,所以在OpenGL下要做骨骼动画只好靠Shader了,让CPU计算,效率会很惨,写写Demo还凑和.
使用指令将顶点的骨骼和权重信息作为Generic Attribute属性传入给Shader对象.
GLint indexBone = glGetAttribLocationARB(m_glPrograme, "bone");
GLint indexWeight = glGetAttribLocationARB(m_glPrograme, "weight");
glVertexAttribPointerARB(indexBone, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(MDL_VERTEX), m_arrMdlVertices[0].bones);
glVertexAttribPointerARB(indexWeight, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(MDL_VERTEX), m_arrMdlVertices[0].weights);
glEnableVertexAttribArrayARB(indexBone);
glEnableVertexAttribArrayARB(indexWeight);
在每帧在CPU中计算骨骼矩阵,并将计算好的骨骼矩阵数组传入Shader对象.
GLint indexBoneMatrices = glGetUniformLocationARB(m_model.m_glPrograme, "boneMatrices");
for(unsigned int i = 0; i < m_animSkeleton.m_vecBones.size(); i++)
{
CM2Bone* pBone = m_animSkeleton.m_vecBones[i];
glUniformMatrix4fvARB(indexBoneMatrices + i, 1, GL_TRUE, pBone->m_transformMatrix);
}
搞定,运行,发现wow的兽人模型竟然有128个骨骼,而N6200的shader的Uniform Matrix参数最多只给60个,还得考虑低端机器,玻璃渣是怎么做的?发现DX的实现从来就是送入硬件处理的,节省了额外的顶点内存,加快了速度,确实是不二的选择.
attribute vec4 weight;
uniform mat4 boneMatrices[60 ];
const float fw = 1.0 / 255.0 ;
void main()
{
vec4 blendVertex;
vec4 blendWeight = weight;
ivec4 blendBone = (ivec4)bone;
for(int i = 0; i < 4; i++)
{
if(blendWeight.x > 0.0)
{
blendVertex += vec4((boneMatrices[blendBone.x] * gl_Vertex).xyz, 1.0) * blendWeight.x * fw;
blendBone = blendBone.yzwx;
blendWeight = blendWeight.yzwx;
}
else break;
}
gl_Position = gl_ModelViewProjectionMatrix * blendVertex;
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_FrontColor = gl_Color;
}