|
|
@ -5,29 +5,10 @@ |
|
|
|
using std::vector; |
|
|
|
using std::vector; |
|
|
|
|
|
|
|
|
|
|
|
namespace lighting { |
|
|
|
namespace lighting { |
|
|
|
|
|
|
|
|
|
|
|
void LightRender::render_circle_light(LightSource source, Point at, PointList &has_light) { |
|
|
|
|
|
|
|
for(matrix::circle it{$lightmap, at, source.radius}; it.next();) { |
|
|
|
|
|
|
|
for(int x = it.left; x < it.right; x++) { |
|
|
|
|
|
|
|
$lightmap[it.y][x] = light_level(source.strength, x, it.y); |
|
|
|
|
|
|
|
has_light.push_back({(size_t)x, (size_t)it.y}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void LightRender::render_compass_light(LightSource source, Point at, PointList &has_light) { |
|
|
|
|
|
|
|
for(matrix::compass it{$lightmap, at.x, at.y}; it.next();) { |
|
|
|
|
|
|
|
if($paths.$paths[it.y][it.x] != WALL_PATH_LIMIT) { |
|
|
|
|
|
|
|
$lightmap[it.y][it.x] = light_level(source.strength, it.x, it.y); |
|
|
|
|
|
|
|
has_light.push_back({it.x, it.y}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void LightRender::render_square_light(LightSource source, Point at, PointList &has_light) { |
|
|
|
void LightRender::render_square_light(LightSource source, Point at, PointList &has_light) { |
|
|
|
for(matrix::in_box it{$lightmap, at.x, at.y, (size_t)floor(source.radius)}; it.next();) { |
|
|
|
for(matrix::in_box it{$lightmap, at.x, at.y, (size_t)floor(source.radius)}; it.next();) { |
|
|
|
if($paths.$paths[it.y][it.x] != WALL_PATH_LIMIT) { |
|
|
|
if($paths.$paths[it.y][it.x] != WALL_PATH_LIMIT) { |
|
|
|
$lightmap[it.y][it.x] = light_level(source.strength, it.x, it.y); |
|
|
|
$lightmap[it.y][it.x] = light_level(source.strength, it.distance(), it.x, it.y); |
|
|
|
has_light.push_back({it.x, it.y}); |
|
|
|
has_light.push_back({it.x, it.y}); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -38,26 +19,22 @@ namespace lighting { |
|
|
|
clear_light_target(at); |
|
|
|
clear_light_target(at); |
|
|
|
PointList has_light; |
|
|
|
PointList has_light; |
|
|
|
|
|
|
|
|
|
|
|
if(source.radius < 1.5f) { |
|
|
|
render_square_light(source, at, has_light); |
|
|
|
render_compass_light(source, at, has_light); |
|
|
|
|
|
|
|
} else if(source.radius < 2.0f) { |
|
|
|
|
|
|
|
render_square_light(source, at, has_light); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
render_circle_light(source, at, has_light); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const int wall_light = source.strength + WALL_LIGHT_LEVEL; |
|
|
|
const int wall_light = source.strength + WALL_LIGHT_LEVEL; |
|
|
|
for(auto point : has_light) { |
|
|
|
for(auto point : has_light) { |
|
|
|
for(matrix::compass it{$lightmap, point.x, point.y}; it.next();) { |
|
|
|
for(matrix::compass it{$lightmap, point.x, point.y}; it.next();) { |
|
|
|
if($paths.$paths[it.y][it.x] == WALL_PATH_LIMIT) { |
|
|
|
if($paths.$paths[it.y][it.x] == WALL_PATH_LIMIT) { |
|
|
|
$lightmap[it.y][it.x] = light_level(wall_light, point.x, point.y); |
|
|
|
// BUG: include the distance in the list of walls to light
|
|
|
|
|
|
|
|
// so that they will be closer to the light level at that point
|
|
|
|
|
|
|
|
$lightmap[it.y][it.x] = light_level(wall_light, 1.0f, point.x, point.y); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int LightRender::light_level(int level, size_t x, size_t y) { |
|
|
|
int LightRender::light_level(int level, float distance, size_t x, size_t y) { |
|
|
|
size_t at = level + $paths.$paths[y][x]; |
|
|
|
size_t at = level + ceil(distance); |
|
|
|
int cur_level = $lightmap[y][x]; |
|
|
|
int cur_level = $lightmap[y][x]; |
|
|
|
int new_level = at < lighting::LEVELS.size() ? lighting::LEVELS[at] : lighting::MIN; |
|
|
|
int new_level = at < lighting::LEVELS.size() ? lighting::LEVELS[at] : lighting::MIN; |
|
|
|
return cur_level < new_level ? new_level : cur_level; |
|
|
|
return cur_level < new_level ? new_level : cur_level; |
|
|
|