2009-12-11 45 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