0

橙皮书第 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 代码?

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

4

1 回答 1

6

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

所以这里有两点要讨论:


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

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

所以:当你通过模型视图矩阵变换你的顶点时,你也应该变换法线。您的法线vec3不是vec4,并且您对平移不感兴趣(法线仅包含方向),因此您可以将法线乘以mat3(gl_ModelViewMatrix),这是左上角的 3-3 子矩阵。

然后:这几乎是正确的,但仍然有点错误 - 原因在 Lighthouse 3D 中得到了很好的描述 - 去阅读。长话短说,mat3(gl_ModelViewMatrix)你必须乘以它的逆转置,而不是 。

OpenGL 2 非常有帮助,它会为您预先计算为gl_NormalMatrix. 因此,正确的代码是:

vec3 N = normalize(gl_NormalMatrix * gl_Normal);

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

我首先想到的是“您使用固定管道有问题”。

我并不是很喜欢 FP(着色器万岁!),但据我所知,当您通过 指定灯光时glLightParameterfv(GL_LIGHT_POSITION, something),这会受到模型视图矩阵的影响。在错误的坐标系中指定灯光位置(或定向灯光的灯光方向)很容易(至少对我来说:))。

我不确定我是否记得正确,因为我现在使用 GL3 和着色器,但让我试试......你的模型视图矩阵的状态是什么?我认为您可能已经在对象空间而不是眼睛空间中指定了定向光的方向,这样您的光就会与您的对象一起旋转。IDK 如果这与此处相关,但在使用 FF 时请务必注意这一点。这是我记得自己在使用 GL 1.1 时经常犯的一个错误。

根据模型视图状态,您可以在以下位置指定灯光:

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

确定它是哪一个。

呵呵..我希望这能让你的话题更清楚。结论是:

  1. 始终在顶点着色器中将法线与顶点一起转换,并且
  2. 如果它看起来与您的预期不同,请考虑如何指定灯光位置。(也许你也想在着色器中乘以光照位置向量?关于光照位置坐标系的评论仍然成立)
于 2010-11-27T13:58:50.697 回答