Optimising per-pixel lighting shader

i’ve written my first per-pixel lighting shader,
and its not optimised, i’ve looked at it, tryed moving some things to the vertex shader, but i loose visual quality.

any quick hints as to how i could optimise this?

phong.vert

 
varying vec3 eye;
varying vec3 light;
varying vec3 normal;

void main()
{
	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
	gl_TexCoord[0] = gl_MultiTexCoord0;
	
	eye = vec3( gl_ModelViewMatrix * gl_Vertex );
	light = normalize( gl_LightSource[0].position.xyz - eye );
	normal = normalize( gl_NormalMatrix * gl_Normal );
}
 

phong.frag

 
uniform sampler2D texture;

varying vec3 eye;
varying vec3 light;
varying vec3 normal;

void main()
{
	vec3 nEye = normalize( eye );
	vec3 nLight = normalize( light );
	vec3 nNormal = normalize( normal );	
	vec3 reflectEye = reflect( nEye, nNormal );
	
	float diff = clamp( dot( nLight, nNormal ), 0.0, 1.0 );
	
	float spec = 0.0;		
	if( diff > 0.0 )
		spec = clamp( pow( clamp( dot( reflectEye, nLight ), 0.0, 1.0 ), gl_FrontMaterial.shininess ), 0.0, 1.0);
	
	vec4 difCol = texture2D( texture, vec2(gl_TexCoord[0]) ) * 
		((gl_LightSource[0].diffuse * diff) + gl_LightSource[0].ambient );
		
	vec4 specCol = gl_LightSource[0].specular * spec * gl_FrontMaterial.specular;
	
	gl_FragColor = difCol + specCol;
}
 

edit: also if you could say why you would do it so i can also understand and learn :slight_smile:
cheers

vec3 nEye = normalize( eye );
u can normalize this in the vs,
perhaps also the same with the normal
get rid of the if statement

hi,
here are a couple of thoughts:

first, you dont need to normalize the vectors in the vertex shader, as you will do it in the fragement shader: they WILL become wrong when interpolated for each fragment, so you can save this.

the second point is the if-statement. unless you have a sm3.0 complient card, you wont benefit from it, and it will even be slower than just calculate the sper variable for each fragment.

hope it helped a bit
wizzo.

If u want high speed, do what zed says and normalize the vectors only in the vertex shader.
If u don’t want the resulting less quality, normalize them in the fs, then u can get rid of of the normalizations in the vertex shader like wizzo says.

But there is another big optimisation:
a dot product never can become more than 1.0. That’s why you don’t need to clamp it. Use max(dot(), 0.0) instead, so it can’t become less than 0.0.

just to correct splat: a dot product with normalized vectors is always in the range [-1…1]. I guess he meant the same thing though.

You can try speeding your shader up by using a cubemap normalizer. On non SM3 hardware and not using half there is no fast native normalize instruction afaik.

Another hint: if you got an nvidia card, use half! Its range is limited (±65536 i think) but you can use it for unit length vectors, scalars, colors (texture values).

Originally posted by splat:

But there is another big optimisation:
a dot product never can become more than 1.0. That’s why you don’t need to clamp it. Use max(dot(), 0.0) instead, so it can’t become less than 0.0.

I am also trying to optimize my per-pixel-lighting and for me (GeForce FX5800) using max(dot(), 0) is slower than using clamp(dot(), 0.0, 1.0).
Probably the clamp turns into a dot_sat instruction? (If I remeber correctly, there is a _sat modifier)

Using a normalization cubemap is a big performance boost on a GeForceFX. Or is for me… :slight_smile:

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.