mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2025-12-21 15:42:35 +00:00
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.
152 lines
4.9 KiB
Plaintext
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
|