2014-01-12 90 views
14

我的普通矩陣有一些問題。如何計算正常矩陣?

vs.glsl

#version 440 

in vec3 vPosition; 
in vec3 vNormal; 

out vec4 eyeCordFs; 
out vec4 eyeNormalFs; 

uniform mat4 model; 
uniform mat4 view; 
uniform mat4 proj; 

void main() 
{ 
    mat4 modelView = view * model; 
    mat4 normalMatrix = view * transpose(inverse(model)); 
    vec4 eyeNorm = normalize(normalMatrix * vec4(vNormal, 0.0)); 
    vec4 eyeCord= modelView * vec4(vPosition, 1.0); 

    eyeCordFs = eyeCord; 
    eyeNormalFs = eyeNorm; 

    gl_Position = proj * modelView * vec4(vPosition,1.0); 
} 

fs.glsl

#version 440 

in vec4 eyeCordFs; 
in vec4 eyeNormalFs; 

out vec3 outputColor; 

uniform vec4 lightPos; 

void main() 
{ 
    vec4 s = normalize(lightPos - eyeCordFs) ; 
    vec4 r = reflect(-s,eyeNormalFs); 
    vec4 v = normalize(-eyeCordFs); 
    float spec = max(dot(v,r),0.0); 
    float diff = max(dot(eyeNormalFs,s),0.0); 

    vec3 diffColor = diff * vec3(1,0,0); 
    vec3 specColor = pow(spec,3) * vec3(1,1,1); 
    vec3 ambientColor = vec3(0.1,0.1,0.1); 

    outputColor = diffColor + 0.5 * specColor + ambientColor; 
} 

這樣做的輸出看起來像 enter image description here

這似乎有點怪我。但我知道我沒有擴展任何東西,所以我想我可以使用modelView矩陣來轉換我的法線。

所以我改了行

vec4 eyeNorm = normalize(normalMatrix * vec4(vNormal, 0.0)); 

vec4 eyeNorm = normalize(modelView * vec4(vNormal, 0.0)); 

現在輸出看起來像這樣

enter image description here

這看起來是正確的。我在計算我的normalMatrix錯誤的方式?

回答

38

正常矩陣是模型視圖矩陣的轉置逆。因此,在GLSL這將是

mat4 normalMatrix = transpose(inverse(modelView)); 

但是你應該計算着色器中正常的矩陣。在着色器中這樣做浪費了很多寶貴的GPU週期。矩陣求逆並不是一個便宜的操作,並且在着色器中執行它會迫使GPU一次又一次地爲每個頂點執行計算。在CPU上預先計算並作爲統一傳遞。

+0

也可以通過模型矩陣的3x3部分(不翻譯)進行轉換。或者它僅適用於世界太空閃電? –

+3

@MichaelIV:只要沒有涉及各向異性變換(比如每個軸不同的縮放因子縮放),它就會起作用。 – datenwolf

+1

「我的寶貴!! .... GPU週期。」 Golum會說,如果他是圖形程序員的話。 – ray