Pointlight attenuation

I already have a good lighting shader that uses a diffuse map, normal map, specular map and glossyness map. The problem is that I don’t know how to do the falloff. I have seen a few samples but they all rely on the info provided by the GL lights which I can’t use. All I have is the light position and the radius of the light and I would like to make it falloff like a pointlight.

Thanks in advance.

Light in the real world is proportional to the inverse squared distance from the light source. That should be pretty easy to compute in your shader…

I’m still having problems. I can now calculate the radius, the first problem is that the radius of impact is highly dependant on the geometry. If you make a box and carve a hole through it causing some funny triangulation, then the radius of impact gets messed up as you can see in the following pic:
http://img155.exs.cx/img155/2179/pointlighterror3we.jpg
The mesh looks like this:
http://img155.exs.cx/img155/1563/pointlighterrormesh0yy.jpg

Another problem is that I don’t know how to make it falloff in such way that there the falloff is smooth all the way to the end without making it obvious that the light shading stops at the end of the radius (unless the user specifies a really high intensity value).

Thanks in advance.

BTW, here is the shader I’m using, made with RenderMonkey.

VERTEX SHADER

uniform vec4 lightPos;
uniform vec4 view_position;

attribute vec3 rm_Tangent;
attribute vec3 rm_Binormal;

varying vec2  vTexCoord;
varying vec3  vLightVec;
varying vec3  vViewVec;
varying vec3  vNormal;

void main(void)
{
   gl_Position = ftransform();

   vTexCoord = vec2(gl_MultiTexCoord0);

   vNormal = gl_NormalMatrix * gl_Normal;

   vec3 lightVec = lightPos.xyz - gl_Vertex.xyz;
   vLightVec.x = dot(lightVec, rm_Tangent);
   vLightVec.y = dot(lightVec, rm_Binormal);
   vLightVec.z = dot(lightVec, gl_Normal);

   vec3 viewVec = view_position.xyz - gl_Vertex.xyz;
   vViewVec.x = dot(viewVec, rm_Tangent);
   vViewVec.y = dot(viewVec, rm_Binormal);
   vViewVec.z = dot(viewVec, gl_Normal);
}

FRAGMENT SHADER

uniform sampler2D Base;
uniform sampler2D Bump;
uniform sampler2D Spec;

uniform float specValue;
uniform float radius;
uniform float intensity;
uniform vec4  lightColor;

varying vec2  vTexCoord;
varying vec3  vLightVec;
varying vec3  vViewVec;
varying vec3  vNormal;

void main(void)
{
   float dist;
   float brightness;
   vec4 base = texture2D(Base, vTexCoord);
   vec3 bump = texture2D(Bump, vTexCoord) * 2.0 - 1.0;
   vec4 spec = texture2D(Spec, vTexCoord);

   bump          = normalize(bump);
   vec3 lightVec = normalize(vLightVec);
   vec3 viewVec  = normalize(vViewVec);

   // Standard lighting
   float diffuse = clamp(dot(lightVec, bump), 0.0, 1.0);
   float specular = pow(clamp(dot(reflect(-viewVec, bump), lightVec) ,0.0, 1.0), specValue);
   
   dist = length(vLightVec);
   
   if (dist < radius)
   {
      brightness = intensity * dist;
   }
   else
   {
      brightness = 0.0;
   }

   gl_FragColor = (diffuse * base + specular * (spec * 2.0)) * (lightColor * brightness);
}

Looks like you have things sort of turned around. Your intensity shouldn’t be proportional to dist. It should be proportional to 1.0 / (dist^2)

Don’t bother using length(), which has an expensive square root. You can use dot() instead to get dist^2

I still have problems with the shape of the pointlight, it isn’t perfectly rounded, it depends on the triangulation of the mesh, what can I do to fix that?

BTW, I don’t want to use an attenuation map, I would like to use a formula that just needs the radius and intensity as input values.

a reasonable approximation would be a gaussian.

something like:
iexp(-(x^2+y^2+z^2))
with:
i = intensity;
x = (3/2)
(dist.x/radius);
y = (3/2)(dist.y/radius);
z = (3/2)
(dist.z/radius);

note: the (3/2) is purely a “fudge” factor. this should give reasonable attenuation, but may need to be changed.

the -(x^2+y^2+z^2) could be replaced by a -(dot(vec)) where vec is the vector [x,y,z] to save computation time.

Originally posted by Baggio:
I still have problems with the shape of the pointlight, it isn’t perfectly rounded, it depends on the triangulation of the mesh, what can I do to fix that?
do the attenuation calculation in the fragment program and not the vertex program

Originally posted by zed:
[quote]Originally posted by Baggio:
I still have problems with the shape of the pointlight, it isn’t perfectly rounded, it depends on the triangulation of the mesh, what can I do to fix that?
do the attenuation calculation in the fragment program and not the vertex program
[/QUOTE]How can I do that?

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