开发者

OpenGL Diffuse Lighting Shader Bug?

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?

开发者_如何学C

[For completeness, the fragment shader just copies the color]


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 not vec4, and you're not interested in translations (normals only contain direction), so you can just multiply your normal by mat3(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:

vec3 N = normalize(gl_NormalMatrix * gl_Normal);

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:

  • eye (camera) space,
  • world space,
  • object space.

Make sure which one it is.

Huh.. I hope that makes the topic more clear for you. The conclusions are:

  1. always transform your normals along with your vertices in your vertex shaders, and
  2. if it looks different from what you expect, think how you specify your light positions. (Maybe you want to multiply the light postion vector in a shader too? The remarks about light position coordinate systems still hold)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜