昨天研究了下Node Based Material System, 虛幻3的材質(zhì)系統(tǒng)是沒戲了,還沒用會呢. 不過Max的一個插件: ShaderFX倒是給我很大的啟發(fā),這東西就是結(jié)點型材質(zhì)系統(tǒng), 而且能生成真正的FX. 不像虛幻3那么不厚道,只是局部顯示HLSL.
經(jīng)過分析ShaderFX導出的Shader文件, 發(fā)現(xiàn)其標準材質(zhì)系統(tǒng)使用的就是逐像素光照模型, 而不同的Materials對應(yīng)的就是一種Shader處理管線, 分別可以處理各種光照,甚至達到Compositor的混合效果. 而Shader Code Generation這個環(huán)節(jié),也遠沒有虛幻3那樣復(fù)雜(虛幻是神,咱們不評論神到底如何),只是將光照需要的各種分量,例如Emissive, Ambient, Diffuse, Specular等根據(jù)各分量提供的計算因子直接嵌入到Pixel Shader主函數(shù)體即可.
逐頂點光照在前面的文章已經(jīng)有介紹,代碼相對簡單, 因此以后在材質(zhì)系統(tǒng)中準備直接上逐像素光照. 因此,需要在我的模型插件中加入Tangent及Binormal支持.
這里是一篇很不錯的講解Tangent Space Vector的文章. 文中有貼過OGRE的Tangent計算代碼,不過查閱OGRE 1.65代碼后發(fā)現(xiàn),OGRE現(xiàn)在根本就不用這個函數(shù)計算Tangent,而是更為復(fù)雜的一個類.
最終,我還是使用了大野豬的ev3d的max插件代碼, 如果需要的話,可以去他博客找svn下載
bool CMaxMesh::__cacl_tbn(sFace_t& face,bool isSkin)
{
Point3 normal[3];
Point3 Tangent;
Point3 p[3];
assign(normal[0],m_MeshData.m_VertexData.m_Normals[face.vert[0]]);
assign(normal[1],m_MeshData.m_VertexData.m_Normals[face.vert[1]]);
assign(normal[2],m_MeshData.m_VertexData.m_Normals[face.vert[2]]);
if(isSkin == false)
{
assign(p[0],m_MeshData.m_VertexData.m_Positons[face.vert[0]]);
assign(p[1],m_MeshData.m_VertexData.m_Positons[face.vert[1]]);
assign(p[2],m_MeshData.m_VertexData.m_Positons[face.vert[2]]);
}
else
{
assign(p[0],m_MeshData.m_VertexData.m_VertexWeights[face.vert[0]].m_InitPos);
assign(p[1],m_MeshData.m_VertexData.m_VertexWeights[face.vert[1]].m_InitPos);
assign(p[2],m_MeshData.m_VertexData.m_VertexWeights[face.vert[2]].m_InitPos);
}
sUVCoord_t uv[3];
uv[0] = m_MeshData.m_VertexData.m_UVChannels[0][face.vert[0]];
uv[1] = m_MeshData.m_VertexData.m_UVChannels[0][face.vert[1]];
uv[2] = m_MeshData.m_VertexData.m_UVChannels[0][face.vert[2]];
Point3 e1 = p[1] - p[0];
Point3 e2 = p[2] - p[0];
sUVCoord_t u1 = { uv[1].u - uv[0].u , uv[1].v - uv[0].v};
sUVCoord_t u2 = { uv[2].u - uv[0].u , uv[2].v - uv[0].v};
float det = ( u1.u * u2.v - u2.u * u1.v);
if(det == 0.0f)
{
Tangent = e1;
}
else
{
Tangent = u2.v * e1 - u1.v * e2;
}
//從Normal 和 Tangent里重新計算出Tangent,因為面的Tangent和頂點的Normal可能不垂直
Point3 final_tangent;
for(int i = 0 ;i < 3 ; ++i)
{
Point3 binormal = CrossProd(normal[i],Tangent);
final_tangent = CrossProd(binormal,normal[i]);
final_tangent.Normalize();
m_MeshData.m_VertexData.m_Tangents[face.vert[i]].x += final_tangent.x;
m_MeshData.m_VertexData.m_Tangents[face.vert[i]].y += final_tangent.y;
m_MeshData.m_VertexData.m_Tangents[face.vert[i]].z += final_tangent.z;
}
return true;
}
感謝大野豬友情出演,正片開始:)
