Jump to content
  • Advertisement
Sign in to follow this  
Tsumuji

GLSL light with correct specular calculation?

This topic is 4396 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have writed this shader. I have got a bunch of examples in the internet and every shader that I test, got strange effects in the specular reflection. So I post here my code: vertshader
varying vec3 normal;
varying vec4 ecPosition;

void main()
{
	normal = gl_NormalMatrix * gl_Normal;
	
	//eye coordinate position
	ecPosition = gl_ModelViewMatrix * gl_Vertex;
	
	gl_TexCoord[0] = gl_MultiTexCoord0;
	gl_Position = ftransform();
}


fagshader
varying vec3 normal;
varying vec4 ecPosition;

sampler2D tex;

void main()
{
	float dist; //dist = distance between eye and light position
	vec3 aux, L, n, V, R, s; /*L = light vector direction(to the light position), 
						n = normal, 
						V = viewer vector, 
						R = reflection vector, 
						s = L+V normalized.
						*/
	
	//Precalculate some needed variables
	n = normalize(normal);
	aux = vec3(gl_LightSource[0].position - ecPosition);
	dist = length(aux);
	L = normalize(aux);
	V = vec3(normalize(-ecPosition));
	//R = normalize(-reflect(L, n)); //????
	s = normalize( L + V );
	
	//vec4 pixelFinalColor = vec4(1.0, 1.0, 1.0, 1.0);
	vec4 pixelFinalColor = gl_FrontMaterial.emission +//emission light +
			(gl_LightModel.ambient * gl_FrontMaterial.ambient);//global ambient light
	
	float Ldotn = max( dot( L, n ), 0.0 );
	if ( Ldotn > 0.0 ){ //Illuminate only the pixels than can be illuminated
		vec4 specularterm = pow( max( dot( s, n ), 0.0 ), gl_FrontMaterial.shininess ) * gl_FrontLightProduct[0].specular;
		vec4 diffuseterm = Ldotn * gl_FrontLightProduct[0].diffuse;
		vec4 ambientterm = gl_FrontLightProduct[0].ambient;
		//vec4 spotlighteffect = 1.0;
		float attenuationfactor = 1.0 / (gl_LightSource[0].constantAttenuation +
				gl_LightSource[0].linearAttenuation * dist +
				gl_LightSource[0].quadraticAttenuation * dist * dist);
		vec4 contribution = attenuationfactor * /*spotlight effect **/ (ambientterm + diffuseterm + specularterm);
		
		pixelFinalColor[3] = gl_FrontMaterial.diffuse[3];//????
		//pixelFinalColor += contribution;
		pixelFinalColor += clamp(contribution, 0.0, 0.1);
	}
	vec4 texcolor = texture2D(tex,gl_TexCoord[0].st);
	
	gl_FragColor = pixelFinalColor * texcolor;
}


What I am doing wrong?

Share this post


Link to post
Share on other sites
Advertisement
I recognize that shader.. I found it to be full of crazy stuff that was more problematic than supporting, and after a few words of wisdom from the good folks here, I ditched the shader completely.

I do not, however, recognize any specular error. I had other problems, like the light becoming dimmer as I looked away from it, and it seemed to move whenever I moved, but those were simple problems I solved by updating the light's position every frame as well as defining a mesh's material properties (specular, diffuse, ambient and shininess) on each frame.

Share this post


Link to post
Share on other sites
Can you post a screenshot with those "strange effects"?

BTW. That fragment shader is much too complicated. It's slow as hell. I suggest writing a new one.

Share this post


Link to post
Share on other sites
Like this one:



but I managed to fix this. Was the clamp that I do not put before.

Well, everything is almost working now, exept for one detail that I figured just before: If I try to illuminate a object that is not textured, I get a specular of grey :>



but it to work like this one :>




hum, how can I multiply correctly the texcolor in the fragshader?


//Precalculate some needed variables
n = normalize(normal);
aux = vec3(gl_LightSource[0].position - ecPosition);
dist = length(aux);
L = normalize(aux);
V = vec3(normalize(-ecPosition));
//R = normalize(-reflect(L, n));
s = normalize( L + V );

//vec4 pixelFinalColor = vec4(1.0, 1.0, 1.0, 1.0);
vec4 pixelFinalColor = gl_FrontMaterial.emission +//emission light +
(gl_LightModel.ambient * gl_FrontMaterial.ambient);//global ambient light

float Ldotn = max( dot( L, n ), 0.0 );
if ( Ldotn > 0.0 ){ //Illuminate only the pixels than can be illuminated
vec4 specularterm = pow( max( dot( s, n ), 0.0 ), gl_FrontMaterial.shininess ) * gl_FrontLightProduct[0].specular;
vec4 diffuseterm = Ldotn * gl_FrontLightProduct[0].diffuse;
vec4 ambientterm = gl_FrontLightProduct[0].ambient;
//vec4 spotlighteffect = 1.0;
float attenuationfactor = 1.0 / (gl_LightSource[0].constantAttenuation +
gl_LightSource[0].linearAttenuation * dist +
gl_LightSource[0].quadraticAttenuation * dist * dist);
vec4 contribution = attenuationfactor * /*spotlight effect **/ (ambientterm + diffuseterm + specularterm);

pixelFinalColor[3] = gl_FrontMaterial.diffuse[3];//????
pixelFinalColor += clamp(contribution, 0.0, 1.0);
}
vec4 texcolor = texture2D(tex,gl_TexCoord[0].st);

gl_FragColor = pixelFinalColor * texcolor;
}

Share this post


Link to post
Share on other sites
There's an error in the lighting equation. Specular term should not be multiplied by the texture color. Right now you're doing Gouraud shading but you should be doing Phong shading. Try adding the specular term to the resulting color. Also I don't know why you're doing

pixelFinalColor[3] = gl_FrontMaterial.diffuse[3];

Try chagning

vec4 contribution = attenuationfactor * /*spotlight effect **/ (ambientterm + diffuseterm + specularterm);

to:

vec4 contribution = attenuationfactor * /*spotlight effect **/ (ambientterm + diffuseterm);


And:

gl_FragColor = pixelFinalColor * texcolor;

to:

gl_FragColor = pixelFinalColor * texcolor + specularterm;


But what I really advise is rewriting the shader completely.

Share this post


Link to post
Share on other sites
hehehe worked very well. Thanks :D
Well, I do "pixelFinalColor[3] = gl_FrontMaterial.diffuse[3];" cause red book says so.
Or I'm confusing something?
Tomorrow I post the line where the book says this is done.

Share this post


Link to post
Share on other sites
@ Tsumuji & Lord Faron
the reason for the "pixelFinalColor[3] = gl_FrontMaterial.diffuse[3];" is because you dont want to modulate the alpha channel of the material by lighting, however that line should come right before (from what i can see) "gl_FragColor = pixelFinalColor * texcolor;"

Share this post


Link to post
Share on other sites
The book says in page 221 at the end of the 2nd paragraph: "...(Remeber that the final A or alpha component at a vertex is equal to the material's diffuse alpha value at that vertex.)".

I don't know if I put tis line where it is, or as you said Exorcist, but this must be done rifght?

And Lord Faron, where can I better the performance of this shader? I can't see how can I get better results since I want a per-pixel effect...

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!