# Elliptical attenuation

## Recommended Posts

There is probably an obvious solution but i cant find.. how to calculate an elliptical attenuation (in a pixel shader) given an origin point and the distance betwen it and various other points.. Right now i'm doing a straightforward spherical attenuation..simply like this: saturate(length(IN.worldvertpos-atten_origin_pos)*atten_factor); where atten_factor is a small number like 0.00005; While i'm doing this for a fog volume calculation it could also be used for light attenuations and so on. The obvious thought is to simply scale the input vertex positions by a small vertical factor...this however doesnt have much parametrical control

##### Share on other sites
Interesting... I'm working on this very problem in regard to gravitation.

When I complete the line element in the next week or so (it will be parametric, based on r, phi and theta), I will pass it along your way if you are still interested.

In the meantime, you might want to check out the nvidia Dawn demo (there is a chapter in GPU Gems 2 on this). If I recall correctly, they used an elliptical cross-section when computing the light reflection/refraction caused by her hair.

##### Share on other sites
Quote:
 saturate(length(IN.worldvertpos-atten_origin_pos)*atten_factor);

Wouldn't that give 0 at the origin? Do you substract it from 1.0 before using it?

Quote:
 The obvious thought is to simply scale the input vertex positions by a small vertical factor...this however doesnt have much parametrical control

Don't scale the positions. Scale the offset vector from the attenuation origin, instead.

In the case of a spherical light source your atten_factor is proportional to the radius of the light's sphere of influence. You can simply use the inverse of the radius like this:

float3 offsetVec = (IN.worldvertpos.xyz - atten_origin_pos.xyz) / lightRadius;float attenuation = 1.0 - saturate(length(offsetVec));

Now in the case of an elliptical light source, you can specify 3 different scale factors for the offset vector. One radius for each axis. What you are doing is scale the object's vertex positions (in the light's space), in order for the light's shape to become a unit sphere. In the same way, if you want to allow rotation (e.g. the ellipsis isn't axis aligned) you can transform the offset vector by the inverse rotation matrix of the light and then scale it(or simply do a 3x3 matrix transformation), before calculating its length.

Hope that helps.

HellRaiZer