mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 10:12:45 +00:00
[MIRROR] Micro-opt lighting (#9268)
Co-authored-by: ShadowLarkens <shadowlarkens@gmail.com> Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
SUBSYSTEM_DEF(lighting)
|
||||
name = "Lighting"
|
||||
wait = 2
|
||||
wait = 1 // CHOMPEdit
|
||||
init_order = INIT_ORDER_LIGHTING
|
||||
flags = SS_TICKER
|
||||
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY //CHOMPEdit Do some work during lobby waiting period. May as well.
|
||||
|
||||
@@ -30,37 +30,49 @@
|
||||
///whether we are to be added to SSlighting's corners_queue list for an update
|
||||
var/needs_update = FALSE
|
||||
|
||||
/datum/lighting_corner/New(turf/new_turf, diagonal)
|
||||
/datum/lighting_corner/New(x, y, z, dynamic) // CHOMPEdit
|
||||
. = ..()
|
||||
save_master(new_turf, turn(diagonal, 180))
|
||||
|
||||
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.
|
||||
src.x = x + 0.5
|
||||
src.y = y + 0.5
|
||||
|
||||
x = new_turf.x + (horizontal == EAST ? 0.5 : -0.5)
|
||||
y = new_turf.y + (vertical == NORTH ? 0.5 : -0.5)
|
||||
// Alright. We're gonna take a set of coords, and from them do a loop clockwise
|
||||
// To build out the turfs adjacent to us. This is pretty fast
|
||||
var/turf/process_next = locate(x, y, z)
|
||||
if(process_next)
|
||||
master_SW = process_next
|
||||
process_next.lighting_corner_NE = src
|
||||
// Now, we go north!
|
||||
process_next = get_step(process_next, NORTH)
|
||||
else
|
||||
// Yes this is slightly slower then having a guarenteeed turf, but there aren't many null turfs
|
||||
// So this is pretty damn fast
|
||||
process_next = locate(x, y + 1, z)
|
||||
|
||||
// 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/new_master_turf
|
||||
// Ok, if we have a north turf, go there. otherwise, onto the next
|
||||
if(process_next)
|
||||
master_NW = process_next
|
||||
process_next.lighting_corner_SE = src
|
||||
// Now, TO THE EAST
|
||||
process_next = get_step(process_next, EAST)
|
||||
else
|
||||
process_next = locate(x + 1, y + 1, z)
|
||||
|
||||
// Diagonal one is easy.
|
||||
new_master_turf = get_step(new_turf, diagonal)
|
||||
if (new_master_turf) // In case we're on the map's border.
|
||||
save_master(new_master_turf, diagonal)
|
||||
// Etc etc
|
||||
if(process_next)
|
||||
master_NE = process_next
|
||||
process_next.lighting_corner_SW = src
|
||||
// Now, TO THE SOUTH AGAIN (SE)
|
||||
process_next = get_step(process_next, SOUTH)
|
||||
else
|
||||
process_next = locate(x + 1, y, z)
|
||||
|
||||
// Now the horizontal one.
|
||||
new_master_turf = get_step(new_turf, horizontal)
|
||||
if (new_master_turf) // Ditto.
|
||||
save_master(new_master_turf, ((new_master_turf.x > x) ? EAST : WEST) | ((new_master_turf.y > y) ? NORTH : SOUTH)) // Get the dir based on coordinates.
|
||||
// anddd the last tile
|
||||
if(process_next)
|
||||
master_SE = process_next
|
||||
process_next.lighting_corner_NW = src
|
||||
|
||||
// And finally the vertical one.
|
||||
new_master_turf = get_step(new_turf, vertical)
|
||||
if (new_master_turf)
|
||||
save_master(new_master_turf, ((new_master_turf.x > x) ? EAST : WEST) | ((new_master_turf.y > y) ? NORTH : SOUTH)) // Get the dir based on coordinates.
|
||||
|
||||
if(((SSplanets && SSplanets.z_to_planet.len >= new_turf.z && SSplanets.z_to_planet[new_turf.z]) || SSlighting.get_pshandler_z(new_turf.z)) && new_turf.has_dynamic_lighting()) sunlight = SUNLIGHT_POSSIBLE //CHOMPEdit
|
||||
if(((SSplanets && SSplanets.z_to_planet.len >= z && SSplanets.z_to_planet[z]) || SSlighting.get_pshandler_z(z)) && dynamic) sunlight = SUNLIGHT_POSSIBLE //CHOMPEdit
|
||||
|
||||
/datum/lighting_corner/proc/save_master(turf/master, dir)
|
||||
switch (dir)
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
|
||||
var/static/datum/lighting_corner/dummy/dummy_lighting_corner = new
|
||||
|
||||
var/turf/affected_turf = src.affected_turf
|
||||
var/datum/lighting_corner/red_corner = affected_turf.lighting_corner_SW || dummy_lighting_corner
|
||||
var/datum/lighting_corner/green_corner = affected_turf.lighting_corner_SE || dummy_lighting_corner
|
||||
var/datum/lighting_corner/blue_corner = affected_turf.lighting_corner_NW || dummy_lighting_corner
|
||||
@@ -68,22 +69,6 @@
|
||||
|
||||
var/max = max(red_corner.largest_color_luminosity, green_corner.largest_color_luminosity, blue_corner.largest_color_luminosity, alpha_corner.largest_color_luminosity)
|
||||
|
||||
var/rr = red_corner.cache_r
|
||||
var/rg = red_corner.cache_g
|
||||
var/rb = red_corner.cache_b
|
||||
|
||||
var/gr = green_corner.cache_r
|
||||
var/gg = green_corner.cache_g
|
||||
var/gb = green_corner.cache_b
|
||||
|
||||
var/br = blue_corner.cache_r
|
||||
var/bg = blue_corner.cache_g
|
||||
var/bb = blue_corner.cache_b
|
||||
|
||||
var/ar = alpha_corner.cache_r
|
||||
var/ag = alpha_corner.cache_g
|
||||
var/ab = alpha_corner.cache_b
|
||||
|
||||
#if LIGHTING_SOFT_THRESHOLD != 0
|
||||
var/set_luminosity = max > LIGHTING_SOFT_THRESHOLD
|
||||
#else
|
||||
@@ -92,31 +77,31 @@
|
||||
var/set_luminosity = max > 1e-6
|
||||
#endif
|
||||
|
||||
if((rr & gr & br & ar) && (rg + gg + bg + ag + rb + gb + bb + ab == 8))
|
||||
//anything that passes the first case is very likely to pass the second, and addition is a little faster in this case
|
||||
var/mutable_appearance/current_underlay = src.current_underlay
|
||||
affected_turf.underlays -= current_underlay
|
||||
if(red_corner.cache_r & green_corner.cache_r & blue_corner.cache_r & alpha_corner.cache_r && \
|
||||
(red_corner.cache_g + green_corner.cache_g + blue_corner.cache_g + alpha_corner.cache_g + \
|
||||
red_corner.cache_b + green_corner.cache_b + blue_corner.cache_b + alpha_corner.cache_b == 8))
|
||||
//anything that passes the first case is very likely to pass the second, and addition is a little faster in this case
|
||||
current_underlay.icon_state = "transparent"
|
||||
current_underlay.color = null
|
||||
affected_turf.underlays |= current_underlay
|
||||
else if(!set_luminosity)
|
||||
affected_turf.underlays -= current_underlay
|
||||
current_underlay.icon_state = "dark"
|
||||
current_underlay.color = null
|
||||
affected_turf.underlays |= current_underlay
|
||||
else
|
||||
affected_turf.underlays -= current_underlay
|
||||
current_underlay.icon_state = "gradient"
|
||||
current_underlay.color = null //CHOMPEdit
|
||||
current_underlay.color = list(
|
||||
rr, rg, rb, 00,
|
||||
gr, gg, gb, 00,
|
||||
br, bg, bb, 00,
|
||||
ar, ag, ab, 00,
|
||||
red_corner.cache_r, red_corner.cache_g, red_corner.cache_b, 00,
|
||||
green_corner.cache_r, green_corner.cache_g, green_corner.cache_b, 00,
|
||||
blue_corner.cache_r, blue_corner.cache_g, blue_corner.cache_b, 00,
|
||||
alpha_corner.cache_r, alpha_corner.cache_g, alpha_corner.cache_b, 00,
|
||||
00, 00, 00, 01
|
||||
)
|
||||
|
||||
affected_turf.underlays |= current_underlay
|
||||
|
||||
// Of note. Most of the cost in this proc is here, I think because color matrix'd underlays DO NOT cache well, which is what adding to underlays does
|
||||
// We use underlays because objects on each tile would fuck with maptick. if that ever changes, use an object for this instead
|
||||
affected_turf.underlays += current_underlay
|
||||
affected_turf.set_luminosity(set_luminosity)
|
||||
|
||||
/datum/lighting_object/proc/removefromturf()
|
||||
|
||||
@@ -111,28 +111,44 @@
|
||||
// As such this all gets counted as a single line.
|
||||
// The braces and semicolons are there to be able to do this on a single line.
|
||||
|
||||
// /tg/ falloff alg
|
||||
#define LUM_FALLOFF(C, T) (1 - CLAMP01(sqrt((C.x - T.x) ** 2 + (C.y - T.y) ** 2 + LIGHTING_HEIGHT) / max(1, light_range)))
|
||||
// This exists so we can cache the vars used in this macro, and save MASSIVE time :)
|
||||
// Most of this is saving off datum var accesses, tho some of it does actually cache computation
|
||||
// You will NEED to call this before you call APPLY_CORNER
|
||||
#define SETUP_CORNERS_CACHE(lighting_source) \
|
||||
var/_turf_x = lighting_source.pixel_turf.x; \
|
||||
var/_turf_y = lighting_source.pixel_turf.y; \
|
||||
var/_range_divisor = max(1, lighting_source.light_range); \
|
||||
var/_light_power = lighting_source.light_power; \
|
||||
var/_applied_lum_r = lighting_source.applied_lum_r; \
|
||||
var/_applied_lum_g = lighting_source.applied_lum_g; \
|
||||
var/_applied_lum_b = lighting_source.applied_lum_b; \
|
||||
var/_lum_r = lighting_source.lum_r; \
|
||||
var/_lum_g = lighting_source.lum_g; \
|
||||
var/_lum_b = lighting_source.lum_b; \
|
||||
|
||||
// Bay/Polaris falloff alg
|
||||
//#define LUM_FALLOFF(C, T)(1 - CLAMP01(((C.x - T.x) ** 2 +(C.y - T.y) ** 2 + LIGHTING_HEIGHT) ** 0.6 / max(1, light_range)))
|
||||
#define SETUP_CORNERS_REMOVAL_CACHE(lighting_source) \
|
||||
var/_applied_lum_r = lighting_source.applied_lum_r; \
|
||||
var/_applied_lum_g = lighting_source.applied_lum_g; \
|
||||
var/_applied_lum_b = lighting_source.applied_lum_b;
|
||||
|
||||
#define LUM_FALLOFF(C) (1 - CLAMP01(sqrt((C.x - _turf_x) ** 2 + (C.y - _turf_y) ** 2 + LIGHTING_HEIGHT) / _range_divisor))
|
||||
|
||||
#define APPLY_CORNER(C) \
|
||||
. = LUM_FALLOFF(C, pixel_turf); \
|
||||
. *= light_power; \
|
||||
. = LUM_FALLOFF(C); \
|
||||
. *= _light_power; \
|
||||
var/OLD = effect_str[C]; \
|
||||
\
|
||||
C.update_lumcount \
|
||||
( \
|
||||
(. * lum_r) - (OLD * applied_lum_r), \
|
||||
(. * lum_g) - (OLD * applied_lum_g), \
|
||||
(. * lum_b) - (OLD * applied_lum_b) \
|
||||
(. * _lum_r) - (OLD * _applied_lum_r), \
|
||||
(. * _lum_g) - (OLD * _applied_lum_g), \
|
||||
(. * _lum_b) - (OLD * _applied_lum_b) \
|
||||
); \
|
||||
|
||||
//CHOMPEdit Begin
|
||||
#define APPLY_CORNER_NEW(C) \
|
||||
. = LUM_FALLOFF(C, pixel_turf); \
|
||||
. *= light_power; \
|
||||
. = LUM_FALLOFF(C); \
|
||||
. *= _light_power; \
|
||||
var/OLD = effect_str[C]; \
|
||||
if (. != 0){ \
|
||||
LAZYADD(C.affecting, src); \
|
||||
@@ -140,21 +156,22 @@
|
||||
} \
|
||||
C.update_lumcount \
|
||||
( \
|
||||
(. * lum_r) - (OLD * applied_lum_r), \
|
||||
(. * lum_g) - (OLD * applied_lum_g), \
|
||||
(. * lum_b) - (OLD * applied_lum_b) \
|
||||
(. * _lum_r) - (OLD * _applied_lum_r), \
|
||||
(. * _lum_g) - (OLD * _applied_lum_g), \
|
||||
(. * _lum_b) - (OLD * _applied_lum_b) \
|
||||
); \
|
||||
//CHOMPEdit End
|
||||
#define REMOVE_CORNER(C) \
|
||||
. = -effect_str[C]; \
|
||||
C.update_lumcount \
|
||||
( \
|
||||
. * applied_lum_r, \
|
||||
. * applied_lum_g, \
|
||||
. * applied_lum_b \
|
||||
. * _applied_lum_r, \
|
||||
. * _applied_lum_g, \
|
||||
. * _applied_lum_b \
|
||||
);
|
||||
|
||||
/datum/light_source/proc/remove_lum()
|
||||
SETUP_CORNERS_REMOVAL_CACHE(src)
|
||||
applied = FALSE
|
||||
for (var/datum/lighting_corner/corner as anything in effect_str)
|
||||
LAZYREMOVE(corner.affecting, src) //CHOMPEdit
|
||||
@@ -163,6 +180,7 @@
|
||||
effect_str = null
|
||||
|
||||
/datum/light_source/proc/recalc_corner(datum/lighting_corner/corner)
|
||||
SETUP_CORNERS_CACHE(src)
|
||||
LAZYINITLIST(effect_str)
|
||||
if (effect_str[corner]) // Already have one.
|
||||
REMOVE_CORNER(corner)
|
||||
@@ -174,6 +192,24 @@
|
||||
/datum/light_source/proc/get_turfs_in_range()
|
||||
return view(CEILING(light_range, 1), source_turf)
|
||||
|
||||
// Keep in mind. Lighting corners accept the bottom left (northwest) set of cords to them as input
|
||||
//CHOMPEdit Start Dynamic light
|
||||
#define GENERATE_MISSING_CORNERS(gen_for) \
|
||||
if (!gen_for.lighting_corner_NE) { \
|
||||
gen_for.lighting_corner_NE = new /datum/lighting_corner(gen_for.x, gen_for.y, gen_for.z, gen_for.has_dynamic_lighting()); \
|
||||
} \
|
||||
if (!gen_for.lighting_corner_SE) { \
|
||||
gen_for.lighting_corner_SE = new /datum/lighting_corner(gen_for.x, gen_for.y - 1, gen_for.z, gen_for.has_dynamic_lighting()); \
|
||||
} \
|
||||
if (!gen_for.lighting_corner_SW) { \
|
||||
gen_for.lighting_corner_SW = new /datum/lighting_corner(gen_for.x - 1, gen_for.y - 1, gen_for.z, gen_for.has_dynamic_lighting()); \
|
||||
} \
|
||||
if (!gen_for.lighting_corner_NW) { \
|
||||
gen_for.lighting_corner_NW = new /datum/lighting_corner(gen_for.x - 1, gen_for.y, gen_for.z, gen_for.has_dynamic_lighting()); \
|
||||
} \
|
||||
gen_for.lighting_corners_initialised = TRUE;
|
||||
//CHOMPEdit End
|
||||
|
||||
/datum/light_source/proc/update_corners()
|
||||
var/update = FALSE
|
||||
var/atom/source_atom = src.source_atom
|
||||
@@ -236,24 +272,27 @@
|
||||
return //nothing's changed
|
||||
|
||||
var/list/datum/lighting_corner/corners = list()
|
||||
var/list/turf/turfs = list()
|
||||
|
||||
if (source_turf)
|
||||
var/oldlum = source_turf.luminosity
|
||||
source_turf.luminosity = CEILING(light_range, 1)
|
||||
for(var/turf/T in get_turfs_in_range())
|
||||
if(!IS_OPAQUE_TURF(T))
|
||||
if(IS_OPAQUE_TURF(T))
|
||||
continue
|
||||
if (!T.lighting_corners_initialised)
|
||||
T.generate_missing_corners()
|
||||
GENERATE_MISSING_CORNERS(T)
|
||||
|
||||
corners[T.lighting_corner_NE] = 0
|
||||
corners[T.lighting_corner_SE] = 0
|
||||
corners[T.lighting_corner_SW] = 0
|
||||
corners[T.lighting_corner_NW] = 0
|
||||
turfs += T
|
||||
source_turf.luminosity = oldlum
|
||||
|
||||
var/list/datum/lighting_corner/new_corners = (corners - effect_str)
|
||||
LAZYINITLIST(effect_str)
|
||||
SETUP_CORNERS_CACHE(src)
|
||||
|
||||
var/list/datum/lighting_corner/new_corners = (corners - src.effect_str)
|
||||
LAZYINITLIST(src.effect_str)
|
||||
var/list/effect_str = src.effect_str
|
||||
if (needs_update == LIGHTING_VIS_UPDATE)
|
||||
for (var/datum/lighting_corner/corner in new_corners) //CHOMPEdit
|
||||
//CHOMPEdit Begin
|
||||
@@ -267,8 +306,8 @@
|
||||
|
||||
for (var/datum/lighting_corner/corner in corners - new_corners) // Existing corners //CHOMPEdit
|
||||
//CHOMPEdit Begin
|
||||
. = LUM_FALLOFF(corner, pixel_turf);
|
||||
. *= light_power;
|
||||
. = LUM_FALLOFF(corner);
|
||||
. *= _light_power;
|
||||
var/OLD = effect_str[corner];
|
||||
if (. != 0)
|
||||
effect_str[corner] = .
|
||||
@@ -277,9 +316,9 @@
|
||||
effect_str -= corner
|
||||
corner.update_lumcount \
|
||||
( \
|
||||
(. * lum_r) - (OLD * applied_lum_r), \
|
||||
(. * lum_g) - (OLD * applied_lum_g), \
|
||||
(. * lum_b) - (OLD * applied_lum_b) \
|
||||
(. * _lum_r) - (OLD * _applied_lum_r), \
|
||||
(. * _lum_g) - (OLD * _applied_lum_g), \
|
||||
(. * _lum_b) - (OLD * _applied_lum_b) \
|
||||
);
|
||||
//CHOMPEdit End
|
||||
|
||||
@@ -293,9 +332,11 @@
|
||||
applied_lum_g = lum_g
|
||||
applied_lum_b = lum_b
|
||||
|
||||
UNSETEMPTY(effect_str)
|
||||
UNSETEMPTY(src.effect_str)
|
||||
|
||||
#undef EFFECT_UPDATE
|
||||
#undef LUM_FALLOFF
|
||||
#undef REMOVE_CORNER
|
||||
#undef APPLY_CORNER
|
||||
#undef SETUP_CORNERS_REMOVAL_CACHE
|
||||
#undef SETUP_CORNERS_CACHE
|
||||
|
||||
@@ -142,38 +142,3 @@
|
||||
/turf/proc/has_dynamic_lighting()
|
||||
var/area/A = loc
|
||||
return (IS_DYNAMIC_LIGHTING(src) && IS_DYNAMIC_LIGHTING(A))
|
||||
|
||||
/turf/proc/generate_missing_corners()
|
||||
|
||||
//CHOMPEdit Begin
|
||||
var/turf/n = get_step(src,NORTH)
|
||||
var/turf/s = get_step(src,SOUTH)
|
||||
var/turf/w = get_step(src,WEST)
|
||||
var/turf/e = get_step(src,EAST)
|
||||
|
||||
|
||||
if (!lighting_corner_NE)
|
||||
if(n && n.lighting_corner_SE)
|
||||
lighting_corner_NE = n.lighting_corner_SE
|
||||
else
|
||||
lighting_corner_NE = new/datum/lighting_corner(src, NORTH|EAST)
|
||||
|
||||
if (!lighting_corner_SE)
|
||||
if(e && e.lighting_corner_SW)
|
||||
lighting_corner_SE = e.lighting_corner_SW
|
||||
else
|
||||
lighting_corner_SE = new/datum/lighting_corner(src, SOUTH|EAST)
|
||||
|
||||
if (!lighting_corner_SW)
|
||||
if(s && s.lighting_corner_NW)
|
||||
lighting_corner_SW = s.lighting_corner_NW
|
||||
else
|
||||
lighting_corner_SW = new/datum/lighting_corner(src, SOUTH|WEST)
|
||||
|
||||
if (!lighting_corner_NW)
|
||||
if(w && w.lighting_corner_NE)
|
||||
lighting_corner_NW = s.lighting_corner_NE
|
||||
else
|
||||
lighting_corner_NW = new/datum/lighting_corner(src, NORTH|WEST)
|
||||
//CHOMPEdit End
|
||||
lighting_corners_initialised = TRUE
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
//Moved initialization here to make sure that it doesn't happen too early when replacing turfs.
|
||||
/datum/sunlight_handler/proc/manualInit()
|
||||
if(!holder.lighting_corners_initialised)
|
||||
holder.generate_missing_corners()
|
||||
GENERATE_MISSING_CORNERS(holder)
|
||||
var/corners = list(holder.lighting_corner_NE,holder.lighting_corner_NW,holder.lighting_corner_SE,holder.lighting_corner_SW)
|
||||
for(var/datum/lighting_corner/corner in corners)
|
||||
if(corner.sunlight == SUNLIGHT_NONE)
|
||||
@@ -62,7 +62,7 @@
|
||||
sunlight_check()
|
||||
|
||||
/datum/sunlight_handler/proc/holder_change()
|
||||
holder.generate_missing_corners() //Somehow corners are self destructing under specific circumstances. Likely race conditions. This is slightly unoptimal but may be necessary.
|
||||
GENERATE_MISSING_CORNERS(holder) //Somehow corners are self destructing under specific circumstances. Likely race conditions. This is slightly unoptimal but may be necessary.
|
||||
sunlight_check() //Also not optimal but made necessary by race conditions
|
||||
sunlight_update()
|
||||
for(var/dir in (cardinal + cornerdirs))
|
||||
@@ -161,7 +161,7 @@
|
||||
sunlight_update()
|
||||
|
||||
/datum/sunlight_handler/proc/sunlight_check()
|
||||
holder.generate_missing_corners() //Somehow corners are self destructing under specific circumstances. Likely race conditions. This is slightly unoptimal but may be necessary.
|
||||
GENERATE_MISSING_CORNERS(holder) //Somehow corners are self destructing under specific circumstances. Likely race conditions. This is slightly unoptimal but may be necessary.
|
||||
set_sleeping(FALSE) //We set sleeping to false just incase. If the conditions are correct, we'll end up going back to sleeping soon enough anyways.
|
||||
var/cur_sunlight = sunlight
|
||||
if(holder.is_outdoors())
|
||||
@@ -391,3 +391,5 @@
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
#undef GENERATE_MISSING_CORNERS
|
||||
|
||||
Reference in New Issue
Block a user