PDA

View Full Version : optimising per-pixel lighting shader



supagu
12-25-2004, 04:39 AM
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 :)
cheers

zed
12-25-2004, 11:40 AM
vec3 nEye = normalize( eye );
u can normalize this in the vs,
perhaps also the same with the normal
get rid of the if statement

wizzo
12-25-2004, 12:41 PM
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.

splat
12-28-2004, 01:48 AM
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.

Volker
12-28-2004, 02:57 AM
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).

gulgi
12-29-2004, 03:42 AM
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.. :)