I need to obtain an attenuation like the doom3`s.
Especially the effect when the angle between the light and the surface is large the light contribution is smaller.
But NOT using bump mapping.
Also in doom3 when the light is closer to the surface the light contribution gets smaller instead of overlighting the surface.
Originally posted by Undertaker:
[b]ok…so what do I do with this dot product ?
In the d3 shaders they calculate atten as usual, how texcoords are calculated is the thingy[/b]
Look in the red book about the lighting equation GL uses. It goes in the diffuse ligthing part.
I don’t know about Doom3. Post the shader here and we will all have a look.
If you’re wanting to do an attenuation, I don’t think you need to use the dot product. That’ll give you the effect of the surfaces which are facing the light most directly being lit more intensely, which you mentioned above, I think - but attenuation (like what doom 3 does) is a function of distance from the light source. If you’re unclear on what to do with the dot product and the attenuation, consider that they are both measures of the amount of light energy that is reaching a surface (so you’re going to multiply them with the color of your fragment from a texture or whatnot). The dot product will give you an approximation of how light bounces diffusely when it hits the surface, and the attenuation factor will tell you how intense the light is when it hits the surface (because light gets weaker as it’s energy is spread over a greater distance).
attenuation might look something like…
atten = A / d
or
atten = A / d^B
where d is the distance from the fragment to the light source you’re evaluating. You can play around with the variables ‘A’ and ‘B’ to get an effect that appeals to you. ‘A’ sort of controls when the light starts to get really bright (when d is less than A) - essentially the light’s strength, and ‘B’ essentially controls the rate at which attentuaion occurs - so B = 2 will probably give you something realistic looking.
So take atten and multiply it by your fragment color, and multiply by the dot product, too. If you use both of these values (the dot and the atten), you’ll start to get something doom3-ish. This is pretty fast, too - so you can definitley use these functions in a scene with 8 lights or whatever.
dotproduct gives the squared distance of a vector, thus u can measure how far away something is
personally though WRT to calculating attenuation i prefer to use something linear like
float attenuation = (end-dist)/(end-start)
which gives an exact cutoff point, with the standard method even if youre a million miles away from the lightsource will never have 0 just a really small number which feels messy (even though it might be more inline with whatever reality does)
OK ,I used the dot prod like in :
(1-(d/r)^2) * dot , and it works…but not correctly because I calculate the light vector from a vertex to the light.
How can I interpolate the light vector across the surface for correct result ?
Originally posted by Undertaker: OK ,I used the dot prod like in :
(1-(d/r)^2) * dot , and it works…but not correctly because I calculate the light vector from a vertex to the light.
How can I interpolate the light vector across the surface for correct result ?
Pass the light vector as a texture coordinate. This will interpolate the vector across the polygon.
Try this: get the light vector in the vertex program, don’t normalize it, but instead scale it by the inverse of the light radius. This will let it interpolate correctly and also give you your squared attenuation by doing a dot product of this vector with itself in the fragment program. The squared attenuation will be from 0 to greater than 1, where >= 1 would be outside the light radius. So then you could do (1 - dot(lightvec, lightvec)) and clamp the result to [0, 1] to get your attenuation factor. As for the usual dot(normal, lightvec) part, you will still need the normalized light vector, which you can get either by passing the light vector (scaled or not, doesn’t matter) through a normalization cubemap or by normalizing it in the fragment program. Doing the normalization in the fragment program is faster and much better looking than using a cube map on my radeon 9800 pro, but cubemaps are probably better for geforce fx and older cards. Using this approach I was able to get nice bump mapping with specular and attenuation in a single pass on a geforce 3 using register combiners, or the equivalent on ATI.