2009-12-11 78 views
2

定向光變換到攝像機空間我有照明下面GLSL代碼:如何GLSL

uniform vec3 lightDir; // Parallel light 
uniform float ambient; 
uniform vec3 lightColour; 

void main() 
{ 
    gl_Position = ftransform(); 

    vec3 eyeNormal = normalize(gl_NormalMatrix * gl_Normal); 
    float intensity = max(ambient, dot(eyeNormal, normalize(-lightDir)); 

    gl_FrontColor = gl_Color * vec4(lightColour, 1.0) * intensity; 
} 

的光載體在世界空間中指定。我使用gluLookAt設置相機的方向和位置。由於OpenGL假定光矢量位於相機空間中,因此光線會隨相機移動,而不是保持固定的方向。

我試過在調用gluLookAt之前和之後激活着色器和設置光矢量,但是我得到了相同的效果。我要做什麼才能正確轉換光矢量?

回答

-1

你着色器中的問題是,你有眼睛空間法線和世界空​​間燈。
我不確定,但通過正常矩陣轉換光矢量應該可以解決問題。或者,爲了更高效,您可以在對象空間(程序代碼)中轉換光vec,然後不需要爲每個法線進行轉換。

+0

我試圖通過gl_NormalMatrix着色器乘以lightDir,也沒有效果。我試着乘以gl_ModelViewMatrix,像這樣:'vec3 lightEyeDir = normalize(vec3(gl_ModelViewMatrix * vec4(-lightDir,1.0)));' 這樣做完全消除了彌散貢獻。 要在程序代碼中轉換光照矢量,我會做什麼轉換? – Aaron 2009-12-11 23:36:06

+0

通過逆模型矩陣轉換光的方向,您應該獲得模型空間燈。 – Tryum 2009-12-14 08:38:50

+1

NormalMatrix只是ModelView矩陣的旋轉部分(沒有平移和縮放)。將光線與它相乘意味着還可以應用模型旋轉(並且您不需要)。 – MaR 2010-03-01 12:27:20

-2

着色器中的代碼計算不隨光線位置而變化的方向燈,因此您應該使用spotLight或pointLight函數。

試着找到這些光源的着色器。如果你找不到,告訴我,我會給你一個。

2

您必須決定在哪個空間進行照明。如果你想遵循「標準」OpenGL,那麼它是查看空間。在傳遞給着色器(imho最簡單的解決方案)之前,您的光矢量必須通過視圖矩陣的旋轉部分進行旋轉。

您也可以將光線應用於其他空間(切線,物體,世界甚至屏幕空間 - 用於緩衝着色),但這是不同的主題。另外請注意,對於高級用途,您將需要忘記OpenGL,並使用自己的矩陣和着色器(沒有默認的照明/轉換內容)做所有事情。

3

您有一個常見問題,常見於GLSL教程在線。你正在通過制服傳遞你的照明值。爲什麼不使用glLight調用,就像使用固定功能渲染一樣,並從gl_LightSource[n]中提取值。區別在於openGL會自動翻譯視圖空間中的所有內容。

void main() 
{ 
    // remember: directional lights are GL_POSITION with w = 0 
    vec3 lightDir = vec3(gl_LightSource[0].position); 
    float ambient = gl_LightSource[0].ambient; 
    vec3 lightColour = vec3(gl_LightSource[0].diffuse); 


    gl_Position = ftransform(); 

    vec3 eyeNormal = normalize(gl_NormalMatrix * gl_Normal); 
    float intensity = max(ambient, dot(eyeNormal, normalize(-lightDir)); 

    gl_FrontColor = gl_Color * vec4(lightColour, 1.0) * intensity; 
} 

一個總是在受到巨大的資源:http://www.lighthouse3d.com/opengl/glsl/index.php?lights

而且總是有用的是GLSL金手指金手指:http://www.cs.brown.edu/courses/cs123/resources/glslQuickRef.pdf

+0

但是在這種情況下,您不需要否定光線方向,我認爲,因爲「位置」字段中的值應該已經是光線的矢量(理論上在無窮遠處的位置)。 – 2011-08-11 12:09:50

+1

請注意,現在不推薦使用glLight調用,而不像制服一樣傳遞光照值。 – 2016-09-26 14:37:21

-1

我懷疑是問題的一部分在於: float intensity = max(ambient, dot(eyeNormal, normalize(-lightDir));

在基於朗伯的着色器中,環境項是由點積縮放的。在這裏,環境術語通常會自行聲明,因爲它可能比點積大。 gl_NormalMatrix的使用也是一個問題,因爲如上所述,這意味着lightDir在物體空間中,而法向矢量則從物體空間轉換到眼睛座標中。

嘗試:

vec3 n=normalize(normal); 
float ndotl=max(0.0, dot(n, normalize(lightDir))); 

vec3 diffuse=ambient * ndotl; 
+0

這是錯的。現在你假設'lightDir'在模型空間中。環境術語是一個作弊術語,即使沒有定向光源也總是會發光,所以它絕對不應該乘以點積,而是增加(或僅在沒有足夠光線時才使用,就像他一樣) 。你的意思可能是光線先天的強度,在他的情況下,它是用點積乘以「lightColour」來表示的。 – 2011-08-11 12:16:33