diff --git a/code/modules/lighting/lighting_corner.dm b/code/modules/lighting/lighting_corner.dm index e02e04b0f7c..3f66bdde70a 100644 --- a/code/modules/lighting/lighting_corner.dm +++ b/code/modules/lighting/lighting_corner.dm @@ -29,35 +29,47 @@ ///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) . = ..() - 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. - - // 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. + // anddd the last tile + if(process_next) + master_SE = process_next + process_next.lighting_corner_NW = src /datum/lighting_corner/proc/save_master(turf/master, dir) switch (dir) diff --git a/code/modules/lighting/lighting_overlay.dm b/code/modules/lighting/lighting_overlay.dm index 155de84b1da..8e118279970 100644 --- a/code/modules/lighting/lighting_overlay.dm +++ b/code/modules/lighting/lighting_overlay.dm @@ -28,8 +28,9 @@ affected_turf.lighting_object = src affected_turf.set_luminosity(0) - for(var/turf/space/space_tile in RANGE_TURFS(1, affected_turf)) - space_tile.update_starlight() + if(config.starlight) + for(var/turf/space/space_tile in RANGE_TURFS(1, affected_turf)) + space_tile.update_starlight() needs_update = TRUE SSlighting.objects_queue += src @@ -57,6 +58,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 @@ -64,22 +66,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 @@ -88,30 +74,30 @@ var/set_luminosity = max > 1e-6 #endif - if((rr & gr & br & ar) && (rg + gg + bg + ag + rb + gb + bb + ab == 8)) + 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 - affected_turf.underlays -= current_underlay 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 = 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() diff --git a/code/modules/lighting/lighting_source.dm b/code/modules/lighting/lighting_source.dm index a04cd6c6eb0..611a875104f 100644 --- a/code/modules/lighting/lighting_source.dm +++ b/code/modules/lighting/lighting_source.dm @@ -111,34 +111,51 @@ // 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) \ ); \ #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) REMOVE_CORNER(corner) @@ -147,6 +164,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) @@ -158,6 +176,22 @@ /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 +#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); \ + } \ + 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); \ + } \ + 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); \ + } \ + 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.lighting_corners_initialised = TRUE; + /datum/light_source/proc/update_corners() var/update = FALSE var/atom/source_atom = src.source_atom @@ -220,24 +254,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 (!T.lighting_corners_initialised) - T.generate_missing_corners() - 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 + if(IS_OPAQUE_TURF(T)) + continue + if (!T.lighting_corners_initialised) + 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 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 as anything in new_corners) APPLY_CORNER(corner) @@ -251,13 +288,15 @@ LAZYADD(corner.affecting, src) effect_str[corner] = . - for (var/datum/lighting_corner/corner as anything in corners - new_corners) // Existing corners - APPLY_CORNER(corner) - if (. != 0) - effect_str[corner] = . - else - LAZYREMOVE(corner.affecting, src) - effect_str -= corner + // New corners are a subset of corners. so if they're both the same length, there are NO old corners! + if(length(corners) != length(new_corners)) + for (var/datum/lighting_corner/corner as anything in corners - new_corners) // Existing corners + APPLY_CORNER(corner) + if (. != 0) + effect_str[corner] = . + else + LAZYREMOVE(corner.affecting, src) + effect_str -= corner var/list/datum/lighting_corner/gone_corners = effect_str - corners for (var/datum/lighting_corner/corner as anything in gone_corners) @@ -269,9 +308,12 @@ 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 +#undef GENERATE_MISSING_CORNERS diff --git a/code/modules/lighting/lighting_turf.dm b/code/modules/lighting/lighting_turf.dm index 4ba09f11f23..dc5437c4cac 100644 --- a/code/modules/lighting/lighting_turf.dm +++ b/code/modules/lighting/lighting_turf.dm @@ -138,19 +138,3 @@ /turf/proc/has_dynamic_lighting() var/area/A = loc return (IS_DYNAMIC_LIGHTING(src) && IS_DYNAMIC_LIGHTING(A)) - -/turf/proc/generate_missing_corners() - - if (!lighting_corner_NE) - lighting_corner_NE = new/datum/lighting_corner(src, NORTH|EAST) - - if (!lighting_corner_SE) - lighting_corner_SE = new/datum/lighting_corner(src, SOUTH|EAST) - - if (!lighting_corner_SW) - lighting_corner_SW = new/datum/lighting_corner(src, SOUTH|WEST) - - if (!lighting_corner_NW) - lighting_corner_NW = new/datum/lighting_corner(src, NORTH|WEST) - - lighting_corners_initialised = TRUE