2

我有以下用于照明的 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,但我得到了相同的效果。我究竟需要做什么才能正确转换光矢量?

4

5 回答 5

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

于 2010-03-05T16:31:18.313 回答
2

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

您还可以在其他空间(切线、对象、世界甚至屏幕空间 - 用于延迟着色)中应用灯光,但这是不同的主题。另请注意,对于高级用途,您将需要忘记 OpenGL,并使用您自己的矩阵和着色器(没有默认照明/转换的东西)来做所有事情。

于 2010-03-01T12:34:25.570 回答
-1

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

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

于 2009-12-11T09:01:48.437 回答
-1

我怀疑部分问题在于: float intensity = max(ambient, dot(eyeNormal, normalize(-lightDir));.

在基于 Lambertian 的着色器中,环境项由点积缩放。在这里,环境术语会经常断言自己,因为它可能大于点积。gl_NormalMatrix 的使用也是一个问题,因为如上所述,这意味着 lightDir 在对象空间中,而法线向量从对象空间转换为眼睛坐标。

尝试:

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

vec3 diffuse=ambient * ndotl; 
于 2011-08-11T10:24:49.290 回答
-2

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

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

于 2009-12-17T16:00:52.140 回答