cg語言漫反射光照模型中的worldMatrix_IT是什麼意思?是世界變換矩陣的轉置的逆?
struct VertexIn
{
float4 position : POSITION;
float4 normal : NORMAL;
};
struct VertexScreen
{
float4 oPosition : POSITION;
float4 color : COLOR;
};
void main_v(VertexIn posIn,
out VertexScreen posOut,
uniform float4x4 modelViewProj,
uniform float4x4 worldMatrix,
uniform float4x4 worldMatrix_IT,
uniform float3 globalAmbient,
uniform float3 lightPosition,
uniform float3 lightColor,
uniform float3 Kd)
{
posOut.oPosition = mul(modelViewProj, posIn.position);
float3 worldPos = mul(worldMatrix, posIn.position).xyz;
float3 N = mul(worldMatrix_IT, posIn.normal).xyz;
N = normalize(N);
//計算入射光方向
float3 L = lightPosition - worldPos;
L = normalize(L);
//計算方向光漫反射光強
float3 diffuseColor = Kd*lightColor*max(dot(N, L), 0);
//計算環境光漫反射光強
float3 ambientColor = Kd*globalAmbient;
posOut.color.xyz = diffuseColor+ambientColor;
posOut.color.w = 1;
}
這是一個漫反射光照模型的頂點著色器代碼,其中的這一句不是很理解
float3 N = mul(worldMatrix_IT, normal).xyz;
這句代碼應該是要將法線從模型空間變換到世界空間吧,為什麼不直接左乘一個worldMatrix,而是要左乘worldMatrix_IT?
worldMatrix_IT是什麼意思?是世界變換矩陣的轉置的逆?
並不一定需要inverse transpose,僅當變換包含非等比縮放時才需要。後者不這樣做的話,法線便不會垂直於平面。
手機輸入不了公式,後補推導。
--
這問題有很多推導方式,以下是其中一種。先證切線矢量(tangent vector)可以直接使用變換矩陣來做變換。
設為兩個表面上接近的點,則是一個切線矢量,那麼對於任何變換矩陣,變換後的切線矢量可以由這兩個點變換後的坐標相減得出:
由於法線的定義就是垂直於平面,即法矢量與切線矢量垂直,那麼:
因為變換後的法矢量也需要垂直於變換後的切線矢量,從上式得出:
證明法矢量需要用變換矩陣的逆的轉置來做變換,才能保證變換後的法矢量垂直於變換後的表面。
另外,對於正交矩陣(Orthogonal matrix),其逆矩陣等同於其轉置矩陣,所以:
由於只含等比縮放、旋轉的變換矩陣是正交矩陣,其逆的轉置即等於自身,所以這情況下不需要使用逆的轉置來變換法線。這個屬於圖形學書中會提到但是容易被忽略的問題。對於法線是一定要用Inverse Transpose(所以不僅是「逆」)來轉換的。這裡有篇中文博客,有示意圖(文章我沒有細看,自己斟酌):http://blog.csdn.net/christina123y/article/details/5963679
——上圖引用自 "Real Time Rendering,3rd edtion". Page 63.
通常在計算光照時,法向量一般都會被變換到世界坐標系或者眼(坐標系)中。而這個變換過程的採用的矩陣一般是平移、旋轉和縮放矩陣的按某種順序的連乘。平移對向量的方向不產生影響;旋轉正是我們希望對法向量進行的操作;如果當變換中存在縮放,且在各軸的縮放比例相同,也不會對法向量方向產生影響,只是改變了它的長度。但是當各軸上的縮放比例不同時,就會出現如上圖中間所示的情況,方向發生了與「預期」相背離的變化。
為什麼要使用原矩陣的逆的轉置呢?
我們希望避免上述那種與「預期」相背離的變化。這種變化的根源在於縮放的非一致性。那我們的目的就是在對法向量進行縮放時取消這種非一致性。由於平移對方向無影響,通常我們只對原變換矩陣的左上3X3矩陣進行分析。設原3X3矩陣為。
其中為純旋轉矩陣(此處增加這兩個純旋轉矩陣只是為了表明變換矩陣的一般性),為純縮放矩陣。我們希望抵消縮放矩陣對法向量帶來的影響。即我們希望對法向量進行變換的矩陣為
又因為純旋轉矩陣的轉置等於其逆矩陣,即。純縮放矩陣的轉置等於它本身,即 。因此有:
所以我們需要原矩陣的逆的轉置。如@milo yip大神所說,逆轉置是因為法線的變換矩陣不同於切線和頂點,因此需要逆轉置矩陣來對其進行模型矩陣變換,但是對於正交矩陣(不引入非等比縮放的模型變換矩陣),其轉置等於其逆矩陣,於是再求逆就得到了原始的模型變換矩陣,對於世界空間法線到視空間的變換來說,這步是沒必要的,因為這個空間變換沒有引入縮放
已經有高人把原理說得很清楚了。不過想想去年的這個時候剛剛看完龍書第一版,算是一隻腳邁進了DirectX的大門,直到前2個月決定嘗試下OpenGL。。。DirectX龍書的11版本有解釋(DirectX10看的是中文版,英文原版沒接觸,翻譯版中沒發現相關解釋)。懶得翻書了,記憶里是在光照那一章,龍書里的shader代碼沒有乘以逆矩陣的這個步驟,一直都是直接使用world project view三個matrix,我也想不起來我是怎麼發現這個問題的,貌似是看另一本書,其中有一段簡化版的光線追蹤代碼,我發現裡面的shader代碼在處理是都會讓world乘以題主所說的worldMatrix_IT這個值。而龍書沒乘以這個值,是因為龍書里的例子進行的都是剛性變換,所以無需加工,我算個入門水平吧,如果說錯了還請指出。修改下答案,畢竟第一次回答還是很緊張的。
上面# @Milo Yip已經推導過了,按照這個推導就OK了。鑒於自己也模糊過這個東西。提供2點讓自己糾結的地方,方便更容易看懂整個公式(好想把圖片給刪除掉呀,經樓下兄次奧提醒),補一張圖上圖1.的解釋是錯誤的,做一個補充,錯誤的經驗也是經驗把
推薦閱讀: