2011
09.09

Lights in full color roguelikes

So long I’ve always used a very basic light model in my prototypes. For a point light at position lx,ly, the light reaching position x,y is :
int squaredDist = (lx-x)*(lx-x)+(ly-y)*(ly-y);
double intensityCoef = 1.0-squaredDist/(radius*radius);

The formula makes the intensity value 1.0 at light position and 0.0 at distance radius from the light.

It’s very fast (especially since 1.0/(radius*radius) can be precomputed) but doesn’t produce very good looking lights :

The intensity decreases linearly and seems to end abruptly at the light range.

A more realistic approach is to use the inverse square law. The light intensity decreases proportionnally to the inverse of square distance :

int squaredDist = (lx-x)*(lx-x)+(ly-y)*(ly-y);
double intensityCoef = 1.0/(1.0+squaredDist);

There are several issues with this naive approach :

  • The intensity decreases very rapidely. This forces us to have huge light radius, which impacts performances
  • The intensity doesn’t reach 0. At the light radius, it’s still 1.0/(1.0+radius*radius) and it drop abruptly to 0 after.

We can easily fix both issues. First we scale down the distance to keep the intensity from dropping too fast :
double intensityCoef1 = 1.0/(1.0+squaredDist/20);

Then we subtract the remaining intensity at radius range so that it reaches 0 :
double intensityCoef2 = intensityCoef1 - 1.0/(1.0+radius*radius);

The issue is that intensity at light position is no more 1.0 but 1.0 – 1.0/(1.0+radius*radius), which results is less bright lights.
To fix that, we scale the final intensity :
double intensityCoef3 = intensityCoef2 / (1.0 - 1.0/(1.0+radius*radius));

 

No Comment.

Add Your Comment