• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            麒麟子

            ~~

            導航

            <2010年4月>
            28293031123
            45678910
            11121314151617
            18192021222324
            2526272829301
            2345678

            統計

            常用鏈接

            留言簿(12)

            隨筆分類

            隨筆檔案

            Friends

            WebSites

            積分與排名

            最新隨筆

            最新評論

            閱讀排行榜

            評論排行榜

            irrlicht引擎:硬件蒙皮骨骼動畫

            這個東西很順利,僅用了半小時就找到了方法,最應該感謝的還是Super TuxKart(簡稱STK,下面就都用這三字母了). 如果不明白STK,同時又對它感興趣的童鞋,可以訪問這里

            http://supertuxkart.sourceforge.net/

            由于墻的原因,需要各位搭梯子。

             

            上周末,在弄換裝的時候,發現irrlicht引擎本身是不支持硬件蒙皮的,多少令人有些失望。 心里就一直尋思著怎么擴展一下,將它弄出來。

            值得說明的是STK對irrlicht引擎的用法是很簡單的,基本上可以說是裸用,并未在irrlicht接口上做修改。 而是對外進行了一些必要的擴展。

            當然,STK也對外開放了一個irrlicht.dll,說是修改了其中的BUG。 但直接使用irrlicht是可以的。

             

            廢話不多說,來說說如何不修改irrlicht一行代碼,通過外部擴展來實現硬件骨骼動畫吧

             

            首先,能夠使我們不修改irrlicht代碼的原因,是因為ISkinnedMesh提供了一個setHardwareSkinning接口,默認為false.

            雖然這個接口的說明是"(This feature is not implemented in irrlicht yet)”,但并不代表,設置與不設置無差別。

            查看代碼可以發現,當你設置了這個為true以后,irrlicht就完全不管你的動畫了。 意思就是,要是你非要讓我干我不干不了的事,那就只有您另請高明了。

            irrlicht連CPU計算都不會參與。 這正好讓我們有機可乘,完全用GPU接管。

             

            而要讓一個頂點參與骨骼計算,那骨骼索引則是少不了的。所以,我們需要想辦法讓頂點數據能夠將骨骼索引代入SHADER中。

            在STK中用了一種巧妙的方法, 就是使用了頂點的顏色數據, 雖然這樣一來,頂點顏色就用不了了。 但在模型渲染時,頂點顏色很少被使用到的。 也就是說,頂點顏色在STK的動畫模型中,被用作了骨骼索引。

            初始化骨骼索引的方法很簡單,用下面的代碼遍歷即可。

            設:我們有一個骨骼動畫模型是 ISkinnedMesh* pSkinnedMesh = …

            那么:初始化代碼如下

            for(u32 i = 0;i < pSkinnedMesh ->getMeshBuffers().size();++i)
            {
                for(u32 g = 0;g < pSkinnedMesh ->getMeshBuffers()[i]->getVertexCount();++g)
                {
                    pSkinnedMesh ->getMeshBuffers()[i]->getVertex(g)->Color = video::SColor(0,0,0,0);
                }
            }

            //初始化完畢以后,就是需要真正的索引賦值了,通過以下代碼可以完成

            const core::array<scene::ISkinnedMesh::SJoint*>& joints = pSkinnedMesh ->getAllJoints();
            for(u32 i = 0;i < joints.size();++i)
            {
                const core::array<scene::ISkinnedMesh::SWeight>&    weights = joints[i]->Weights;
                for(u32 j = 0;j < weights.size();++j)
                {
                    int buffId = weights[j].buffer_id;

                    int vertexId = pSkinedMesh->getAllJoints()[i]->Weights[j].vertex_id;
                    video::SColor* vColor = &pSkinedMesh->getMeshBuffers()[buffId]->getVertex(vertexId)->Color;

                    if(vColor->getRed() == 0)
                        vColor->setRed(i + 1);
                    else if(vColor->getGreen() == 0)
                        vColor->setGreen(i + 1);
                    else if(vColor->getBlue() == 0)
                        vColor->setBlue(i + 1);
                    else if(vColor->getAlpha() == 0)
                        vColor->setAlpha(i + 1);
                }
            }

             

            //經過以上兩個步驟,頂點數據改造完成。 值得注意的是, 在這里, 索引 0 是被認為是無效的

             

            然后,我們來創建一個SHADER作為渲染。

            假設 我們將這個pSkinnedMesh綁定了到了一個IAnimatedSceneNode* node 上。

            那,我們為這個結點創建一個材質 在創建材質前,我們需要準備一個SHADER回調。 SHADER回調就像下面一樣就可以了。

            class HWSkinCallBack:public video::IShaderConstantSetCallBack
            {
                scene::IAnimatedMeshSceneNode* m_pNode;
            public:
                HWSkinCallBack(scene::IAnimatedMeshSceneNode* node):m_pNode(node)
                {

                }
                virtual void OnSetConstants(video::IMaterialRendererServices* services,
                    s32 userData)
                {
                    scene::ISkinnedMesh* mesh = (scene::ISkinnedMesh*)m_pNode->getMesh();
                    f32 joints_data[55 * 16];
                    int copyIncrement = 0;

                    const core::array<scene::ISkinnedMesh::SJoint*> joints = mesh->getAllJoints();
                    for(u32 i = 0;i < joints.size();++i)
                    {
                        core::matrix4 joint_vertex_pull(core::matrix4::EM4CONST_NOTHING);
                        joint_vertex_pull.setbyproduct(joints[i]->GlobalAnimatedMatrix, joints[i]->GlobalInversedMatrix);

                        f32* pointer = joints_data + copyIncrement;
                        for(int i = 0;i < 16;++i)
                            *pointer++ = joint_vertex_pull[i];

                        copyIncrement += 16;
                    }

                    services->setVertexShaderConstant("JointTransform", joints_data, mesh->getAllJoints().size() * 16);
                }
            };

             

            好了,現在我們來創建一個材質

            s32 hwskm = gpu->addHighLevelShaderMaterialFromFiles(
                    "../../skinning.vert","main",video::EVST_VS_2_0,
                    "","main",video::EPST_PS_2_0,&hwc,video::EMT_SOLID);

            //用新創建出來的材質賦值給這個結點

            node->setMaterialType((video::E_MATERIAL_TYPE)hwskm );

             

            //到此,設置完畢。

            //最后,就是skinning.vert本身的內容了。 貼出來即可,沒有太多技巧,就是一個普通的蒙皮。

            // skinning.vert

            #define MAX_JOINT_NUM 36
            #define MAX_LIGHT_NUM 8

            uniform mat4 JointTransform[MAX_JOINT_NUM];

            void main()
            {
                int index;
                vec4 ecPos;
                vec3 normal;
                vec3 light_dir;
                float n_dot_l;
                float dist;

                mat4 ModelTransform = gl_ModelViewProjectionMatrix;
                index = int(gl_Color.r * 255.99);
                mat4 vertTran = JointTransform[index - 1];
                index = int(gl_Color.g * 255.99);
                if(index > 0)
                    vertTran += JointTransform[index - 1];

                index = int(gl_Color.b * 255.99);
                if(index > 0)
                    vertTran += JointTransform[index - 1];
                index = int(gl_Color.a * 255.99);
                if(index > 0)
                    vertTran += JointTransform[index - 1];
                ecPos = gl_ModelViewMatrix * vertTran * gl_Vertex;
                normal = normalize(gl_NormalMatrix * mat3(vertTran) * gl_Normal);
                gl_FrontColor = vec4(0,0,0,0);
                for(int i = 0;i < MAX_LIGHT_NUM;i++)
                {
                    light_dir = vec3(gl_LightSource[i].position-ecPos);
                    n_dot_l = max(dot(normal, normalize(light_dir)), 0.0);
                    dist = length(light_dir);
                    n_dot_l *= 1.0 / (gl_LightSource[0].constantAttenuation + gl_LightSource[0].linearAttenuation * dist);
                    gl_FrontColor += gl_LightSource[i].diffuse * n_dot_l;
                }
                gl_FrontColor = clamp(gl_FrontColor,0.3,1.0);

                ModelTransform *= vertTran;
                gl_Position = ModelTransform * gl_Vertex;
                gl_TexCoord[0] = gl_MultiTexCoord0;
                gl_TexCoord[1] = gl_MultiTexCoord1;
                /*
                // Reflections.
                vec3 r = reflect( ecPos.xyz , normal );
                float m = 2.0 * sqrt( r.x*r.x + r.y*r.y + (r.z+1.0)*(r.z+1.0) );
                gl_TexCoord[1].s = r.x/m + 0.5;
                gl_TexCoord[1].t = r.y/m + 0.5;
                */
            }

             

             

            //注:這是GLSL 2.0, 在用IRR做測試的時候,要選GL驅動方式。

             

            還是上個圖吧,不上圖感覺沒有真像。 雖然圖看不出來什么動作

            image

            為了說明它真的在動,不得不上第二張。

             

            image 

             

            在此,十分感謝Super Tux Kart. 提供了一個學習和擴展irrlicht的榜樣.

            posted on 2013-03-26 00:08 麒麟子 閱讀(3348) 評論(0)  編輯 收藏 引用 所屬分類: Game and EngineIrrlicht

            久久精品无码一区二区三区日韩 | 国产精品成人精品久久久 | 99久久国产亚洲综合精品| 四虎国产精品成人免费久久| 伊人久久大香线蕉av不卡| 久久99毛片免费观看不卡| 国产一区二区精品久久凹凸| 久久久噜噜噜久久中文字幕色伊伊| 色8久久人人97超碰香蕉987| 久久噜噜久久久精品66| 久久久无码精品亚洲日韩蜜臀浪潮| 久久AⅤ人妻少妇嫩草影院| 香蕉久久夜色精品升级完成| 国产免费久久精品99久久| 久久精品国产亚洲av水果派| 久久久久一级精品亚洲国产成人综合AV区 | 日本久久中文字幕| 久久久久一区二区三区| 久久精品欧美日韩精品| 亚洲av伊人久久综合密臀性色 | 久久青青草原精品影院| 77777亚洲午夜久久多人| 国产亚洲色婷婷久久99精品91| 久久香蕉国产线看观看精品yw| 精品无码人妻久久久久久| 久久99国产精品久久99果冻传媒| 久久综合亚洲色一区二区三区 | 精品无码久久久久国产| 久久久久久精品无码人妻| 色综合久久中文字幕综合网| 2020最新久久久视精品爱| 日本三级久久网| 亚洲成人精品久久| 成人精品一区二区久久久| 久久久久久综合一区中文字幕| 久久99国产精品一区二区| 狠狠色婷婷综合天天久久丁香| 久久国产精品久久国产精品| 99久久国产综合精品网成人影院| 国产福利电影一区二区三区久久久久成人精品综合 | 国产精品一区二区久久精品无码|