如何在GLSL中将定向光转换为相机空间

时间:2009-12-11 04:50:34

标签: opengl transform glsl lighting uniform

我有以下用于照明的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之前和之后激活着色器并设置光矢量,但我得到了相同的效果。我究竟需要做些什么才能正确转换光矢量?

5 个答案:

答案 0 :(得分: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 Cheat Cheat:http://www.cs.brown.edu/courses/cs123/resources/glslQuickRef.pdf

答案 1 :(得分:2)

您必须决定在哪个区域进行照明。如果你想遵循“标准”OpenGL,那么它是 view 空间。然后,在传递到着色器之前,必须通过视图矩阵的旋转部分旋转光矢量(最简单的解决方案)。

您还可以在其他空间(切线,对象,世界甚至屏幕空间)中应用灯光以进行隐藏着色,但这是不同的主题。另请注意,对于高级用途,您将需要忘记OpenGL并使用您自己的矩阵和着色器(没有默认的光照/转换内容)执行所有操作。

答案 2 :(得分:-1)

你的着色器中的问题是,你有眼睛空间法线和世界空​​间的灯光 我不确定,但用常规矩阵转换光矢量应该可以解决问题。

或者,为了提高效率,您可以在对象空间中(在程序代码中)转换光vec,然后不需要对每个法线进行转换。

答案 3 :(得分:-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; 

答案 4 :(得分:-2)

着色器中的代码计算的方向光不会随光的位置而变化,因此您应该使用spotLight或pointLight函数。

尝试为这些光源找到着色器。如果你找不到,请告诉我,我会寄给你一个。