Re: A Lighting Model
- From: Jeff Lait <torespondisfutile@xxxxxxxxxxx>
- Date: Mon, 10 Mar 2008 10:19:24 -0700 (PDT)
On Mar 10, 11:44 am, jice <jice.nos...@xxxxxxxxx> wrote:
On 10 mar, 15:20, Jeff Lait <torespondisfut...@xxxxxxxxxxx> wrote:
Next, I want to attack the whole idea of using inverse-square. This
is a waste of your time. While light follows inverse-square, the
thing you want to model is your character's *perception* of the
light. Your eyes are extremely non-linear. I can look out the window
and see the window frame despite orders of magnitudes difference in
"brightness".
What this non-linearity means is that you should not be tempted to
hold any fall-off curve as "correct". Especially not one as harsh as
a inverse-square. You can pick whatever fall-off curve gives you the
best aesthetic results.
light *= 1 / (a + b*d + c*d*d)
where a, b, and c are tuneable parameters and d is the distance to the
light source.
I'd go for a = 0, b = 1, c = 0 and try out a pure linear fall off.
On another hand, a good point of the inverse square law is that it's
very easy and fast to implement :
float invSquaredLightRadius = 1.0f / 100 ; // light with 10 meters
radius
float squaredDistanceToLight = dx*dx+dy*dy; // squared distance to
light. no sqrt needed
float intensity = 1.0f - squaredDistanceToLight *
invSquaredLightRadius;
Cells getting an intensity > 0.0 are lit.
Might be quick to write down, but not so quick to get right. This
isn't inverse square fall off, but a linear-squared fall off. It has
a parabolic shape and looks very different from an actual inverse
square fall off:
float intensity = 1.0f / (squaredDistanceToLight *
invSquaredLightRadius);
Note that I would actually prefer your fall off to the actual inverse
square law. But, I think, that was my entire point - you should chose
your fall off function based on aesthetic, not physics.
You have only a few multiplications per cell. You avoid especially the
sqrt operation needed to get the distance (ok, John Carmack's magical
trick can help you to get this faster).
If you care about sqrt, you could always just use a table lookup for
your distance calculations. Roguelikes have a very coarse grid, so
float
slowdist(int x, int y)
{
return sqrt(x*x+y*y);
}
float
dist(int x, int y)
{
int idx
x = abs(x);
y = abs(y);
if (x > y)
{
if (x > MAXDIST)
return slowdist(x, y);
idx = (x * (x+1) / 2) + y;
}
else
{
if (y > MAXDIST)
return slowdist(x, y);
idx = (y * (y+1) / 2) + x;
}
return theLightTable[idx];
}
where theLightTable is a precalculated distance table consisting of
MAXDIST*(MAXDIST+1)/2 floats storing the relevant octant's carefully
calculated distance:
float theLightTable[MAXDIST*(MAXDIST+1)/2];
void
builddist()
{
int x, y, idx;
for (x = 0; x < MADIST; x++)
{
for (y = 0; y <= x; y++)
{
theLightTable[x*(x+1)/2 + y] = slowdist(x, y);
}
}
}
Note that the complexity of this does not count against the complexity
of the lighting calculation since one could always use the simple &
fast to implement slowdist(), only invoking this cache if you find
yourself on the Gameboy Advance. (In which case it is as important to
throw out those floats as well :>)
--
Jeff Lait
(POWDER: http://www.zincland.com/powder)
.
- Follow-Ups:
- Re: A Lighting Model
- From: jice
- Re: A Lighting Model
- References:
- A Lighting Model
- From: Paladin_za
- Re: A Lighting Model
- From: uschkinredsunshine@xxxxxx
- Re: A Lighting Model
- From: Martin Read
- Re: A Lighting Model
- From: uschkinredsunshine@xxxxxx
- Re: A Lighting Model
- From: Paul Donnelly
- Re: A Lighting Model
- From: Jeff Lait
- Re: A Lighting Model
- From: jice
- A Lighting Model
- Prev by Date: Re: A Lighting Model
- Next by Date: Re: libtcod 1.2.1 released
- Previous by thread: Re: A Lighting Model
- Next by thread: Re: A Lighting Model
- Index(es):
Relevant Pages
|