PDA

View Full Version : Pointlight attenuation.



Baggio
04-01-2005, 07:21 AM
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.

mogumbo
04-01-2005, 08:27 AM
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....

Baggio
04-01-2005, 10:13 AM
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.

Baggio
04-01-2005, 10:25 AM
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);
}

mogumbo
04-01-2005, 04:49 PM
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

Baggio
04-04-2005, 04:56 AM
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?

Baggio
04-04-2005, 05:23 AM
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.

carl_lewis
04-04-2005, 06:50 AM
a reasonable approximation would be a gaussian.

something like:
i*exp(-(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.

zed
04-04-2005, 10:24 AM
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

Baggio
04-05-2005, 10:53 AM
Originally posted by zed:

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 programHow can I do that?