General Lighting Improvements (#3482)

changes:

Z-lights can now shine both upwards and downwards.
Z-lights will now get less intense with each zlevel traversed.
Sunlight no longer has distance falloff.
Minor optimizations/simplification for directional lighting.
This commit is contained in:
Lohikar
2017-09-22 15:54:11 -06:00
committed by Erki
parent 0732abb600
commit 21e06212b6
5 changed files with 114 additions and 55 deletions

View File

@@ -34,7 +34,6 @@
var/tmp/cached_origin_x // The last known X coord of the origin.
var/tmp/cached_origin_y // The last known Y coord of the origin.
var/tmp/old_direction // The last known direction of the origin.
var/tmp/targ_sign // The sign to test the point against.
var/tmp/test_x_offset // How much the X coord should be offset due to direction.
var/tmp/test_y_offset // How much the Y coord should be offset due to direction.
var/tmp/facing_opaque = FALSE
@@ -46,6 +45,8 @@
var/needs_update = LIGHTING_NO_UPDATE
var/skip_falloff = FALSE // ONLY for use with sunlight, behavior is undefined if TRUE on regular sources.
/datum/light_source/New(atom/owner, atom/top)
source_atom = owner // Set our new owner.
@@ -68,8 +69,6 @@
//L_PROF(source_atom, "source_new([type])")
return ..()
// Kill ourselves.
/datum/light_source/Destroy(force)
//L_PROF(source_atom, "source_destroy")
@@ -159,31 +158,19 @@
#define MINMAX(NUM) ((NUM) < 0 ? -round(-(NUM)) : round(NUM))
#define ARBITRARY_NUMBER 10
/datum/light_source/proc/update_angle()
var/turf/T = get_turf(top_atom)
var/ndir
if (istype(top_atom, /mob) && top_atom:facing_dir)
ndir = top_atom:facing_dir
else
ndir = top_atom.dir
// Don't do anything if nothing is different, trig ain't free.
if (T.x == cached_origin_x && T.y == cached_origin_y && old_direction == ndir)
return
/datum/light_source/proc/regenerate_angle(ndir)
old_direction = ndir
var/turf/front = get_step(T, old_direction)
var/turf/front = get_step(source_turf, old_direction)
facing_opaque = (front && front.has_opaque_atom)
cached_origin_x = test_x_offset = T.x
cached_origin_y = test_y_offset = T.y
cached_origin_x = test_x_offset = source_turf.x
cached_origin_y = test_y_offset = source_turf.y
if (facing_opaque)
return
var/angle = light_angle / 2
var/angle = light_angle * 0.5
switch (old_direction)
if (NORTH)
limit_a_t = angle + 90
@@ -214,8 +201,6 @@
limit_b_x = MINMAX(limit_b_x)
limit_b_y = POLAR_TO_CART_Y(light_range + ARBITRARY_NUMBER, limit_b_t)
limit_b_y = MINMAX(limit_b_y)
// This won't change unless the origin or dir changes, might as well do it here.
targ_sign = PSEUDO_WEDGE(limit_a_x, limit_a_y, limit_b_x, limit_b_y) > 0
#undef ARBITRARY_NUMBER
#undef POLAR_TO_CART_X
@@ -248,7 +233,16 @@
var/actual_range = light_range
APPLY_CORNER(C,now)
var/Sx = source_turf.x
var/Sy = source_turf.y
var/Sz = source_turf.z
if (skip_falloff)
APPLY_CORNER_SIMPLE(C)
else
var/height = C.z == Sz ? LIGHTING_HEIGHT : CALCULATE_CORNER_HEIGHT(C.z, Sz)
APPLY_CORNER(C, now, Sx, Sy, height)
UNSETEMPTY(effect_str)
// If you update this, update the equivalent proc in lighting_source_novis.dm.
@@ -305,11 +299,36 @@
light_angle = source_atom.light_wedge
update = TRUE
if (light_angle && top_atom.dir != old_direction)
update = TRUE
if (light_angle)
var/ndir
if (istype(top_atom, /mob) && top_atom:facing_dir)
ndir = top_atom:facing_dir
else
ndir = top_atom.dir
if (update && light_angle)
update_angle()
if (old_direction != ndir) // If our direction has changed, we need to regenerate all the angle info.
regenerate_angle(ndir)
update = TRUE
else // Check if it was just a x/y translation, and update our vars without an regenerate_angle() call if it is.
var/co_updated = FALSE
if (source_turf.x != cached_origin_x)
test_x_offset += source_turf.x - cached_origin_x
cached_origin_x = source_turf.x
co_updated = TRUE
if (source_turf.y != cached_origin_y)
test_y_offset += source_turf.y - cached_origin_y
cached_origin_y = source_turf.y
co_updated = TRUE
if (co_updated)
// We might be facing a wall now.
var/turf/front = get_step(source_turf, old_direction)
facing_opaque = (front && front.has_opaque_atom)
update = TRUE
if (update)
needs_update = LIGHTING_CHECK_UPDATE
@@ -324,11 +343,18 @@
var/list/Tcorners
var/Sx = source_turf.x
var/Sy = source_turf.y
var/Sz = source_turf.z
var/corner_height = LIGHTING_HEIGHT
var/actual_range = (light_angle && facing_opaque) ? light_range * LIGHTING_BLOCKED_FACTOR : light_range
var/test_x
var/test_y
FOR_DVIEW(T, Ceiling(actual_range), source_turf, 0)
var/zlights_going_up = FALSE
var/turf/originalT // This is needed to reset our search point for bidirectional Z-lights.
FOR_DVIEW(originalT, Ceiling(actual_range), source_turf, 0)
T = originalT
zlights_going_up = FALSE
check_t:
if (light_angle && !facing_opaque) // Directional lighting coordinate filter.
@@ -336,7 +362,7 @@
test_y = T.y - test_y_offset
// if the signs of both of these are NOT the same, the point is NOT within the cone.
if (((PSEUDO_WEDGE(limit_a_x, limit_a_y, test_x, test_y) > 0) != targ_sign) || ((PSEUDO_WEDGE(test_x, test_y, limit_b_x, limit_b_y) > 0) != targ_sign))
if ((PSEUDO_WEDGE(limit_a_x, limit_a_y, test_x, test_y) > 0) || (PSEUDO_WEDGE(test_x, test_y, limit_b_x, limit_b_y) > 0))
continue
if (T.dynamic_lighting || T.light_sources)
@@ -362,9 +388,21 @@
turfs += T
if (isopenturf(T) && T:below)
T = T:below // Consider the turf below us as well. (Z-lights)
goto check_t
// Note: above is defined on ALL turfs, but below is only defined on OPEN TURFS.
zlight_check:
if (zlights_going_up) // If we're searching upwards, check above.
if (istype(T.above)) // We escape the goto loop if this condition is false.
T = T.above
goto check_t
else
if (isopenturf(T) && T:below) // Not searching upwards and we have a below turf.
T = T:below // Consider the turf below us as well. (Z-lights)
goto check_t
else // Not searching upwards and we don't have a below turf.
zlights_going_up = TRUE
T = originalT
goto zlight_check
END_FOR_DVIEW
@@ -391,7 +429,7 @@
effect_str[C] = 0
continue
APPLY_CORNER_XY(C, now, Sx, Sy)
APPLY_CORNER_BY_HEIGHT(now)
else
L = corners - effect_str
for (thing in L)
@@ -401,7 +439,7 @@
effect_str[C] = 0
continue
APPLY_CORNER_XY(C, now, Sx, Sy)
APPLY_CORNER_BY_HEIGHT(now)
for (thing in corners - L)
C = thing
@@ -409,7 +447,7 @@
effect_str[C] = 0
continue
APPLY_CORNER_XY(C, now, Sx, Sy)
APPLY_CORNER_BY_HEIGHT(now)
L = effect_str - corners
for (thing in L)