• Create Account

## Easy OpenGL Directional Lighting Question

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

12 replies to this topic

### #1Terin  Members

192
Like
0Likes
Like

Posted 16 July 2012 - 08:38 PM

Hey all, this should be a REALLY simple question that someone should hopefully be able to explain.

When defining directional lighting, I'm getting extremely confused by how we should define it. I realize the final coordinate, the w-coordinate, should be 0.

But suppose that up is a positive Z axis, down is a negative Z axis, and West/East are Negative/Positive X axis and South/North are Negative/Positive Y axis -- say I want a directional light to shine from the upper-west, what would my directional light look like? Would my direction vector (simplifying it, I realize I'd use cos/sin) (-1,0,1,0) or (1,0,-1,0)?

Also, are there any gotcha's with lighting when it comes to directional lighting? I saw something about having to apply the light's position AFTER pushing in all of your geometry, otherwise it doesn't translate/move correctly... In addition, when working with the fixed pipeline before, my directional lighting was off ALWAYS. I ended up having to use a spotlight and make it really wide (which worked), however I'd like to do this the correct way.

Thank you!

### #2Ashaman73  Members

13651
Like
2Likes
Like

Posted 16 July 2012 - 09:39 PM

I realize the final coordinate, the w-coordinate, should be 0.

This is the case, because you don't want to affect the vector by a translation, when multiplying with a transformation matrix. The transformation should only rotate the vector.

upper-west

(1,0,1)
Then you should define a source point, I think you want to have (0,0,0), right ?

The direction is (target-source):
(1,0,1) - (0,0,0) = (1,0,1)

After that you need to normalize it, directions are often needed in unit length:
(1,0,1) * (1/length(1,0,1))

Also, are there any gotcha's with lighting when it comes to directional lighting? I saw something about having to apply the light's position AFTER pushing in all of your geometry, otherwise it doesn't translate/move correctly.

When you transform a vertex or vector you move it from one space (i.e. world space) into an other space (i.e. camera space aka eye view). Lighting is often done in camera space, therefore you need to transform all vectors/vertices into the same space. When transforming a model this is done automatically by the transformation matrix, when you set a direction vector for lightning you need to transform it before uploading it to the GPU, that is transform * (lx,ly,lz,0) .

Edit: correction due to the comment of dpadam450.

Edited by Ashaman73, 16 July 2012 - 11:05 PM.

Ashaman

2053
Like
2Likes
Like

Posted 16 July 2012 - 10:23 PM

The direction in regards to lights is the direction pointing to the light. Not the direction the rays are coming.

Unless you have a modified coordinate system, openGL y-axis is up.

### #4scniton  Members

252
Like
1Likes
Like

Posted 17 July 2012 - 12:00 PM

Also, are there any gotcha's with lighting when it comes to directional lighting?

From http://www.opengl.or...tml/glLight.xml : When glLight* is called with the GL_POSITION argument, the "position is transformed by the modelview matrix when glLight is called (just as if it were a point), and it is stored in eye coordinates."

### #5Terin  Members

192
Like
0Likes
Like

Posted 17 July 2012 - 09:42 PM

Lots of good responses, thank you all.

So, let me see if I can make some sense of this. First, yes, suppose 0,0,0 is the center always of the screen. Wouldn't to the west and up (as per my prior description) be (-1,0,1)? Assuming that for whatever reason I had translated to some arbitrary point, making it the center (say, [x, y, z]), the resulting light would require the light direction to be (x -(-1), y, z - 1) => (x + 1, y, z -1), correct?

In any case, furthermore, if I were to specify the glLight's Position to -1, 0, 1 -- that wouldn't be enough, since I need to normalize it to unit length... What exactly is "unit length?" Apologies for what is most likely considered a simple question.

2053
Like
1Likes
Like

Posted 17 July 2012 - 09:53 PM

Wouldn't to the west and up (as per my prior description) be (-1,0,1)

yes

Assuming that for whatever reason I had translated to some arbitrary point, making it the center (say, [x, y, z]), the resulting light would require the light direction to be (x -(-1), y, z - 1) => (x + 1, y, z -1), correct?

A light with w = 0, means it is directional and not effected by translation basically 0*translation is what the math comes out to be. If you want a positional light such as a lamp post then yea something like that.

I'm pretty sure the lights position is normalized if you use GL without shaders. The vector 1,0,1 is bigger than 1,0,0. If you don't know the Pythagorean theorem then thats what it is for.

### #7Terin  Members

192
Like
0Likes
Like

Posted 18 July 2012 - 08:58 AM

I am using GL with Shaders. Trying to get my shadow code working -- had a lot of help from a few other people, just trying to get the final pieces correct.

Good to confirm/know everything, but yeah, it looks like I need to normalize the light's direction...

After reading again (and again) -- is the length(x,y,z) supposed to be the length of the vector, ala the Pythagorean theorem, to normalize it? Then just scale each dimension of the light's direction with that length?

i.e.

(-1, 0, 1) * ( 1 / sqrt(2) ) => (-1 / sqrt(2), 0, 1/ sqrt(2)) ?

If so, I think I finally got it. Oy.

2053
Like
0Likes
Like

Posted 18 July 2012 - 09:16 AM

......what shadow technique are you using. Considering you don't know what normalize means, shadowing is a bit scary to be doing. There is a function called normalize() in GLSL.

### #9Terin  Members

192
Like
0Likes
Like

Posted 18 July 2012 - 09:52 AM

I'm using Shadow Mapping, dropping the depth buffer, then re-applying it to the scene. Everything works perfectly, minus the light source being kind of in a funky position, which is why I'm trying to figure this part out. I do realize there's a function in GLSL for normalize -- I figured I'd probably be able to use that, but wanted to make sure I knew it in the standard pipeline as well.

I understand normalizing puts things into a specific scale/unit length, as you said, but I get very confused at the different matrices, i.e. World Matrix vs View Matrix vs ModelView. I know it seems silly, but I don't do this every day -- I do this on the side, when I have time, so I'm not always working with it and need to be reminded.

Regardless, let me try this out and see if it does what I want it to. Thank you for everyone's help so far.

2053
Like
1Likes
Like

Posted 18 July 2012 - 12:27 PM

So you are most likely doing it wrong because shadow mapping does not require a vector to the sun at all, and will have nothing to do with normalizing it either.

When learning shadow mapping, try projecting an image texture instead of a depth buffer, this way you can get the math part down and then just replace the image with a depth buffer, because sometimes you will user a depth buffer that is not what you thought it was.

### #11Terin  Members

192
Like
0Likes
Like

Posted 18 July 2012 - 12:51 PM

Here's what I have so far.

My shader for building the depth buffer and shadows is done as follows and works correctly:

[source lang="cpp"] //Vertex varying vec4 LightPosition; void main() { gl_Position = ftransform(); // Get the actual in-scene vector position. LightPosition = gl_Position; // Share this position with the fragment shader. } //Fragment varying vec4 LightPosition; void main() { gl_FragColor = vec4(LightPosition.z / LightPosition.w); // The color is the depth ratio. }[/source]

This builds everything fine, and I've checked.

The actual code for the shaders that draw the scene are as follows:

[source lang="cpp"] //Vertex uniform mat4 LightModelViewProjectionMatrix; uniform mat4 WorldMatrix; varying vec3 Normal; varying vec4 LightCoordinate; // Position in model view projection space from the lights view. varying vec4 WorldPosition; // Position in world space. void main() { Normal = gl_Normal; WorldPosition = WorldMatrix * gl_Vertex; LightCoordinate = LightModelViewProjectionMatrix * gl_Vertex; gl_Position = ftransform(); // Transform via fixed function into the viewer's view gl_TexCoord[0] = gl_MultiTexCoord0; } //Fragment uniform sampler2D DiffuseMap; uniform sampler2D ShadowMap; uniform mat4 WorldMatrix; uniform float MinimumShadow; varying vec3 Normal; varying vec4 LightCoordinate; varying vec4 WorldPosition; void main() { // Direct lighting // ------------------------------ vec4 Color = gl_LightSource[0].ambient; vec3 l = normalize(gl_LightSource[0].position.xyz - WorldPosition.xyz); // direction to the light source vec3 view_normal = normalize(gl_NormalMatrix * Normal); vec3 view_light_direction = normalize(vec3(gl_LightSource[0].position)); //(WorldMatrix * vec4( LightPosition.x, LightPosition.y, LightPosition.z, 0 ) ).xyz; //float lambert = max(dot(view_normal, view_light_direction), 0.2); float lambert = max(dot(Normal, l), MinimumShadow); Color.xyz *= lambert; //Blend in Color from primary texture unit Color.wxyz *= texture2D(DiffuseMap, vec2(gl_TexCoord[0])).wxyz; // Shadow mapping // ------------------------------ vec4 lcoord = LightCoordinate; // Fragment position in light space. lcoord /= lcoord.w; // Project to cartesian space lcoord.xy = lcoord.xy * 0.5 + 0.5; // Scale since light clipping space is in [-1,1] but texture space is [0,1] float fragmentDepth = lcoord.w; // Depth of the fragment in light space. float shadowMapDepth = texture2D(ShadowMap, lcoord.xy).x; // Depth in the shadow map. float eps = 0.001; // depth bias float shadow = fragmentDepth - eps > shadowMapDepth ? 0.5: 1.0; gl_FragColor = Color * shadow; }[/source]

This appears to be where I start having the screw-ups. Everything in the scene renders right -- except for the light. The Shadow Mapping part works great at the bottom, but the top part seems to be screwing up somehow. Mind you, I realize the correct code should be the first lambert (that is commented out). However, there are no shadows in this situation.

Now, I've got the position building correctly to what I believe it should be. In fact, it's at the point where I can render from the Light's viewpoint and it shows how I expect it to.

[source lang="csharp"] Single LightX = (Single)( Math.Cos( Radians ) ); Single LightY = 0.0f; Single LightZ = (Single)( Math.Sin( Radians ) ); Double LightAngle = Radians / Math.PI * 180.0d; Single[] LightDirection = new Single[] { LightX, LightY, LightZ, 0.0f }; Gl.glLightfv( Gl.GL_LIGHT0, Gl.GL_POSITION, LightDirection );[/source]

Does anything appear to be outwardly wrong?

2053
Like
1Likes
Like

Posted 18 July 2012 - 01:22 PM

So what I would suggest again, is instead of binding the shadow texture, Bind an image of a tree or anything and see if you can see any of the image at all noticeable.

The Shadow Mapping part works great at the bottom, but the top part seems to be screwing up somehow.

So you have shadows but not lighting? Post a pic.

You mentioned you have a 0 for the w coordinate but you are subtracting light position from world position as if it is a point light.

### #13Terin  Members

192
Like
0Likes
Like

Posted 18 July 2012 - 05:36 PM

This current code actually renders the shadows and light (but the light is incorrect).

Here's what that looks like:

That is the problem I have with that code. When I do it with the other stuff that's commented out, I have flat shading with no shadows. It's as if I had just put a film over the screen and changed the color of it to darken the entire scene.

EDIT:

Just want to note that I changed the discussion of this and posted to a different topic (since this is no longer an accurate title and is a completely different issue altogether) : http://www.gamedev.net/topic/628307-help-with-shadow-mapping-and-multi-texturing/

Edited by Terin, 20 July 2012 - 11:33 PM.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.