Sign in to follow this  
sevenfold1

GLSL Directional Light

Recommended Posts

Hello,
I'm trying to setup a basic directional light that matches the fixed pipeline.

However, my GLSL version looks like a point light, with very dark edges.
Ambient is zero, specular is zero, and attenuation is off, so it doesn't interfere.

How can I match the same shading as seen in the fixed version?

fu73mb.jpg


//////////////////////////////////////////

// VERTEX SHADER

varying vec3 N;
varying vec3 L;

void main()
{    
    N = normalize(gl_NormalMatrix * gl_Normal);
    L = normalize(gl_LightSource[0].position.xyz);	// directional light

    gl_Position = ftransform();
}

//////////////////////////////////////////

// FRAGMENT SHADER

varying vec3 N;
varying vec3 L;

void main()
{ 
    N = normalize(N);
    L = normalize(L);

    float lamb = max( dot(N,L), 0.0 );
    
    vec4 diffuseColor = vec4(1,1,1,1);
    gl_FragColor = lamb * diffuseColor;
}

Share this post


Link to post
Share on other sites

#1: Don’t normalize the light/normal in the vertex shader if you are going to renormalize them in the pixel shader.  Think about where each needs to be normalized and only normalize them there.

Normalize the light vector in the vertex shader since it does not change across the face of the triangle.

The normal will not be normalized across the face of the triangle even if you normalize it in the vertex shader, so only normalize it in the pixel shader.

 

#2: You are using per-pixel shading while they are using vertex shading.

If you want their result (which you shouldn’t), then perform lighting in the vertex shader, not the pixel shader.  The pixel shader simply outputs the result as the final color.

 

 

L. Spiro

Share this post


Link to post
Share on other sites

>>perform lighting in the vertex shader, not the pixel shader...


Thanks, that was it!

I didn't realize where I made the calculations made a difference.


>>Don’t normalize the light/normal in the vertex shader if you are going to renormalize them in the pixel shader.

No problem. I read somewhere that these "varying" variables get interpolated when getting passed around, so I have no idea if there are still normalized or not.



///////////////////////////////////////////////////////////////////

// VERTEX SHADER

varying vec4 fragColor;

void main()
{    
    vec3 N = normalize(gl_NormalMatrix * gl_Normal);
    vec3 L = normalize(gl_LightSource[0].position.xyz);	// directional light

    //////////////////////////////////

    float lamb = max( dot(N,L), 0.0 );
    vec4 diffuseColor = vec4(1,1,1,1);
    fragColor = lamb * diffuseColor;

    //////////////////////////////////

    gl_Position = ftransform();
}

///////////////////////////////////////////////////////////////////

// FRAGMENT SHADER

varying vec4 fragColor;

void main()
{ 
    gl_FragColor = fragColor;
}

Share this post


Link to post
Share on other sites

so I have no idea if there are still normalized or not.

Think about the result of linearly interpolating between 2 points.
Even if the 2 points are normalized at the start, the points between them will only still be normalized if the start and end point are the same.
Interpolate mentally between these 2 normals:
\   /
 \ /
  º
Going directly across from one to the other, you can mentally see that the points on the line segment you draw are not unit-length.

The light direction, on the other hand, doesn’t change, so it is the same as interpolating from one point to the same point. So if that point is normalized it will stay normalized. Hence it can be done once in the vertex shader.


L. Spiro

Share this post


Link to post
Share on other sites

you should also normalize the normal on the vertex shader otherwise you're giving the normal with a greater length an unwanted weight in interpolation

Edited by IYP

Share this post


Link to post
Share on other sites
If the normals are of unit length on input, multiplication with gl_NormalMatrix (which is deprecated) will result in normals of some consistent ratio.
Meaning in most cases all normals will still be 1 length long, but may all be 0.5 long, etc.
In other words, as long as the normals are the same length in input they will be the same length after gl_NormalMatrix.


L. Spiro

Share this post


Link to post
Share on other sites
Thanks, this works great for my purposes, but the only downside to doing calculations in the vertex shader, is that I can't use the texture2D sampler anymore. That must be done in the fragment shader, per pixel.

Share this post


Link to post
Share on other sites

as L. Spiro said you'd really want to do shading on fragment shader for smooth and per fragment shading I don't really see a reason not to do that. and your shading being different from fixed pipe line doesn't mean you're doing it wrong it means fixed pipe line is doing it wrong

Edited by IYP

Share this post


Link to post
Share on other sites

 

 

Thanks, this works great for my purposes, but the only downside to doing calculations in the vertex shader, is that I can't use the texture2D sampler anymore. That must be done in the fragment shader, per pixel. 

 

 

well i dont know modern glsl but what i know is that you can use sampler2D in a vertex shader.

 

Another thing you can even make a texture projection where texture is a single circle (filled with a color) and project it onto a scene works exactly as directional light

Share this post


Link to post
Share on other sites

To get this working with texture coords, I have to pass the lighting factor as a vector, like vec4.
Passing it as a single float to the fragment shader always fails. The float is always zero.

Is this a problem with the GLSL version or somewhere else?

///////////////////////////////////////////////////////////////////

// VERTEX SHADER

varying float lamb;
varying vec4 diffuseColor;

void main()
{    
    vec3 N = normalize(gl_NormalMatrix * gl_Normal);
    vec3 L = normalize(gl_LightSource[0].position.xyz);	// directional light

    float lamb = max( dot(N,L), 0.0 );
    diffuseColor = lamb * vec4(1,1,1,1);

    //////////////////////////////////

    gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_Position = ftransform();
}

///////////////////////////////////////////////////////////////////

// FRAGMENT SHADER

uniform sampler2D diffuseMap;
varying float lamb;
varying vec4 diffuseColor;

void main()
{ 
    // fails
    //gl_FragColor = lamb * texture2D(diffuseMap, gl_TexCoord[0].st);

    // works
    gl_FragColor = diffuseColor * texture2D(diffuseMap, gl_TexCoord[0].st);
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this