前面兩小節分別說明了骨骼動畫的數學原理和一種骨骼動畫格式m3d的讀取,這一節講解渲染的思路。
其實,進行骨骼動畫的渲染,整體思路是:
第一,求出某個動畫片段下某乙個時間點下所有骨骼的finalmatrix(由骨骼在某一幀的pos,scale,quat求出)
第二,由於「第一」中渲染骨骼動畫的時間點可能不在整數幀數上,比如我假設某個動畫片段存在50幀畫面,開始時間為0s,結束時間為2.0s,而第48幀畫面的開始時間為1.8s,第49幀的畫面的開始時間為1.9s,而假設你想渲染的動畫時間點為1.85s,所以你想求出所有骨骼的finalmatrix,就需要進行相應的插值,進行平滑過度。
//得到某個骨頭在時間t的變換矩陣
void boneanimation::interpolate(float t, xmfloat4x4& m)const
else if (t >= keyframes.back().timepos)
else}}}
//得到所有骨頭在時間t的變換矩陣陣列,bonetransform[i]代表第i根骨頭在時間t的變換矩陣
void animationclip::interpolate(float t, vector& bonetransform)const
}
bool graphicsclass::renderskeletalcharacter(float deltatime)
//更新第乙個人物的骨骼動畫時間
mcharacterinstance1.update(deltatime);
/*---------------繪製第乙個人物例項(characterinstance1)--------------------*/
//第一,(更新)獲取viewmatrix(根據cameraclass的mpostion和mrotation來生成的)
mfirstcameraclass->updateviewmatrix();
//第二,獲取三個變換矩陣(worldmatrix和projmatrixviewmatrix來自cameraclass)
worldmatrix =xmloadfloat4x4(&mcharacterinstance1.world);
viewmatrix = mfirstcameraclass->getviewmatrix();
projmatrix = md3d->getprojmatrix();
//第三,進行渲染(人物頂點資料,索引資料,各種常量快取,紋理資源等)
for (uint subset = 0; subset < mcharacterinstance1.model->subsetcount; ++subset)
return true;
}
skeletalcharactershader.fx
texture2d diffusemap:register(t0); //漫反射紋理資源
texture2d normalmap:register(t1); //法線紋理資源
samplerstate sampletype:register(s0); //取樣方式
//vertexshader
cbuffer cbmatrix:register(b0)
;cbuffer cblight:register(b1)
cbuffer cbbonetranform:register(b2)
cbuffer material : register(b3)
cbuffer camera : register(b4)
struct vertexin
;struct vertexout
;float3 normalsampletoworldspace(float3 normalmapsample, float3 unitnormalw, float4 tangentw)
vertexout vs(vertexin ina)
; weights[0] = ina.weights.x;
weights[1] = ina.weights.y;
weights[2] = ina.weights.z;
weights[3] = 1- ina.weights.x- ina.weights.y- ina.weights.z;
float3 posl = float3(0.0f, 0.0f, 0.0f);
float3 normall= float3(0.0f, 0.0f, 0.0f);
float3 tangentl = float3(0.0f, 0.0f, 0.0f);
//將頂點按骨骼權重比進行相應的骨骼變換
for (int i = 0; i < 4; ++i)
//變換到齊次裁剪空間
= mul(ina.posl, world); float3*float4x4 這個並不報錯,忽略了分值w為1.0f
outa.pos = mul(float4(posl, 1.0f), world);
outa.w_pos = outa.pos.xyz;
outa.pos = mul(outa.pos, view);
outa.pos = mul(outa.pos, proj);
//法線變換到世界空間
outa.w_normal = mul(normall, (float3x3)worldinvtranspose); //此事世界逆轉置矩陣的第四行本來就沒啥用
outa.w_normal = normalize(outa.w_normal);
outa.tex= ina.tex;
//切線變換到世界空間
outa.w_tangent = float4(normalize(mul(tangentl, (float3x3)world)), ina.tangentl.w);
return outa;
}float4 ps(vertexout outa) : sv_target
程式執行gif畫面:
//第二十二,例項化skinmodelclass
mcharacterinstance1.model = mcharactermodel;
mcharacterinstance2.model = mcharactermodel;
mcharacterinstance1.timepos = 0.0f;
mcharacterinstance2.timepos = 0.0f;
mcharacterinstance1.clipname = "take1";
mcharacterinstance2.clipname = "take1";
mcharacterinstance1.finaltransforms.resize(mcharactermodel->skinneddata.bonecount());
mcharacterinstance2.finaltransforms.resize(mcharactermodel->skinneddata.bonecount());
xmmatrix modelscale = xmmatrixscaling(0.15f, 0.15f, -0.15f); //
xmmatrix modelrot = xmmatrixrotationy(0);
xmmatrix modeloffset = xmmatrixtranslation(55.0f, 10.0f, 36.0f);
xmstorefloat4x4(&mcharacterinstance1.world, modelscale*modelrot*modeloffset);
xmstorefloat4x4(&mcharacterinstance2.world, modelscale*modelrot*modeloffset);
若不將座標進行z翻轉(乘以負數),人物的渲染結果將出現問題,如下所示:
在寫骨骼動畫渲染的時候,碰上了記憶體訪問錯誤問題,如下圖所示:
一般這種問題的出現,是你訪問了未分配記憶體的位址或者是訪問null指標指向的位址。
在寫這個demo的時候。碰上乙個到目前為止都沒碰上的問題,就是使用float3的posl乘以float4x4,導致圖形完全無法顯示,如下所示:
outa.pos = mul(ina.posl, world)
其中outa.pos為float4型別, float3*float4x4按道理編譯shader會報錯,但實際上並沒有報錯,導致了outa.pos.w預設值為0,而讓圖形無法顯示,這種錯誤有時候真的難以察覺,因為圖形無法顯示,連debug vertexshader和pixelshader的機會都沒有。 Directx11教程四十三之glow 邊緣發光
這一節教程是關於渲染3d物體的發光邊緣,結構如下 這裡借用下虛幻四引擎演示下 邊緣發光效果 如下圖所示 如上面圖中虛幻四引擎中被選中的立方體的邊緣是發光的,我實現的就是這種發光效果 這裡有篇部落格介紹了 glow 是怎麼實現的 unity3d shader 著色器 給物體邊緣加高光輪廓的辦法 這裡大...
Directx11教程37 紋理對映 7
本章是在教程35 36的基礎上來實現乙個光照紋理結合的程式,就是把場景中旋轉的cube加上紋理。lighttex.vs中頂點的結構現在為 struct vertexinputtype 紋理座標 output.tex input.tex 紋理座標不做任何變化,只是單純的從vs輸出到ps中。lightt...
Directx11教程38 紋理對映 8
上篇日誌中,我們用紋理和光照顏色調製的方式得到最終顏色,本章我們嘗試用紋理取樣的顏色,直接做為材質的漫反射係數kd,並用它來做光照計算,最後再做個gamma校正,如果不做的話,效果會偏亮。lighttex.ps主要改動 float4 texturecolor shadertexture.sample...