OpenGL 漫射照明着色器错误?
橙皮书第 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 = 归一化(gl_Normal);
我得到的漫射照明就像固定管道一样。
这是什么 gl_NormalMatrix,删除它有什么作用,...这是橙皮书中的一个错误...还是我设置的 OpenGL 代码不正确?
[为了完整性,片段着色器仅复制颜色]
The Orange book, section 16.2, lists implementing diffuse lighting as:
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));
}
However, when I run this, the lighting changes when I move my camera.
On the other hand, when I change
vec3 N = normalize(gl_NormalMatrix * gl_Normal);
to
vec3 N = normalize(gl_Normal);
I get diffuse lighting that works like the fixed pipeline.
What is this gl_NormalMatrix, what did removing it do, ... and is this a bug in the orange book ... or am I setting up my OpenGl code improperly?
[For completeness, the fragment shader just copies the color]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧,希望时隔半年再回答你的问题没有什么问题吧? :)
所以这里有两件事需要讨论:
a)着色器应该是什么样子
你应该通过模型视图矩阵来转换你的法线 - 这是给定的。考虑一下如果不这样做会发生什么 - 您的模型视图矩阵可以包含某种旋转。您的立方体将被旋转,但法线仍指向旧方向!这显然是错误的。
因此:当您通过模型视图矩阵变换顶点时,您还应该变换法线。您的法线是
vec3
而不是vec4
,并且您对平移不感兴趣(法线仅包含方向),因此您只需将法线乘以mat3(gl_ModelViewMatrix )
,这是左上角的 3-3 子矩阵。然后:这几乎是正确的,但仍然有点错误 - 原因详细描述Lighthouse 3D - 请阅读。长话短说,您必须乘以它的逆变换,而不是
mat3(gl_ModelViewMatrix)
。OpenGL 2 非常有用,它会为您预先计算为
gl_NormalMatrix
。因此,正确的代码是:b) 但它与固定管道不同,为什么?
我首先想到的是“你使用的固定管道有问题”。
我不太热衷于 FP(着色器万岁!),但据我记得,当您通过
glLightParameterfv(GL_LIGHT_POSITION, some)
指定灯光时,这会受到模型视图矩阵的影响。在错误的坐标系中指定灯光位置(或定向灯的灯光方向)很容易(至少对我来说:))。我不确定我是否记得正确当时是如何工作的,因为我现在使用 GL3 和着色器,但让我尝试一下......你的模型视图矩阵的状态是什么?我认为您可能在对象空间而不是眼睛空间中指定了定向光方向,以便您的光会与对象一起旋转。我不知道这是否与这里相关,但在使用 FF 时请务必注意这一点。我记得当我还在使用 GL 1.1 时,我经常犯这个错误。
根据模型视图状态,您可以在以下位置指定灯光:
确定是哪一个。
嗯..我希望这能让你更清楚这个话题。结论是:
OK, I hope there's nothing wrong with answering your question after over half a year? :)
So there are two things to discuss here:
a) What should the shader look like
You SHOULD transform your normals by the modelview matrix - that's a given. Consider what would happen if you don't - your modelview matrix can contain some kind of rotation. Your cube would be rotated, but the normals would still point in the old direction! This is clearly wrong.
So: When you transform your vertices by modelview matrix, you should also transform the normals. Your normals are
vec3
notvec4
, and you're not interested in translations (normals only contain direction), so you can just multiply your normal bymat3(gl_ModelViewMatrix)
, which is the upper-left 3-3 submatrix.Then: This is ALMOST correct, but still a bit wrong - the reasons are well-described on Lighthouse 3D - go have a read. Long story short, instead of
mat3(gl_ModelViewMatrix)
, you have to multiply by an inverse transpose of that.And OpenGL 2 is very helpful and precalculates this for you as
gl_NormalMatrix
. Hence, the correct code is:b) But it's different from fixed pipeline, why?
The first thing which comes to my mind is that "something's wrong with your usage of fixed pipeline".
I'm not really keen on FP (long live shaders!), but as far as I can remember, when you specify your lights via
glLightParameterfv(GL_LIGHT_POSITION, something)
, this was affected by the modelview matrix. It was easy (at least for me :)) to make a mistake of specifying the light position (or light direction for directional lights) in the wrong coordinate system.I'm not sure if I remember correctly how that worked back then since I use GL3 and shaders nowadays, but let me try... what was your state of modelview matrix? I think it just might be possible that you have specified the directional light direction in object space instead of eye space, so that your light would rotate together with your object. IDK if that's relevant here, but make sure to pay attention to that when using FF. That's a mistake I remember myself doing often when I was still using GL 1.1.
Depending on the modelview state, you could specify the light in:
Make sure which one it is.
Huh.. I hope that makes the topic more clear for you. The conclusions are: