09.09

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