Strange shader performance

Hello! I’m trying to do a lighting shader and determine which lights are enabled. I made a simple IF to see what lights should be used but it slowed things down instead of speeding things up.

Following code is slower:


for(int i=0;i<5;i++){
  if(gl_LightSource[i].diffuse  != vec4(0.0,0.0,0.0,0.0))
    pointLight(i, n, v, shininess, amb, dif, spe);
}

Follwing code is faster (IF is commented out):


for(int i=0;i<5;i++){
  //if(gl_LightSource[i].diffuse  != vec4(0.0,0.0,0.0,0.0))
    pointLight(i, n, v, shininess, amb, dif, spe);
}

If using IF is a bad thing, how should I determine which lights are turned on? Any help appreciated.

How much faster ?
What is your video card ?
Is “pointLight” a costly function ?

Hardware support for conditionals is not always very fast.
Depending on the hardware, both branches are executed, and one discarded. Sometimes there is a fixed cost for IF.

In a simple scene which fills the entire screen I gain around 10-20 frames per second.

The pointLight function looks as follows:


void pointLight(in int i, in vec3 N, in vec3 V,
                in float shininess,
                inout vec4 ambient,
                inout vec4 diffuse,
                inout vec4 specular){
  vec3 halfVector;
  vec3 D = gl_LightSource[i].position.xyz - V;
  vec3 L = normalize(D);
  float pf=0.5;
  float nDotL=0.5;
  float dist = 1.0;
  float att = 0.5;
	
  dist = length(D);
  att = (1.0/(gl_LightSource[i].constantAttenuation +
              gl_LightSource[i].linearAttenuation * dist +
              gl_LightSource[i].quadraticAttenuation *
              dist * dist));

  nDotL = dot(N,L);
  pf = pow(max(0.0,dot(N,L)),shininess);	
  ambient  += gl_LightSource[i].ambient * att;	
  diffuse  += gl_LightSource[i].diffuse * nDotL * att;
  specular += gl_LightSource[i].specular * pf * att;
}

My video card is an GeForce 7800 GT.

It’s normal. Heard it many times now.
Conditionals are costly. They are worth it if there is a large number of instructions that can be skipped.
If a light is off, either set its properties to zero or write multiple shader versions, one for 1 light, another for 2 lights, etc.

You should try to use a boolean “lightEnabled” instead of testing if the diffuse color isn’t pure black. I think it’ll allow the driver to do some optimizations, since the state of a light is a constant for all pixels.

Is it really faster to have multiple versions of the same shader with different number of lights, even if I need to switch active shader a few times (3-8) per pass? That sounds like a strange work around.

It’s not as strange as it sounds.

Try it, you might like it.

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