irrlicht代碼法線貼圖相關問題

irrlicht的代碼關於法線貼圖的範例即 PerPixelLighting。


程序準備資源部分,


先是一個磚牆普遍紋理,設到 text0


然後是一個法線紋理貼圖,設到text1(中間經過處理,將對比度,轉換成相應的法線數據)


然後是在COpenGLDriver::drawVertexPrimitiveList函數中,會走到case EVT_TANGENTS:這個分支.


接下來的代碼 要結合渲染腳本(一段嵌入的僞彙編,irrlicht 1.7 估計還沒有引入glsl)


case EVT_TANGENTS:
if (vertices)
{
glNormalPointer(GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Normal);
glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].TCoords);
glVertexPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Pos);
}
else
{
glNormalPointer(GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(12));
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(S3DVertexTangents), buffer_offset(24));
glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(28));
glVertexPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(0));
}


if (MultiTextureExtension)
{
extGlClientActiveTexture(GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
if (vertices)
glTexCoordPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Tangent);
else
glTexCoordPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(36));


extGlClientActiveTexture(GL_TEXTURE2_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
if (vertices)
glTexCoordPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Binormal);
else
glTexCoordPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(48));
}
break;

因爲程序並沒有設置 text2,所以這段代碼令人費解

同樣,在text1處,傳入的紋理映射數組,也令人不解


所以,它們不是紋理映射,是頂點法線的切空間中的兩個軸(相關切空間可以參考 相關文章)

因爲多邊形的位置在空間中不斷變化,根據法線紋理來計算光照,需要將光線變換到切空間中去。

這樣才能直接計算出光照值。


text1 text2關於傳入的是tangent 和bitangent,

以便在頂點渲染與像素渲染腳本中使用,將光線變換到頂點的切空間,並最終計算出每個頂點的像素值。

相應的渲染腳本存在 COpenGLParallaxMapRenderer.cpp中的數組變量中:

OPENGL_PARALLAX_MAP_VSH OPENGL_PARALLAX_MAP_PSH


注意腳本中的這一段代碼:

"#input\n"\
"# 0-3: transposed world matrix;\n"\
"#;12: Light01 position \n"\
"#;13: x,y,z: Light01 color; .w: 1/LightRadius^2 \n"\
"#;14: Light02 position \n"\
"#;15: x,y,z: Light02 color; .w: 1/LightRadius^2 \n"\
"#;16: Eye position \n"\
"\n"\
"ATTRIB InPos = vertex.position;\n"\
"ATTRIB InColor = vertex.color;\n"\
"ATTRIB InNormal = vertex.normal;\n"\
"ATTRIB InTexCoord = vertex.texcoord[0];\n"\
"ATTRIB InTangent = vertex.texcoord[1];\n"\
"ATTRIB InBinormal = vertex.texcoord[2];\n"\


所以 text1 text2傳進去的紋理映射參數,在計算時是作爲頂點切空間tangent和binormal(也就是bitangent)。

text2沒指定紋理,也沒關係,因爲實際計算的時候並沒有涉及到text2紋理相關的內存。


弄清參數傳遞機制後,接下來,生成tangent binormal以及相應的光線變換到切空間算法參考

Mathematics for 3D Game Programming and Computer Graphics 這本說的6.8章節(最新版本的好像在7.8章節)



這段代碼有點怪異,究其原因也是因爲tangent 和 binormal沒有現成的機制傳給渲染腳本導致的。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章