Attenuation shader, correct or not correct?

Started by
2 comments, last by 21st Century Moose 10 years, 11 months ago

Is this the correct way of calculating and applying attenuation?

This is my basic diffuse shader with attenuation:

.vert


varying vec3 vertex_light_position;

varying vec3 vertex_light_half_vector;

varying vec4 color;

varying vec3 N;

varying vec3 v;
 void main(void)

{

    v = vec3(gl_ModelViewMatrix * gl_Vertex);

    N = normalize(gl_NormalMatrix * gl_Normal);
    color = gl_Color;

    vertex_light_position = normalize(gl_LightSource[0].position.xyz);
    vertex_light_half_vector = normalize(gl_LightSource[0].halfVector.xyz);



    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

}

.frag


varying vec3 vertex_light_position;

varying vec3 vertex_light_half_vector;

varying vec4 color;

varying vec3 N;

varying vec3 v;
void main()

{ 

   float constantAttenuation=1.0;

   float linearAttenuation=1.0;

   float quadraticAttenuation=0.02;
   float dist = length(gl_LightSource[0].position - v);

   float att = 1.0/(constantAttenuation + (linearAttenuation * dist) + (quadraticAttenuation * dist * dist));


   vec3 L = normalize(gl_LightSource[0].position.xyz - v);

   vec3 E = normalize(-v);

   vec3 R = normalize(reflect(-L,N));

  

   vec4 diffuse_color = vec4(0.0,1.0,0.0,0.0);

   float diffuse_value = max(dot(N,L), 0.0);

  

   if (gl_FrontFacing){

       gl_FragColor = color + (((diffuse_color-color) * (diffuse_value))*att);

   }else{

       gl_FragColor = color;

   }

  

}
Advertisement

The attenuation equation is 1/(k_c + k_l * d + k_q * d * d) so apparently in your code you got it right (d is distance, k_c constant coef., k_l linear coef., k_q quadratic coef.).

The thing is, that distance can grow quite fast, and at mere distance of 10 points your light intensity (in your case) is 1 / (1.0 + 1.0 * 10 + 0.02 * 10 * 10) = 1/13 ... so everything at distance of 10 will be quite dark (intensity less than 0.1).

So if you're getting dark image, just try to fine tune attenuation factors - linear should be just a fraction of constant attenuation and quadratic should be just a fraction of linear attenuation. For example: using 1.0 as constant coefficient, 0.007 as linear coefficient and 0.00003 as quadratic coefficient yields half intensity at distance of 100.

My current blog on programming, linux and stuff - http://gameprogrammerdiary.blogspot.com

Thanks, that makes sense!

Should be noted that there is no "correct" way of calculating attenuation in the shader-based world; the constant/linear/quadratic equation is consistent with old-school fixed-pipeline attenuation formulae, but with shaders you can use any attenuation formula you wish.

For a physically "correct" formula for light attenuation, you just need inverse-square (i.e. the quadratic portion of the formula you're currently using) but, once again, if using a different formula looks better with your source data or otherwise meets your requirements better, then by all means use it.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

This topic is closed to new replies.

Advertisement