mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 10:43:20 +00:00
Merge pull request #9889 from PJB3005/bay-lights
Lighting optimizations + NVG meson fix
This commit is contained in:
@@ -1,15 +1,6 @@
|
||||
// Macro functions.
|
||||
#define RAND_F(LOW, HIGH) (rand()*(HIGH-LOW) + LOW)
|
||||
|
||||
// List of square roots for the numbers 1-100.
|
||||
var/list/sqrtTable = list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10)
|
||||
|
||||
/proc/Clamp(val, min, max)
|
||||
return max(min, min(val, max))
|
||||
|
||||
// min is inclusive, max is exclusive
|
||||
/proc/Wrap(val, min, max)
|
||||
var/d = max - min
|
||||
|
||||
@@ -1315,3 +1315,25 @@ var/list/WALLITEMS = list(
|
||||
temp_col = "0[temp_col]"
|
||||
colour += temp_col
|
||||
return colour
|
||||
|
||||
//Version of view() which ignores darkness, because BYOND doesn't have it.
|
||||
/proc/dview(var/range = world.view, var/center, var/invis_flags = 0)
|
||||
if(!center)
|
||||
return
|
||||
|
||||
var/global/mob/dview/DV
|
||||
if(!DV)
|
||||
DV = new
|
||||
|
||||
DV.loc = center
|
||||
|
||||
DV.see_in_dark = range
|
||||
DV.see_invisible = invis_flags
|
||||
|
||||
. = view(range, DV)
|
||||
DV.loc = null
|
||||
|
||||
/mob/dview
|
||||
invisibility = 101
|
||||
density = 0
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon = 'icons/turf/areas.dmi'
|
||||
icon_state = "unknown"
|
||||
layer = 10
|
||||
luminosity = 1
|
||||
luminosity = 0
|
||||
mouse_opacity = 0
|
||||
var/lightswitch = 1
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
var/holy = 0
|
||||
|
||||
var/dynamic_lighting = 1
|
||||
luminosity = 1
|
||||
|
||||
/turf/New()
|
||||
..()
|
||||
@@ -41,7 +42,6 @@
|
||||
src.Entered(AM)
|
||||
return
|
||||
turfs |= src
|
||||
return
|
||||
|
||||
/turf/Destroy()
|
||||
turfs -= src
|
||||
@@ -229,6 +229,7 @@
|
||||
var/old_opacity = opacity
|
||||
var/old_dynamic_lighting = dynamic_lighting
|
||||
var/list/old_affecting_lights = affecting_lights
|
||||
var/old_lighting_overlay = lighting_overlay
|
||||
|
||||
//world << "Replacing [src.type] with [N]"
|
||||
|
||||
@@ -280,6 +281,7 @@
|
||||
W.levelupdate()
|
||||
. = W
|
||||
|
||||
lighting_overlay = old_lighting_overlay
|
||||
affecting_lights = old_affecting_lights
|
||||
if((old_opacity != opacity) || (dynamic_lighting != old_dynamic_lighting) || force_lighting_update)
|
||||
reconsider_lights()
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#define LIGHTING_LAMBERTIAN 1 // use lambertian shading for light sources
|
||||
#define LIGHTING_HEIGHT 1 // height off the ground of light sources on the pseudo-z-axis, you should probably leave this alone
|
||||
#define LIGHTING_TRANSITIONS 1 // smooth, animated transitions, similar to /tg/station
|
||||
#define LIGHTING_ROUND_VALUE (1 / 128) //Value used to round lumcounts, values smaller than 1/255 don't matter (if they do, thanks sinking points), greater values will make lighting less precise, but in turn increase performance, VERY SLIGHTLY.
|
||||
|
||||
#define LIGHTING_RESOLUTION 1 // resolution of the lighting overlays, powers of 2 only, max of 32
|
||||
#define LIGHTING_LAYER 10 // drawing layer for lighting overlays
|
||||
#define LIGHTING_ICON 'icons/effects/lighting_overlay.dmi' // icon used for lighting shading effects
|
||||
|
||||
@@ -60,13 +60,16 @@
|
||||
if(top_atom != source_atom)
|
||||
if(!top_atom.light_sources) top_atom.light_sources = list()
|
||||
top_atom.light_sources += src
|
||||
|
||||
if(!needs_update)
|
||||
lighting_update_lights += src
|
||||
needs_update = 1
|
||||
|
||||
/datum/light_source/proc/force_update()
|
||||
needs_update = 1
|
||||
force_update = 1
|
||||
if(!needs_update)
|
||||
lighting_update_lights += src
|
||||
needs_update = 1
|
||||
|
||||
/datum/light_source/proc/check()
|
||||
if(!source_atom || !light_range || !light_power)
|
||||
@@ -113,11 +116,7 @@
|
||||
|
||||
/datum/light_source/proc/falloff(atom/movable/lighting_overlay/O)
|
||||
#if LIGHTING_FALLOFF == 1 // circular
|
||||
#if LIGHTING_RESOLUTION == 1
|
||||
. = (O.x - source_turf.x)**2 + (O.y - source_turf.y)**2 + LIGHTING_HEIGHT
|
||||
#else
|
||||
. = (O.x - source_turf.x + O.xoffset)**2 + (O.y - source_turf.y + O.yoffset)**2 + LIGHTING_HEIGHT
|
||||
#endif
|
||||
|
||||
#if LIGHTING_LAMBERTIAN == 1
|
||||
. = CLAMP01((1 - CLAMP01(sqrt(.) / light_range)) * (1 / (sqrt(. + 1))))
|
||||
@@ -126,11 +125,7 @@
|
||||
#endif
|
||||
|
||||
#elif LIGHTING_FALLOFF == 2 // square
|
||||
#if LIGHTING_RESOLUTION == 1
|
||||
. = abs(O.x - source_turf.x) + abs(O.y - source_turf.y) + LIGHTING_HEIGHT
|
||||
#else
|
||||
. = abs(O.x - source_turf.x + O.xoffset) + abs(O.y - source_turf.y + O.yoffset) + LIGHTING_HEIGHT
|
||||
#endif
|
||||
|
||||
#if LIGHTING_LAMBERTIAN == 1
|
||||
. = CLAMP01((1 - CLAMP01(. / light_range)) * (1 / (sqrt(.)**2 + )))
|
||||
@@ -142,26 +137,36 @@
|
||||
/datum/light_source/proc/apply_lum()
|
||||
applied = 1
|
||||
if(istype(source_turf))
|
||||
for(var/atom/movable/lighting_overlay/O in view(light_range, source_turf))
|
||||
var/strength = light_power * falloff(O)
|
||||
for(var/turf/T in dview(light_range, source_turf, INVISIBILITY_LIGHTING))
|
||||
if(T.lighting_overlay)
|
||||
var/strength = light_power * falloff(T.lighting_overlay)
|
||||
if(!strength) //Don't add turfs that aren't affected to the affected turfs.
|
||||
continue
|
||||
|
||||
effect_r[O] = lum_r * strength
|
||||
effect_g[O] = lum_g * strength
|
||||
effect_b[O] = lum_b * strength
|
||||
effect_r[T.lighting_overlay] = round(lum_r * strength, LIGHTING_ROUND_VALUE)
|
||||
effect_g[T.lighting_overlay] = round(lum_g * strength, LIGHTING_ROUND_VALUE)
|
||||
effect_b[T.lighting_overlay] = round(lum_b * strength, LIGHTING_ROUND_VALUE)
|
||||
|
||||
T.lighting_overlay.update_lumcount(
|
||||
round(lum_r * strength, LIGHTING_ROUND_VALUE),
|
||||
round(lum_g * strength, LIGHTING_ROUND_VALUE),
|
||||
round(lum_b * strength, LIGHTING_ROUND_VALUE)
|
||||
)
|
||||
|
||||
if(!T.affecting_lights)
|
||||
T.affecting_lights = list()
|
||||
|
||||
O.update_lumcount(lum_r * strength, lum_g * strength, lum_b * strength)
|
||||
for(var/turf/T in view(light_range, source_turf))
|
||||
if(!T.affecting_lights) T.affecting_lights = list()
|
||||
T.affecting_lights += src
|
||||
effect_turf += T
|
||||
|
||||
/datum/light_source/proc/remove_lum()
|
||||
applied = 0
|
||||
for(var/atom/movable/lighting_overlay/O in effect_r)
|
||||
O.update_lumcount(-effect_r[O], -effect_g[O], -effect_b[O])
|
||||
|
||||
for(var/turf/T in effect_turf)
|
||||
if(T.affecting_lights) T.affecting_lights -= src
|
||||
if(T.affecting_lights)
|
||||
T.affecting_lights -= src
|
||||
|
||||
if(T.lighting_overlay)
|
||||
T.lighting_overlay.update_lumcount(-effect_r[T.lighting_overlay], -effect_g[T.lighting_overlay], -effect_b[T.lighting_overlay])
|
||||
|
||||
effect_r.Cut()
|
||||
effect_g.Cut()
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
anchored = 1
|
||||
|
||||
icon = LIGHTING_ICON
|
||||
icon_state = "light1"
|
||||
layer = LIGHTING_LAYER
|
||||
invisibility = INVISIBILITY_LIGHTING
|
||||
blend_mode = BLEND_MULTIPLY
|
||||
@@ -14,22 +15,40 @@
|
||||
var/lum_g
|
||||
var/lum_b
|
||||
|
||||
#if LIGHTING_RESOLUTION != 1
|
||||
var/xoffset
|
||||
var/yoffset
|
||||
#endif
|
||||
|
||||
var/needs_update
|
||||
|
||||
/atom/movable/lighting_overlay/New()
|
||||
. = ..()
|
||||
verbs.Cut()
|
||||
|
||||
var/turf/T = loc //If this runtimes atleast we'll know what's creating overlays in things that aren't turfs.
|
||||
T.luminosity = 0
|
||||
|
||||
/atom/movable/lighting_overlay/proc/update_lumcount(delta_r, delta_g, delta_b)
|
||||
if(!delta_r && !delta_g && !delta_b) //Nothing is being changed all together.
|
||||
return
|
||||
|
||||
var/should_update = 0
|
||||
|
||||
if(!needs_update) //If this isn't true, we're already updating anyways.
|
||||
if(max(lum_r, lum_g, lum_b) < 1) //Any change that could happen WILL change appearance.
|
||||
should_update = 1
|
||||
|
||||
else if(max(lum_r + delta_r, lum_g + delta_g, lum_b + delta_b) < 1) //The change would bring us under 1 max lum, again, guaranteed to change appearance.
|
||||
should_update = 1
|
||||
|
||||
else //We need to make sure that the colour ratios won't change in this code block.
|
||||
var/mx1 = max(lum_r, lum_g, lum_b)
|
||||
var/mx2 = max(lum_r + delta_r, lum_g + delta_g, lum_b + delta_b)
|
||||
|
||||
if(lum_r / mx1 != (lum_r + delta_r) / mx2 || lum_g / mx1 != (lum_g + delta_g) / mx2 || lum_b / mx1 != (lum_b + delta_b) / mx2) //Stuff would change.
|
||||
should_update = 1
|
||||
|
||||
lum_r += delta_r
|
||||
lum_g += delta_g
|
||||
lum_b += delta_b
|
||||
|
||||
if(!needs_update && should_update)
|
||||
needs_update = 1
|
||||
lighting_update_overlays += src
|
||||
|
||||
@@ -46,3 +65,43 @@
|
||||
#else
|
||||
color = rgb(lum_r * 255 * ., lum_g * 255 * ., lum_b * 255 * .)
|
||||
#endif
|
||||
|
||||
var/turf/T = loc
|
||||
|
||||
if(istype(T)) //Incase we're not on a turf, pool ourselves, something happened.
|
||||
if(color != "#000000")
|
||||
T.luminosity = 1
|
||||
else //No light, set the turf's luminosity to 0 to remove it from view()
|
||||
#if LIGHTING_TRANSITIONS == 1
|
||||
spawn(LIGHTING_INTERVAL - 1)
|
||||
T.luminosity = 0
|
||||
#else
|
||||
T.luminosity = 0
|
||||
#endif
|
||||
|
||||
else
|
||||
warning("A lighting overlay realised its loc was NOT a turf (actual loc: [loc][loc ? ", " + loc.type : ""]) in update_overlay() and got pooled!")
|
||||
qdel(src)
|
||||
|
||||
/atom/movable/lighting_overlay/ResetVars()
|
||||
loc = null
|
||||
|
||||
lum_r = 0
|
||||
lum_g = 0
|
||||
lum_b = 0
|
||||
|
||||
color = "#000000"
|
||||
|
||||
needs_update = 0
|
||||
|
||||
/atom/movable/lighting_overlay/Destroy()
|
||||
lighting_update_overlays -= src
|
||||
|
||||
var/turf/T = loc
|
||||
if(istype(T))
|
||||
T.lighting_overlay = null
|
||||
|
||||
for(var/datum/light_source/D in T.affecting_lights) //Remove references to us on the light sources affecting us.
|
||||
D.effect_r -= src
|
||||
D.effect_g -= src
|
||||
D.effect_b -= src
|
||||
|
||||
@@ -5,7 +5,11 @@
|
||||
create_lighting_overlays()
|
||||
|
||||
/datum/controller/process/lighting/doWork()
|
||||
for(var/datum/light_source/L in lighting_update_lights)
|
||||
var/list/lighting_update_lights_old = lighting_update_lights //We use a different list so any additions to the update lists during a delay from scheck() don't cause things to be cut from the list without being updated.
|
||||
lighting_update_lights = null //Nulling it first because of http://www.byond.com/forum/?post=1854520
|
||||
lighting_update_lights = list()
|
||||
|
||||
for(var/datum/light_source/L in lighting_update_lights_old)
|
||||
if(L.needs_update)
|
||||
if(L.destroyed || L.check() || L.force_update)
|
||||
L.remove_lum()
|
||||
@@ -15,13 +19,13 @@
|
||||
|
||||
scheck()
|
||||
|
||||
lighting_update_lights.Cut()
|
||||
var/list/lighting_update_overlays_old = lighting_update_overlays //Same as above.
|
||||
lighting_update_overlays = null //Same as above
|
||||
lighting_update_overlays = list()
|
||||
|
||||
for(var/atom/movable/lighting_overlay/O in lighting_update_overlays)
|
||||
for(var/atom/movable/lighting_overlay/O in lighting_update_overlays_old)
|
||||
if(O.needs_update)
|
||||
O.update_overlay()
|
||||
O.needs_update = 0
|
||||
|
||||
scheck()
|
||||
|
||||
lighting_update_overlays.Cut()
|
||||
|
||||
@@ -5,26 +5,15 @@
|
||||
|
||||
// duplicates lots of code, but this proc needs to be as fast as possible.
|
||||
/proc/create_lighting_overlays(zlevel = 0)
|
||||
var/state = "light[LIGHTING_RESOLUTION]"
|
||||
var/area/A
|
||||
if(zlevel == 0) // populate all zlevels
|
||||
for(var/turf/T in world)
|
||||
if(T.dynamic_lighting)
|
||||
A = T.loc
|
||||
if(A.lighting_use_dynamic)
|
||||
#if LIGHTING_RESOLUTION == 1
|
||||
var/atom/movable/lighting_overlay/O = new(T)
|
||||
O.icon_state = state
|
||||
#else
|
||||
for(var/i = 0; i < LIGHTING_RESOLUTION; i++)
|
||||
for(var/j = 0; j < LIGHTING_RESOLUTION; j++)
|
||||
var/atom/movable/lighting_overlay/O = new(T)
|
||||
O.pixel_x = i * (32 / LIGHTING_RESOLUTION)
|
||||
O.pixel_y = j * (32 / LIGHTING_RESOLUTION)
|
||||
O.xoffset = (((2*i + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5)
|
||||
O.yoffset = (((2*j + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5)
|
||||
O.icon_state = state
|
||||
#endif
|
||||
var/atom/movable/lighting_overlay/O = PoolOrNew(/atom/movable/lighting_overlay, T)
|
||||
T.lighting_overlay = O
|
||||
|
||||
else
|
||||
for(var/x = 1; x <= world.maxx; x++)
|
||||
for(var/y = 1; y <= world.maxy; y++)
|
||||
@@ -32,16 +21,5 @@
|
||||
if(T.dynamic_lighting)
|
||||
A = T.loc
|
||||
if(A.lighting_use_dynamic)
|
||||
#if LIGHTING_RESOLUTION == 1
|
||||
var/atom/movable/lighting_overlay/O = new(T)
|
||||
O.icon_state = state
|
||||
#else
|
||||
for(var/i = 0; i < LIGHTING_RESOLUTION; i++)
|
||||
for(var/j = 0; j < LIGHTING_RESOLUTION; j++)
|
||||
var/atom/movable/lighting_overlay/O = new(T)
|
||||
O.pixel_x = i * (32 / LIGHTING_RESOLUTION)
|
||||
O.pixel_y = j * (32 / LIGHTING_RESOLUTION)
|
||||
O.xoffset = (((2*i + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5)
|
||||
O.yoffset = (((2*j + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5)
|
||||
O.icon_state = state
|
||||
#endif
|
||||
var/atom/movable/lighting_overlay/O = PoolOrNew(/atom/movable/lighting_overlay, T)
|
||||
T.lighting_overlay = O
|
||||
|
||||
@@ -1,29 +1,18 @@
|
||||
/turf
|
||||
var/list/affecting_lights
|
||||
var/atom/movable/lighting_overlay/lighting_overlay
|
||||
|
||||
/turf/proc/reconsider_lights()
|
||||
for(var/datum/light_source/L in affecting_lights)
|
||||
L.force_update()
|
||||
|
||||
/turf/proc/lighting_clear_overlays()
|
||||
for(var/atom/movable/lighting_overlay/L in src)
|
||||
L.loc = null
|
||||
if(lighting_overlay)
|
||||
qdel(lighting_overlay)
|
||||
|
||||
/turf/proc/lighting_build_overlays()
|
||||
if(!locate(/atom/movable/lighting_overlay) in src)
|
||||
var/state = "light[LIGHTING_RESOLUTION]"
|
||||
if(!lighting_overlay)
|
||||
var/area/A = loc
|
||||
if(A.lighting_use_dynamic)
|
||||
#if LIGHTING_RESOLUTION == 1
|
||||
var/atom/movable/lighting_overlay/O = new(src)
|
||||
O.icon_state = state
|
||||
#else
|
||||
for(var/i = 0; i < LIGHTING_RESOLUTION; i++)
|
||||
for(var/j = 0; j < LIGHTING_RESOLUTION; j++)
|
||||
var/atom/movable/lighting_overlay/O = new(src)
|
||||
O.pixel_x = i * (32 / LIGHTING_RESOLUTION)
|
||||
O.pixel_y = j * (32 / LIGHTING_RESOLUTION)
|
||||
O.xoffset = (((2*i + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5)
|
||||
O.yoffset = (((2*j + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5)
|
||||
O.icon_state = state
|
||||
#endif
|
||||
var/atom/movable/lighting_overlay/O = PoolOrNew(/atom/movable/lighting_overlay, src)
|
||||
lighting_overlay = O
|
||||
|
||||
@@ -215,7 +215,7 @@
|
||||
return
|
||||
|
||||
/mob/living/proc/adjust_fire_stacks(add_fire_stacks) //Adjusting the amount of fire_stacks we have on person
|
||||
fire_stacks = Clamp(fire_stacks + add_fire_stacks, min = FIRE_MIN_STACKS, max = FIRE_MAX_STACKS)
|
||||
fire_stacks = Clamp(fire_stacks + add_fire_stacks, FIRE_MIN_STACKS, FIRE_MAX_STACKS)
|
||||
|
||||
/mob/living/proc/handle_fire()
|
||||
if(fire_stacks < 0)
|
||||
|
||||
@@ -957,7 +957,9 @@ var/list/be_special_flags = list(
|
||||
#define WALL_CAN_OPEN 1
|
||||
#define WALL_OPENING 2
|
||||
|
||||
#define CLAMP01(x) max(0, min(1, x))
|
||||
#define Clamp(x, y, z) (x <= y ? y : (x >= z ? z : x))
|
||||
|
||||
#define CLAMP01(x) (Clamp(x, 0, 1))
|
||||
|
||||
#define DEFAULT_WALL_MATERIAL "steel"
|
||||
#define DEFAULT_TABLE_MATERIAL "plastic"
|
||||
|
||||
Reference in New Issue
Block a user