やっとハードウェアスキニングに成功

どうにも気になるのでいろいろ試していたがやっとできた。
pythonでpmdのスキニングをやっても40FPSくらい出るようになった。元が7FPSくらいだったのでだいぶよい。モーフィングとIK解決はやっていないが。

とりあえず、使ったシェーダー。PMD用に2ボーンきめうち仕様にしている。

        attribute float bone_index0;
        attribute float bone_index1;
        attribute float bone_weight0;
        uniform mat4 skinning[%d];

        void main()
        {
            vec4 deformed;

            if(bone_weight0>0.999){
                deformed=skinning[int(bone_index0)] * gl_Vertex;
            }
            else if(bone_weight0<0.001){
                deformed=skinning[int(bone_index1)] * gl_Vertex;
            }
            else{
                deformed=
                skinning[int(bone_index0)] * gl_Vertex * bone_weight0
                +
                skinning[int(bone_index1)] * gl_Vertex * (1.0-bone_weight0);
            }

            gl_Position=gl_ModelViewProjectionMatrix * deformed;
            gl_FrontColor=gl_Color;
            gl_TexCoord[0]=gl_MultiTexCoord0;
        }

で、
uniform mat4 skinning[%d];
が問題で、うちのGeForce6200では60くらいが限界だった。
これにあわせてメッシュを分割する必要がある。
分割するとスキニング行列を個々の分割にあわせて並べなおしたり、ボーンの参照インデックスがずれるので調整してやったりといっためんどくさい処理が必要になる。この辺はpythonのディクショナリで適当にインデックスを弄くり回してやったのでそんなに苦労はしなかったがc++でやっていたら何回も設計変更して嫌になるところだ。
glDrawElementsはやめてglDrawArrays用に展開した方がよさそうだ。


あと、glslのデバッグがすべて勘頼みなのが問題だ。今日はわりと勘が当たったがいつもそうはいかないからなぁ。

最大の罠は、これ。
glVertexPointer(4, GL_FLOAT, 0, self.vertices)
4要素の同次座標にしないといけなかった。
atribute vec4 gl_Vertex
ってことなんだろうけどglVertexPointerはよきに計らってくれないよw
全部
glVertexAttribPointer
でやれってことなのか。

いずれにしろ、なにかGLSLのデバッガ的なものを開拓しないとシェーダーでいろいろやるのは難しいな。

参考

pyOpenGLでやったけど参考にしたのはこれ
http://www.codesampler.com/oglsrc/oglsrc_11.htm#ogl_skinning