lighting: fix + optimize colored lights

turfs now directly hold color lumcounts
overlay is averaged + rounded from that instead of strings
overall colored lumcount is now rounded properly
fixes having thousands of lighting subareas after a fire
fixes #5417

Signed-off-by: Mloc-Argent <colmohici@gmail.com>
This commit is contained in:
Mloc-Argent
2014-06-30 23:23:46 +01:00
parent 38c5b38017
commit 6fe27b57b1

View File

@@ -39,7 +39,12 @@ datum/light_source
var/list/effect = list()
var/__x = 0 //x coordinate at last update
var/__y = 0 //y coordinate at last update
var/l_color
var/__z = 0 //z coordinate at last update
var/_l_color //do not use directly, only used as reference for updating
var/col_r
var/col_g
var/col_b
New(atom/A)
@@ -47,9 +52,10 @@ datum/light_source
CRASH("The first argument to the light object's constructor must be the atom that is the light source. Expected atom, received '[A]' instead.")
..()
owner = A
l_color = owner.l_color
readrgb(owner.l_color)
__x = owner.x
__y = owner.y
__z = owner.z
// the lighting object maintains a list of all light sources
lighting_controller.lights += src
@@ -61,12 +67,13 @@ datum/light_source
return 1 //causes it to be removed from our list of lights. The garbage collector will then destroy it.
// check to see if we've moved since last update
if(owner.x != __x || owner.y != __y)
if(owner.x != __x || owner.y != __y || owner.z != __z)
__x = owner.x
__y = owner.y
__z = owner.z
changed = 1
if (owner.l_color != l_color)
if (owner.l_color != _l_color)
changed = 1
if(changed)
@@ -79,19 +86,19 @@ datum/light_source
proc/remove_effect()
// before we apply the effect we remove the light's current effect.
for(var/turf/T in effect) // negate the effect of this light source
T.update_lumcount(-effect[T], l_color, 1)
T.update_lumcount(-effect[T], col_r, col_g, col_b, 1)
effect.Cut() // clear the effect list
proc/add_effect()
// only do this if the light is turned on and is on the map
if(owner.loc && owner.luminosity > 0)
l_color = owner.l_color
readrgb(owner.l_color)
effect = list()
for(var/turf/T in view(owner.get_light_range(),owner))
var/delta_lumen = lum(T)
if(delta_lumen > 0)
effect[T] = delta_lumen
T.update_lumcount(delta_lumen, l_color, 0)
T.update_lumcount(delta_lumen, col_r, col_g, col_b, 0)
return 0
else
@@ -116,6 +123,15 @@ datum/light_source
else
return sqrtTable[owner.trueLuminosity] - dist
proc/readrgb(col)
_l_color = col
if(col)
col_r = GetRedPart(col)
col_g = GetGreenPart(col)
col_b = GetBluePart(col)
else
col_r = null
atom
var/datum/light_source/light
var/trueLuminosity = 0 // Typically 'luminosity' squared. The builtin luminosity must remain linear.
@@ -214,45 +230,38 @@ turf
var/lighting_lumcount = 0
var/lighting_changed = 0
var/color_lighting_lumcount = 0
var/list/colors = list()
var/lumcount_r = 0
var/lumcount_g = 0
var/lumcount_b = 0
var/light_col_sources = 0
turf/space
lighting_lumcount = 4 //starlight
turf/proc/update_lumcount(amount, _lcolor, removing = 0)
turf/proc/update_lumcount(amount, col_r, col_g, col_b, removing = 0)
lighting_lumcount += amount
var/blended
if (_lcolor)
if (removing)
colors.Remove(_lcolor) // Remove the color that's leaving us from our list.
if(!isnull(col_r)) //col_r is the "key" var, if it's null so will the rest
if(removing)
light_col_sources--
lumcount_r -= col_r
lumcount_g -= col_g
lumcount_b -= col_b
else
light_col_sources++
lumcount_r += col_r
lumcount_g += col_g
lumcount_b += col_b
if (colors && !colors.len)
l_color = null // All our color is gone, no color for us.
else if (colors && colors.len > 1)
var/maxdepth = 3 // Will blend 3 colors, anymore than that and it looks bad or we will get lag on every tile update.
var/currentblended = colors
if (colors.len > maxdepth)
currentblended = MixColors(colors.Copy(1,maxdepth+1))
if(light_col_sources)
var/r_avg = max(0, min(255, round(lumcount_r / light_col_sources, 16) + 15))
var/g_avg = max(0, min(255, round(lumcount_g / light_col_sources, 16) + 15))
var/b_avg = max(0, min(255, round(lumcount_b / light_col_sources, 16) + 15))
l_color = rgb(r_avg, g_avg, b_avg)
else
l_color = null
if (currentblended)
//world << "Ended up with [currentblended]"
l_color = currentblended // blended the remaining colors so apply it.
else
l_color = null // Something went wrong, no color for you.
else
l_color = colors[colors.len]
else // we added a color.
colors.Add(_lcolor) // Add the base color to the list.
if (l_color && _lcolor && l_color != _lcolor) // Blend colors.
blended = MixColors(list(l_color,_lcolor))
if (blended)
l_color = blended // If we had a blended color, this is what we get otherwise.
else
l_color = _lcolor // Basecolor is our color.
// if ((l_color != LIGHT_WHITE && l_color != "#FFF") || removing)
color_lighting_lumcount = max(color_lighting_lumcount + amount, 0) // Minimum of 0.
if(!lighting_changed)
@@ -298,7 +307,8 @@ turf/proc/shift_to_subarea()
// pomf - If we have a lighting color that is not null, apply the new tag to seperate the areas.
if (l_color)
new_tag += "[l_color][color_lighting_lumcount]" // pomf - We append the color lighting lumcount so we can have colored lights.
// pomf - We append the (rounded!) color lighting lumcount so we can have colored lights.
new_tag += "[l_color][min(max(round(color_lighting_lumcount,1),0),lighting_controller.lighting_states)]"
if(Area.tag!=new_tag) //skip if already in this area
var/area/A = locate(new_tag) // find an appropriate area