Here's an example of the shadowing mechanism I wrote about
early in this thread.
Extract and compile the attachment using
Code:
tar -xzvf shadow.tar.gz.txt
cd shadow/
make
The example program creates a 510x510 grayscale PGM file
test.pgm. Check out the
example I attached.
The
visibility() function in
shadow.h can create a visibility map up to 255 tiles away from the origin. The origin must be within the map. Usage:
Code:
visibility(width, height, origin_x, origin_y,
result_map, result_x_stride, result_y_stride,
obstacle_map, obstacle_x_stride, obstacle_y_stride);
The
_x_stride parameters define the size of each tile, and
_y_stride parameters define the size of each row of tiles.
obstacle_map defines the opacity of the obstacles, 0 for totally transparent, 255 for totally opaque. This map is only read, never modified.
The resulting visibility map is saved in
result_map, where 255 indicates fully visible and 0 indicates hidden.
Note that the weights in
shadow.h are not truly accurate; visibility is not uniform in all directions. This is not too difficult to fix; I just didn't bother since I don't actually need this for anything myself. (I used a quick script to calculate the weights.)
The key feature in this method is speed. Running time of the
visibility() function depends only on the size of the map (i.e. it is O(
width×
height)), not on the number or type of the obstacles in it. On my machine,
visibility() takes about 80 clock cycles per tile, or about 20 million clock cycles for the 510x510 tile map in the example program. Optimizing the arrays for each specific use case would make it even faster.
Note that this same function can be used to implement point lights: allocate a temporary light map, apply
visibility() to the obstacles around the light, saving the result to the temporary light map, then sum (with clamping) the temporary light map to the overall light map. Although the current weights do not have distance attenuation, another weight table can be easily created for each light type; with a bit of code tweaking, you could even do directional lights.