2014-01-12 37 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(modelView * vec4(vNormal, 0.0)); 

にライン

vec4 eyeNorm = normalize(normalMatrix * 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サイクル。グラフィック・プログラマーであれば、ゴラムは言っていただろう。 – ray

関連する問題