David's Blog

Mostly Hobby Stuff

Light Attenuation

leave a comment »

Recently I have mostly been doing art stuff however one thing I found that needed improvement was the lighting system. I was using, the fairly awful standard method for computing light attenuation i.e.:

attenuation = 1.0f / (a + b*dist + c*dist*dist)

The reason this is bad is that it requires 3 rather unintuitive parameters, plus it may not fall off to zero at the edge of the lights range. There are a number of alternatives:

  • Use a texture (3D or 1D) to encode an arbitrary function. This would be a good way to go but it would increase the complexity of the material system and require more work to define the textures. In addition there is likely a performance cost. Since I am already heavily bandwidth bound I didn’t want to pay this cost.
  • Use smoothstep(), this produces nice looking results, but it provides little control.
  • Use something similar to the way spot light falloff is calculated. i.e. have a MinDistance parameter which specifies the range at which the light has full effect, then use a pow() to encode a falloff. The exponent gives a nice intuitive control for the rate of falloff. Hence I chose this solution.

For example:

float ComputeAttenuation(float3 position, float3 lightPosition, float4 attenuation)
	float dist = distance(position, lightPosition);
	float range = attenuation.w;

	if(dist < range)
        float attenMinDist = attenuation.x * range;
        float attenExponent = attenuation.y;
        //attenuation.z is unused for now

        float attenIn = clamp((range - dist) / (range - attenMinDist), 0.0f, 1.0f);
        float result = pow(abs(attenIn), attenExponent);

        return result;
		return 0;

Which is nice and simple and saves a huge amount of time when tweaking light attenuation.

At the moment I am working on improving my lighting performance, which really suffers once I start having 10s or 100s of lights in a level. Of course only a few are visible at once, but searching for the lights, evaluating filtering, shadows, setting effect constants etc is not good. So what I am doing is evaluating light<=>material bindings only when lights or objects move.

This however does lead to not being able to make the light selection view dependant, hence in principle lights could be bound which are not visible. However this is perhaps not a bad thing, since it will eliminate lights going on and off as the player moves. In addition lazy evaluating light bindings will make it easier for me to add support for static shadow maps.


Written by therealdblack

April 10, 2010 at 5:12 pm

Posted in Graphics, Hobby Game, XNA

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: