GLSL lighting problem (pics)

Started by
11 comments, last by James Trotter 18 years, 8 months ago
I'm trying to implement OpenGL-like lighting on GLSL, but I'm facing problems. When rendered without the shader via the OpenGL pipeline, everything looks like this So far so good. But when I use the shader I've made myself, or any of the shaders at Lighthouse3D everything looks like this My shader code could be anything from the directional light tutorials at Lighthouse3d.com. All I really want is an per-pixel version of the opengl pipeline code. Everything is rendered via the exact same values, but the problem is in the shader and i have no idea what it is. I've tried to implement it on my own without copying the sourcecode overthere but the result is the same and I can't make any progress. All pointers would be welcome. Here is how i setup my lights:

	vec4 amb_source = {0.040f, 0.040f, 0.040f, 1.0f};
	vec4 dif_source = {1.0f, 1.0f, 1.0f, 1.0f};
	
	
	
	GLfloat light_pos[] = { 0.0, 100.0, 0.0, 0.0};
	
	normalize_vec3(light_pos);
	glLightfv(GL_LIGHT0, GL_AMBIENT, amb_source);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, dif_source);

	glLightfv(GL_LIGHT0, GL_POSITION, light_pos);



and here are my current shaders


vertex
varying vec4 diffuse,ambient;
varying vec3 normal,lightDir,halfVector;

void main()
{	
	/* first transform the normal into eye space and 
	normalize the result */
	normal = normalize(gl_NormalMatrix * gl_Normal);
	
	/* now normalize the light's direction. Note that 
	according to the OpenGL specification, the light 
	is stored in eye space. Also since we're talking about 
	a directional light, the position field is actually direction */
	lightDir = normalize(vec3(gl_LightSource[0].position));
	
	/* Normalize the halfVector to pass it to the fragment shader */
	halfVector = normalize(gl_LightSource[0].halfVector.xyz);
				
	/* Compute the diffuse, ambient and globalAmbient terms */
	diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;
	ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;
	ambient += gl_LightModel.ambient * gl_FrontMaterial.ambient;
	
	gl_Position = ftransform();
	gl_FrontColor = gl_Color;
} 

fragment
varying vec4 diffuse,ambient;
varying vec3 normal,lightDir,halfVector;
	
	
void main()
{
	vec3 n,halfV,viewV,ldir;
	float NdotL,NdotHV;
		
	/* The ambient term will always be present */
	vec4 color = ambient;
		
	/* a fragment shader can't write a varying variable, hence we need
	a new variable to store the normalized interpolated normal */
	n = normalize(normal);
	
	/* compute the dot product between normal and ldir */
	NdotL = max(dot(n,lightDir),0.0);
	
	if (NdotL > 0.0) {
		color += (diffuse) * NdotL;
		halfV = normalize(halfVector);
		NdotHV = max(dot(n,halfV),0.0);
		color += gl_FrontMaterial.specular * 
				gl_LightSource[0].specular * 
				pow(NdotHV, gl_FrontMaterial.shininess);
	}
	
	gl_FragColor = color*gl_Color;
}


edit: Its important to notice that in the second picture the patterns you see there follow the patterns visible in the one rendered via OpenGL pipeline. So the normals are ok, but there is something I don't understand with the code.
Advertisement
This probably won't solve your problem, but you are needlessly (re)normalizing the normal vector in the fragment shader.

Quote:Original post by el capitan
Its important to notice that in the second picture the patterns you see there follow the patterns visible in the one rendered via OpenGL pipeline. So the normals are ok, but there is something I don't understand with the code.


What is it you don't understand?

Also, it might just be me, but I think this if statement looks a bit out of place:

if (NdotL > 0.0) {   ...}


I wrote a shader like this a while ago, I'll go see if I can dig it up again...
This is very confusing. I got it working by changing
normal = normalize(gl_NormalMatrix * gl_Normal);
ot this
normal = normalize(gl_Normal);

Can someone explain me what is goign on? I even checked the mathbooks and its supposed to be the original way... Now I'm utterly, staggeringly confused. Maybe a driver issue? Eh?
You need to enable lighting and enable light0 to have the shader recognize it.

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

You also want to put the colors into the material if you use them.

glEnable(GL_COLOR_MATERIAL);
static float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color)

It should default to 'white' (maybe) but it is better to initialize it.

I think you also need to compute the vertex color from the lights, that is what fixed function lighting does ;-)


"It's such a useful tool for living in the city!"
Quote:Original post by Name_Unknown
You need to enable lighting and enable light0 to have the shader recognize it.

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

You also want to put the colors into the material if you use them.

glEnable(GL_COLOR_MATERIAL);
static float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color)

It should default to 'white' (maybe) but it is better to initialize it.

I think you also need to compute the vertex color from the lights, that is what fixed function lighting does ;-)


ugh

ok
Quote:Original post by Name_Unknown
You need to enable lighting and enable light0 to have the shader recognize it.

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);



No you dont.
I've got some code which does lighting at both the vertex and fragment level and the test program doesnt have these lines at all and reproduces the same effect as the fixed function pipeline (and yes, I'm using the built in uniforms and setting them via the glLight() functions).

Quote:
I think you also need to compute the vertex color from the lights, that is what fixed function lighting does ;-)


Again, no you dont unless you are doing vertex lighting or are using the fixed function pipeline to do the shading.
Otherwise you are free to just calculate the three (iirc) vectors and perform the rest of the lighting in the fragment shader and calculate the colours there.

Why are you normalizing the light position?
Quote:Original post by _the_phantom_
Quote:Original post by Name_Unknown
You need to enable lighting and enable light0 to have the shader recognize it.

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);



No you dont.
I've got some code which does lighting at both the vertex and fragment level and the test program doesnt have these lines at all and reproduces the same effect as the fixed function pipeline (and yes, I'm using the built in uniforms and setting them via the glLight() functions).

Quote:
I think you also need to compute the vertex color from the lights, that is what fixed function lighting does ;-)


Again, no you dont unless you are doing vertex lighting or are using the fixed function pipeline to do the shading.
Otherwise you are free to just calculate the three (iirc) vectors and perform the rest of the lighting in the fragment shader and calculate the colours there.


My mistake. Everything I said is not right, so I will refrain from further
comments. I just got the GLSL guide and have only been starting through it. Don't enable color tracking either.

The only thing I wonder is why use gl_Color in the fragment shader. What is it if you don't set glColor?
"It's such a useful tool for living in the city!"
1st: Try using shaders generated via 3dlabs.com ShaderGen.
2nd: If that fails, output normal to color chanel (u can range compress it)
3rd: --//--//-- light position
3rd: --//--//-- eye position if you use any space but view(eye) space
4th: Try writing shader with constant materials and light positions

Tell us the results...
______________________________Madman
Quote:Original post by Name_Unknown
The only thing I wonder is why use gl_Color in the fragment shader. What is it if you don't set glColor?


Whatever it was last set to in another operation, or iirc it defaults to (1.0f,1.0f,1.0f,1.0f)

This topic is closed to new replies.

Advertisement