**0**

# Easy OpenGL Directional Lighting Question

###
#1
Members - Reputation: **192**

Posted 16 July 2012 - 08:38 PM

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!

###
#2
Crossbones+ - Reputation: **6930**

Posted 16 July 2012 - 09:39 PM

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.I realize the final coordinate, the w-coordinate, should be 0.

First define your two points.

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))*

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 isAlso, 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.

*transform * (lx,ly,lz,0)*.

Edit: correction due to the comment of dpadam450.

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

My game: Gnoblins

Developer journal about Gnoblins

Small goodies: Simple alpha transparency in deferred shader

###
#4
Members - Reputation: **252**

Posted 17 July 2012 - 12:00 PM

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."Also, are there any gotcha's with lighting when it comes to directional lighting?

###
#5
Members - Reputation: **192**

Posted 17 July 2012 - 09:42 PM

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.

###
#6
Members - Reputation: **861**

Posted 17 July 2012 - 09:53 PM

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

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.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?

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.

###
#7
Members - Reputation: **192**

Posted 18 July 2012 - 08:58 AM

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.

###
#9
Members - Reputation: **192**

Posted 18 July 2012 - 09:52 AM

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.

###
#10
Members - Reputation: **861**

Posted 18 July 2012 - 12:27 PM

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.

I would post your shader or the shadow portion of it.

###
#11
Members - Reputation: **192**

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?

###
#12
Members - Reputation: **861**

Posted 18 July 2012 - 01:22 PM

So you have shadows but not lighting? Post a pic.The Shadow Mapping part works great at the bottom, but the top part seems to be screwing up somehow.

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.

###
#13
Members - Reputation: **192**

Posted 18 July 2012 - 05:36 PM

Here's what that looks like:

https://plus.google....sts/GkWqzumYmKv

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.**