OpenGL漫反射照明着色器Bug?

时间:2010-03-13 09:42:41

标签: fragment-shader vertex-shader

橙皮书第16.2节列出了实施漫反射照明:

void main()
{
  vec3 N = normalize(gl_NormalMatrix * gl_Normal);
  vec4 V = gl_ModelViewMatrix * gl_vertex;
  vec3 L = normalize(lightPos - V.xyz);
  gl_FrontColor = gl_Color * vec4(max(0.0, dot(N, L));
}

然而,当我运行时,我移动相机时灯光会发生变化。 另一方面,当我改变

  vec3 N = normalize(gl_NormalMatrix * gl_Normal);

要       vec3 N = normalize(gl_Normal);

我得到的散光照明就像固定的管道一样。

这是什么gl_NormalMatrix,删除它做了什么,......这是橙皮书中的一个错误......还是我不正确地设置我的OpenGl代码?

[为完整起见,片段着色器只复制颜色]

1 个答案:

答案 0 :(得分:6)

好的,我希望半年后回答你的问题没有错? :)

所以这里有两件事要讨论:


a)着色器应该是什么样的

你应该通过模型视图矩阵转换法线 - 这是给定的。考虑如果不这样做会发生什么 - 您的模型视图矩阵可以包含某种旋转。你的立方体会被旋转,但法线仍会指向旧的方向!这显然是错误的。

所以:当你通过模型视图矩阵变换顶点时,你也应该变换法线。你的法线是vec3而不是vec4,你对翻译不感兴趣(法线只包含方向),所以你可以将你的法线乘以mat3(gl_ModelViewMatrix),即左上角3-3子矩阵。

然后:这几乎是正确的,但仍然有点错误 - 原因是well-described on Lighthouse 3D - go have a read。长话短说,而不是mat3(gl_ModelViewMatrix),你必须乘以逆转换。

OpenGL 2非常有用,并以[{1}}为您预先计算。因此,正确的代码是:

gl_NormalMatrix

b)但它与固定管道不同,为什么?

首先我想到的是“使用固定管道时出了问题”。

我并不是真的热衷FP(长时间着色器!),但据我记忆所及,当您通过vec3 N = normalize(gl_NormalMatrix * gl_Normal); 指定灯光时,这受到了模型视图矩阵的影响。很容易(至少对我来说:))在错误的坐标系中指定灯光位置(或方向灯的光线方向)时会出错。

我不确定自从我现在使用GL3和着色器以来我是否记得它是如何工作的,但让我试试......你的模型视图矩阵是什么状态?我认为你可能有可能在物体空间而不是眼睛空间中指定了方向性光线方向,这样你的光线就会与物体一起旋转。 IDK如果与此相关,但在使用FF时请务必注意。当我还在使用GL 1.1时,我记得自己经常犯这个错误。

根据型号视图状态,您可以指定灯光:

  • 眼睛(相机)空间,
  • 世界空间,
  • 对象空间。

确定它是哪一个。

嗯..我希望能让你的主题更加清晰。结论是:

  1. 始终将您的法线与顶点着色器中的顶点一起变换,并
  2. 如果它看起来与您的预期不同,请考虑如何指定您的灯光位置。 (也许你想在着色器中乘以光位置矢量?关于光位置坐标系的评论仍然存在)