Files
Aurora.3/code/modules/lighting/lighting_corner.dm
Lohikar fac6d7916c Lighting performance tweaks (#2200)
Port of tgstation/tgstation#26975.

Changes the lighting engine to apply lighting changes in one step using stored lum value differences instead of two steps (remove_lum, add_lum).

Seems to show a speedup in lighting updates as well as a reduction in server memory usage due to aggressive freeing of unneeded lists.

Lighting overlays also default to fullbright instead of fulldark so movable area transitions look less strange.
2017-05-15 22:25:13 +03:00

152 lines
4.9 KiB
Plaintext

/var/datum/lighting_corner/dummy/dummy_lighting_corner = new
// Because we can control each corner of every lighting overlay.
// And corners get shared between multiple turfs (unless you're on the corners of the map, then 1 corner doesn't).
// For the record: these should never ever ever be deleted, even if the turf doesn't have dynamic lighting.
// This list is what the code that assigns corners listens to, the order in this list is the order in which corners are added to the /turf/corners list.
/var/list/LIGHTING_CORNER_DIAGONAL = list(NORTHEAST, SOUTHEAST, SOUTHWEST, NORTHWEST)
/datum/lighting_corner
var/list/turf/masters
var/list/datum/light_source/affecting // Light sources affecting us.
var/active = FALSE // TRUE if one of our masters has dynamic lighting.
var/x = 0
var/y = 0
var/z = 0
var/lum_r = 0
var/lum_g = 0
var/lum_b = 0
var/lum_u = 0 // UV Radiation, not visible.
var/needs_update = FALSE
var/cache_r = 0
var/cache_g = 0
var/cache_b = 0
var/cache_u = 0
var/cache_mx = 0
/datum/lighting_corner/New(var/turf/new_turf, var/diagonal)
. = ..()
SSlighting.lighting_corners += src
masters = list()
masters[new_turf] = turn(diagonal, 180)
z = new_turf.z
var/vertical = diagonal & ~(diagonal - 1) // The horizontal directions (4 and 8) are bigger than the vertical ones (1 and 2), so we can reliably say the lsb is the horizontal direction.
var/horizontal = diagonal & ~vertical // Now that we know the horizontal one we can get the vertical one.
x = new_turf.x + (horizontal == EAST ? 0.5 : -0.5)
y = new_turf.y + (vertical == NORTH ? 0.5 : -0.5)
// My initial plan was to make this loop through a list of all the dirs (horizontal, vertical, diagonal).
// Issue being that the only way I could think of doing it was very messy, slow and honestly overengineered.
// So we'll have this hardcode instead.
var/turf/T
var/i
// Diagonal one is easy.
T = get_step(new_turf, diagonal)
if (T) // In case we're on the map's border.
if (!T.corners)
T.corners = list(null, null, null, null)
masters[T] = diagonal
i = LIGHTING_CORNER_DIAGONAL.Find(turn(diagonal, 180))
T.corners[i] = src
// Now the horizontal one.
T = get_step(new_turf, horizontal)
if (T) // Ditto.
if (!T.corners)
T.corners = list(null, null, null, null)
masters[T] = ((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH) // Get the dir based on coordinates.
i = LIGHTING_CORNER_DIAGONAL.Find(turn(masters[T], 180))
T.corners[i] = src
// And finally the vertical one.
T = get_step(new_turf, vertical)
if (T)
if (!T.corners)
T.corners = list(null, null, null, null)
masters[T] = ((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH) // Get the dir based on coordinates.
i = LIGHTING_CORNER_DIAGONAL.Find(turn(masters[T], 180))
T.corners[i] = src
update_active()
/datum/lighting_corner/proc/update_active()
active = FALSE
for (var/turf/T in masters)
if (T.lighting_overlay)
active = TRUE
// God that was a mess, now to do the rest of the corner code! Hooray!
/datum/lighting_corner/proc/update_lumcount(var/delta_r, var/delta_g, var/delta_b, var/delta_u, var/now = FALSE)
lum_r += delta_r
lum_g += delta_g
lum_b += delta_b
lum_u += delta_u
if (needs_update)
return
if (!now)
needs_update = TRUE
update_overlays(FALSE)
SSlighting.corner_queue += src
else
update_overlays(TRUE)
/datum/lighting_corner/proc/update_overlays(var/now = FALSE)
// Cache these values a head of time so 4 individual lighting overlays don't all calculate them individually.
var/mx = max(lum_r, lum_g, lum_b) // Scale it so 1 is the strongest lum, if it is above 1.
. = 1 // factor
if (mx > 1)
. = 1 / mx
else if (mx < LIGHTING_SOFT_THRESHOLD)
. = 0 // 0 means soft lighting.
#ifdef LIGHTING_USE_MEMORY_HACK
cache_r = lum_r * . + (rand(1,999)/100000) || LIGHTING_SOFT_THRESHOLD
cache_g = lum_g * . + (rand(1,999)/100000) || LIGHTING_SOFT_THRESHOLD
cache_b = lum_b * . + (rand(1,999)/100000) || LIGHTING_SOFT_THRESHOLD
cache_u = lum_u * . || LIGHTING_SOFT_THRESHOLD
cache_mx = mx
#else
cache_r = round(lum_r * ., LIGHTING_ROUND_VALUE) || LIGHTING_SOFT_THRESHOLD
cache_g = round(lum_g * ., LIGHTING_ROUND_VALUE) || LIGHTING_SOFT_THRESHOLD
cache_b = round(lum_b * ., LIGHTING_ROUND_VALUE) || LIGHTING_SOFT_THRESHOLD
cache_u = lum_u * . || LIGHTING_SOFT_THRESHOLD
cache_mx = round(mx, LIGHTING_ROUND_VALUE)
#endif
for (var/TT in masters)
var/turf/T = TT
if (T.lighting_overlay)
if (now)
T.lighting_overlay.update_overlay()
else if (!T.lighting_overlay.needs_update)
T.lighting_overlay.needs_update = TRUE
SSlighting.overlay_queue += T.lighting_overlay
/datum/lighting_corner/Destroy(force = FALSE)
crash_with("Some fuck [force ? "force-" : ""]deleted a lighting corner.")
if (!force)
return QDEL_HINT_LETMELIVE
SSlighting.lighting_corners -= src
return ..()
/datum/lighting_corner/dummy/New()
return