Game Development Community

Lighting Falloff Changes (fixes?)

by Jacob Dankovchik · in Torque 3D Professional · 06/29/2012 (7:35 pm) · 2 replies

So I'm working on a game set entirely in a dungeon and thus requires a lot of moody lighting. In playing with lights, I couldn't help but notice that no matter what, I kept getting a really even, washed out look. The lights seem to always follow a near-linear falloff which just doesn't work well. Decided to do some checking around.

This is a light set with 0 1 0 for the attenuation ratio, so in other words fully linear:

i1018.photobucket.com/albums/af302/Darkshadow851/th_old_lin.jpg

And this is the same light but with 0 0 1, so fully quadratic:
i1018.photobucket.com/albums/af302/Darkshadow851/th_old_quad.jpg

Notice anything odd? The quadratic falloff is actually SLOWER of a decay than linear, when normally quadratic is way, way sooner. So obviously something isn't making sense...

I did some looking in to the way attenuation is calculated and ultimately, it didn't make much sense to me. It wants to take radius in to account to effect how it decays, which in my opinion it shouldn't really do. But on top of that, the overall calculation just... wasn't right. So here's what I did to make it just the proper falloffs without taking radius in to account.

What that means for you would be that sometimes your light will stop before it actually decays away, so you end up with a hard light edge. Also means that you may have a radius way bigger than you need.

But anyhow, the changes (they're nice and simple):

In advancedLightBinManager.cpp, around line 703, change attenRatio from Point2F to Point3F.

Remove
Point2F attenParams( ( 1.0f / radius ) * attenRatio.y,
                           ( 1.0f / ( radius * radius ) ) * attenRatio.z );

And change
matParams->setSafe( lightAttenuation, attenParams );
to
matParams->setSafe( lightAttenuation, attenRatio );
.

Next, go to the shader folder, under lighting/advanced, and open lightingUtils.hlsl. In the argument line for the attenuate function, change attParams from float2 to float3.

Now, replace the line that says
return 1.0 - dot( attParams, float2( dist, dist * dist ) );
with
return (1.0 * attParams.x) + ((1/dist)*attParams.y) + ((1/(dist*dist))*attParams.z);

That's the line that really has the most change to the entire thing. The last little bit is to open up pointLightP.hlsl and change
uniform float2 lightAttenuation
to
uniform float3 lightAttenuation
. Make this same change in spotLightP.hlsl and you're done! (I think. I'll admit, I did this all quite hastily)

But anyhow, the results.

This is the original lighting, 2 lights posted against walls that I use for torch lights (mesh not included). They are set to quadratic falloff.
i1018.photobucket.com/albums/af302/Darkshadow851/th_old_quad_wall.jpg


Now this is post-change, but with the brightness cranked up to get the radius a bit bigger:
i1018.photobucket.com/albums/af302/Darkshadow851/th_new_quad_wall.jpg


Not bad actually, because any light should be very very intense at its source. However it doesn't have the spread we need at quadratic. So let's try half quadratic, half linear.
i1018.photobucket.com/albums/af302/Darkshadow851/th_new_quadLin_wall.jpg

Much better, but still not quite there. We don't wanna go too much further though because then we'll lose out on that nice exponential drop that any natural light has. So what we can do instead is toss in a nice fill light! That'd be a low-brightness light with no shadows and constant intensity. This will smooth out the light in the dark areas and also bring back some of that intensity we lost by swapping to the half linear half quadratic.
i1018.photobucket.com/albums/af302/Darkshadow851/th_new_quadLin_wall_fill.jpg


And there we go. Got almost the same overall brightness level (a tiny bit darker, but I didn't bother to check to see if I needed to adjust the fill light) while also getting the much more intense look in the area immediate to the light. It now looks much more natural to a real-world light source. Not all washed out like Torque lights tend to be, and opens up the doors for some good moody light.

Thoughts, questions, comments, or concerns??

#1
06/29/2012 (11:32 pm)
Hmmm, nice 'correction' I will add this to my engine. I like the overall look. THANKS!

Ron
#2
07/02/2012 (12:55 am)
Good job there!
also replace (1/dist) with (1.0/max(0.00001, dist)) ,because you have an implicit conversion from int to float ,that may fall on some drivers and a possible nan.