Add support for change sun light color in night and day.

This commit is contained in:
SFENCE 2023-12-11 05:16:38 +01:00
parent a7908da968
commit 60d1927b04
14 changed files with 259 additions and 100 deletions

View File

@ -39,6 +39,7 @@ core.features = {
dynamic_add_media_filepath = true,
lsystem_decoration_type = true,
item_meta_range = true,
light_intensity = true,
}
function core.has_feature(arg)

View File

@ -5431,6 +5431,8 @@ Utilities
lsystem_decoration_type = true,
-- Overrideable pointing range using the itemstack meta key `"range"` (5.9.0)
item_meta_range = true,
-- set_lighting support light_intensity table (5.9.0)
light_intensity = true,
}
```
@ -8336,6 +8338,18 @@ child will follow movement and rotation of that bone.
* `volumetric_light`: is a table that controls volumetric light (a.k.a. "godrays")
* `strength`: sets the strength of the volumetric light effect from 0 (off, default) to 1 (strongest)
* This value has no effect on clients who have the "Volumetric Lighting" or "Bloom" shaders disabled.
* `light_intensity` is a table that controls calculation of sun light color.
`sun_color = color_offset + color_ratio_coef*daynight_ratio` where `daynight_ratio` is not linear to day time.
Result color lesser or equal to 0.0 means no color in light.
Result color greater or equal to 1.0 means full color in light.
* `color_offset` is a table that controls red, green and blue color offsets.
* `r` (default: `-0.04`)
* `g` (default: `-0.04`)
* `b` (default: `0.078`)
* `color_ratio_coef` is a table that controls red, green and blue color ration coefficients.
* `r` (default: `0.001`)
* `g` (default: `0.001`)
* `b` (default: `0.00098`)
* `get_lighting()`: returns the current state of lighting for the player.
* Result is a table with the same fields as `light_definition` in `set_lighting`.

View File

@ -1,30 +1,15 @@
local lighting_sections = {
{n = "shadows", d = "Shadows",
entries = {
{ n = "intensity", d = "Shadow Intensity", min = 0, max = 1 }
}
},
{
n = "exposure", d = "Exposure",
entries = {
{n = "luminance_min", d = "Minimum Luminance", min = -10, max = 10},
{n = "luminance_max", d = "Maximum Luminance", min = -10, max = 10},
{n = "exposure_correction", d = "Exposure Correction", min = -10, max = 10},
{n = "speed_dark_bright", d = "Bright light adaptation speed", min = -10, max = 10, type="log2"},
{n = "speed_bright_dark", d = "Dark scene adaptation speed", min = -10, max = 10, type="log2"},
{n = "center_weight_power", d = "Power factor for center-weighting", min = 0.1, max = 10},
}
}
}
local function dump_lighting(lighting)
local modpath = minetest.get_modpath(minetest.get_current_modname())
local function dumpByRecipe(data, recipe)
local result = "{\n"
local section_count = 0
for _,section in ipairs(lighting_sections) do
for _,section in ipairs(recipe) do
section_count = section_count + 1
local parameters = section.entries or {}
local state = lighting[section.n] or {}
local state = data[section.n] or {}
result = result.." "..section.n.." = {\n"
@ -40,7 +25,7 @@ local function dump_lighting(lighting)
result = result.." }"
if section_count < #lighting_sections then
if section_count < #recipe then
result = result..","
end
result = result.."\n"
@ -49,74 +34,59 @@ local function dump_lighting(lighting)
return result
end
minetest.register_chatcommand("set_lighting", {
params = "",
description = "Tune lighting parameters",
func = function(player_name, param)
local player = minetest.get_player_by_name(player_name);
if not player then return end
local function buildGUI(player, data, recipe, gui_name)
local form = {
"formspec_version[2]",
"size[15,30]",
"position[0.99,0.15]",
"anchor[1,0]",
"padding[0.05,0.1]",
"no_prepend[]"
};
local lighting = player:get_lighting()
local exposure = lighting.exposure or {}
local line = 1
for _,section in ipairs(recipe) do
local parameters = section.entries or {}
local state = data[section.n] or {}
local form = {
"formspec_version[2]",
"size[15,30]",
"position[0.99,0.15]",
"anchor[1,0]",
"padding[0.05,0.1]",
"no_prepend[]"
};
table.insert(form, "label[1,"..line..";"..section.d.."]")
line = line + 1
local line = 1
for _,section in ipairs(lighting_sections) do
local parameters = section.entries or {}
local state = lighting[section.n] or {}
table.insert(form, "label[1,"..line..";"..section.d.."]")
line = line + 1
for _,v in ipairs(parameters) do
table.insert(form, "label[2,"..line..";"..v.d.."]")
table.insert(form, "scrollbaroptions[min=0;max=1000;smallstep=10;largestep=100;thumbsize=10]")
local value = state[v.n]
if v.type == "log2" then
value = math.log(value or 1) / math.log(2)
end
local sb_scale = math.floor(1000 * (math.max(v.min, value or 0) - v.min) / (v.max - v.min))
table.insert(form, "scrollbar[2,"..(line+0.7)..";12,1;horizontal;"..section.n.."."..v.n..";"..sb_scale.."]")
line = line + 2.7
for _,v in ipairs(parameters) do
table.insert(form, "label[2,"..line..";"..v.d.."]")
table.insert(form, "scrollbaroptions[min=0;max=1000;smallstep=10;largestep=100;thumbsize=10]")
local value = state[v.n]
if v.type == "log2" then
value = math.log(value or 1) / math.log(2)
end
line = line + 1
local sb_scale = math.floor(1000 * (math.max(v.min, value or 0) - v.min) / (v.max - v.min))
table.insert(form, "scrollbar[2,"..(line+0.7)..";12,1;horizontal;"..section.n.."."..v.n..";"..sb_scale.."]")
line = line + 2.7
end
minetest.show_formspec(player_name, "lighting", table.concat(form))
local debug_value = dump_lighting(lighting)
local debug_ui = player:hud_add({type="text", position={x=0.1, y=0.3}, scale={x=1,y=1}, alignment = {x=1, y=1}, text=debug_value, number=0xFFFFFF})
player:get_meta():set_int("lighting_hud", debug_ui)
line = line + 1
end
})
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "lighting" then return end
minetest.show_formspec(player:get_player_name(), gui_name, table.concat(form))
local debug_value = dumpByRecipe(data, recipe)
local debug_ui = player:hud_add({type="text", position={x=0.1, y=0.3}, scale={x=1,y=1}, alignment = {x=1, y=1}, text=debug_value, number=0xFFFFFF})
player:get_meta():set_int(gui_name.."_hud", debug_ui)
end
if not player then return end
local hud_id = player:get_meta():get_int("lighting_hud")
local function receiveFields(player, fields, data, recipe, gui_name)
local hud_id = player:get_meta():get_int(gui_name.."_hud")
if fields.quit then
player:hud_remove(hud_id)
player:get_meta():set_int("lighting_hud", -1)
player:get_meta():set_int(gui_name.."_hud", -1)
return
end
local lighting = player:get_lighting()
for _,section in ipairs(lighting_sections) do
for _,section in ipairs(recipe) do
local parameters = section.entries or {}
local state = (lighting[section.n] or {})
lighting[section.n] = state
local state = (data[section.n] or {})
data[section.n] = state
for _,v in ipairs(parameters) do
@ -133,8 +103,96 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end
end
local debug_value = dump_lighting(lighting)
local debug_value = dumpByRecipe(data, recipe)
player:hud_change(hud_id, "text", debug_value)
end
local lighting_recipe = {
{n = "shadows", d = "Shadows",
entries = {
{ n = "intensity", d = "Shadow Intensity", min = 0, max = 1 }
}
},
{
n = "exposure", d = "Exposure",
entries = {
{n = "luminance_min", d = "Minimum Luminance", min = -10, max = 10},
{n = "luminance_max", d = "Maximum Luminance", min = -10, max = 10},
{n = "exposure_correction", d = "Exposure Correction", min = -10, max = 10},
{n = "speed_dark_bright", d = "Bright light adaptation speed", min = -10, max = 10, type="log2"},
{n = "speed_bright_dark", d = "Dark scene adaptation speed", min = -10, max = 10, type="log2"},
{n = "center_weight_power", d = "Power factor for center-weighting", min = 0.1, max = 10},
}
},
}
minetest.register_chatcommand("set_lighting", {
params = "",
description = "Tune lighting parameters",
func = function(player_name, param)
local player = minetest.get_player_by_name(player_name)
if not player then return end
local lighting = player:get_lighting()
buildGUI(player, lighting, lighting_recipe, "lighting")
end
})
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "lighting" then return end
if not player then return end
local lighting = player:get_lighting()
receiveFields(player, fields, lighting, lighting_recipe, "lighting")
player:set_lighting(lighting)
end)
end)
local light_intensity_recipe = {
{n = "color_offset", d = "Color offset",
entries = {
{n = "r", d = "Red color offset", min = -1, max = 2},
{n = "g", d = "Green color offset", min = -1, max = 2},
{n = "b", d = "Blue color offset", min = -1, max = 2},
}
},
{n = "color_ratio_coef", d = "Color day-night ratio coefficient",
entries = {
{n = "r", d = "Red color day-night ratio coefficient", min = -1e-3, max = 2e-3},
{n = "g", d = "Green color day-night ratio coefficient", min = -1e-3, max = 2e-3},
{n = "b", d = "Blue color day-night ratio coefficient", min = -1e-3, max = 2e-3},
}
}
}
minetest.register_chatcommand("set_light_intensity", {
params = "",
description = "Tune lighting light_intensity parameters",
func = function(player_name, param)
local player = minetest.get_player_by_name(player_name)
if not player then return end
local lighting = player:get_lighting()
local light_intensity = lighting.light_intensity
buildGUI(player, light_intensity, light_intensity_recipe, "light_intensity")
end
})
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "light_intensity" then return end
if not player then return end
local lighting = player:get_lighting()
local light_intensity = lighting.light_intensity
receiveFields(player, fields, light_intensity, light_intensity_recipe, "light_intensity")
player:set_lighting(lighting)
end)

View File

@ -262,7 +262,8 @@ void ClientEnvironment::step(float dtime)
u16 light = getInteriorLight(node_at_lplayer, 0, m_client->ndef());
lplayer->light_color = encode_light(light, 0); // this transfers light.alpha
final_color_blend(&lplayer->light_color, light, day_night_ratio);
const LightIntensity &lightIntensity = m_client->getEnv().getLocalPlayer()->getLighting().lightIntensity;
final_color_blend(&lplayer->light_color, light, day_night_ratio, lightIntensity);
}
/*

View File

@ -719,6 +719,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
const float animation_time = m_client->getAnimationTime();
const int crack = m_client->getCrackLevel();
const u32 daynight_ratio = m_client->getEnv().getDayNightRatio();
const Lighting &lighting = m_client->getEnv().getLocalPlayer()->getLighting();
const v3f camera_position = m_camera_position;
@ -780,7 +781,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
mesh_animate_count < (m_control.range_all ? 200 : 50)) {
bool animated = block_mesh->animate(faraway, animation_time,
crack, daynight_ratio);
crack, daynight_ratio, lighting.lightIntensity);
if (animated)
mesh_animate_count++;
} else {

View File

@ -908,8 +908,10 @@ void GenericCAO::updateLight(u32 day_night_ratio)
// based on the entity glow.
if (m_enable_shaders)
light = encode_light(light_at_pos, m_prop.glow);
else
final_color_blend(&light, light_at_pos, day_night_ratio);
else {
const LightIntensity &lightIntensity = m_env->getLocalPlayer()->getLighting().lightIntensity;
final_color_blend(&light, light_at_pos, day_night_ratio, lightIntensity);
}
if (light != m_last_light) {
m_last_light = light;

View File

@ -470,8 +470,9 @@ public:
void onSetConstants(video::IMaterialRendererServices *services) override
{
u32 daynight_ratio = (float)m_client->getEnv().getDayNightRatio();
const auto &lighting = m_client->getEnv().getLocalPlayer()->getLighting();
video::SColorf sunlight;
get_sunlight_color(&sunlight, daynight_ratio);
get_sunlight_color(&sunlight, daynight_ratio, lighting.lightIntensity);
m_day_light.set(sunlight, services);
u32 animation_timer = m_client->getEnv().getFrameTime() % 1000000;
@ -509,7 +510,7 @@ public:
m_texel_size0_vertex.set(m_texel_size0, services);
m_texel_size0_pixel.set(m_texel_size0, services);
const AutoExposure &exposure_params = m_client->getEnv().getLocalPlayer()->getLighting().exposure;
const AutoExposure &exposure_params = lighting.exposure;
std::array<float, 7> exposure_buffer = {
std::pow(2.0f, exposure_params.luminance_min),
std::pow(2.0f, exposure_params.luminance_max),
@ -527,7 +528,6 @@ public:
m_bloom_strength_pixel.set(&m_bloom_strength, services);
}
const auto &lighting = m_client->getEnv().getLocalPlayer()->getLighting();
float saturation = lighting.saturation;
m_saturation_pixel.set(&saturation, services);
@ -3458,8 +3458,9 @@ PointedThing Game::updatePointedThing(
}
u32 daynight_ratio = client->getEnv().getDayNightRatio();
const Lighting &lighting = client->getEnv().getLocalPlayer()->getLighting();
video::SColor c;
final_color_blend(&c, light_level, daynight_ratio);
final_color_blend(&c, light_level, daynight_ratio, lighting.lightIntensity);
// Modify final color a bit with time
u32 timer = client->getEnv().getFrameTime() % 5000;

View File

@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/directiontables.h"
#include "client/meshgen/collector.h"
#include "client/renderingengine.h"
#include "client/localplayer.h"
#include <array>
#include <algorithm>
#include <cmath>
@ -281,19 +282,17 @@ u16 getSmoothLightTransparent(const v3s16 &p, const v3s16 &corner, MeshMakeData
return getSmoothLightCombined(p, dirs, data);
}
void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio){
f32 rg = daynight_ratio / 1000.0f - 0.04f;
f32 b = (0.98f * daynight_ratio) / 1000.0f + 0.078f;
sunlight->r = rg;
sunlight->g = rg;
sunlight->b = b;
void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio, const LightIntensity &lightIntensity){
sunlight->r = lightIntensity.colorOffset_rgb.X+lightIntensity.colorRatioCoef_rgb.X*daynight_ratio;
sunlight->g = lightIntensity.colorOffset_rgb.Y+lightIntensity.colorRatioCoef_rgb.Y*daynight_ratio;
sunlight->b = lightIntensity.colorOffset_rgb.Z+lightIntensity.colorRatioCoef_rgb.Z*daynight_ratio;
}
void final_color_blend(video::SColor *result,
u16 light, u32 daynight_ratio)
u16 light, u32 daynight_ratio, const LightIntensity &lightIntensity)
{
video::SColorf dayLight;
get_sunlight_color(&dayLight, daynight_ratio);
get_sunlight_color(&dayLight, daynight_ratio, lightIntensity);
final_color_blend(result,
encode_light(light, 0), dayLight);
}
@ -742,8 +741,9 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs
if (!m_enable_shaders) {
// Extract colors for day-night animation
// Dummy sunlight to handle non-sunlit areas
const LightIntensity &lightIntensity = client->getEnv().getLocalPlayer()->getLighting().lightIntensity;
video::SColorf sunlight;
get_sunlight_color(&sunlight, 0);
get_sunlight_color(&sunlight, 0, lightIntensity);
std::map<u32, video::SColor> colors;
const u32 vertex_count = p.vertices.size();
@ -834,7 +834,7 @@ MapBlockMesh::~MapBlockMesh()
}
bool MapBlockMesh::animate(bool faraway, float time, int crack,
u32 daynight_ratio)
u32 daynight_ratio, const LightIntensity &lightIntensity)
{
if (!m_has_animation) {
m_animation_force_timer = 100000;
@ -896,7 +896,7 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack,
// Day-night transition
if (!m_enable_shaders && (daynight_ratio != m_last_daynight_ratio)) {
video::SColorf day_color;
get_sunlight_color(&day_color, daynight_ratio);
get_sunlight_color(&day_color, daynight_ratio, lightIntensity);
for (auto &daynight_diff : m_daynight_diffs) {
auto *mesh = m_mesh[daynight_diff.first.first];

View File

@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/numeric.h"
#include "client/tile.h"
#include "voxel.h"
#include "lighting.h"
#include <array>
#include <map>
#include <unordered_map>
@ -190,7 +191,7 @@ public:
// daynight_ratio: 0 .. 1000
// crack: -1 .. CRACK_ANIMATION_LENGTH-1 (-1 for off)
// Returns true if anything has been changed.
bool animate(bool faraway, float time, int crack, u32 daynight_ratio);
bool animate(bool faraway, float time, int crack, u32 daynight_ratio, const LightIntensity &lightIntensity);
scene::IMesh *getMesh()
{
@ -308,7 +309,7 @@ u16 getSmoothLightTransparent(const v3s16 &p, const v3s16 &corner, MeshMakeData
* Returns the sunlight's color from the current
* day-night ratio.
*/
void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio);
void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio, const LightIntensity &lightIntensity);
/*!
* Gives the final SColor shown on screen.
@ -318,7 +319,7 @@ void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio);
* night light
*/
void final_color_blend(video::SColor *result,
u16 light, u32 daynight_ratio);
u16 light, u32 daynight_ratio, const LightIntensity &lightIntensity);
/*!
* Gives the final SColor shown on screen.

View File

@ -27,3 +27,8 @@ AutoExposure::AutoExposure()
speed_bright_dark(1000.f),
center_weight_power(1.f)
{}
LightIntensity::LightIntensity()
: colorOffset_rgb{-0.04, -0.04, 0.078},
colorRatioCoef_rgb{1e-3, 1e-3, 0.98e-3}
{}

View File

@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include "irr_v3d.h"
/**
* Parameters for automatic exposure compensation
@ -46,11 +47,33 @@ struct AutoExposure
AutoExposure();
};
/**
* Parameters for set color and intensity of night and day light.
*
* Light color is calculated in function get_sunlight_color.
* Variable daynight_ration can be from 0 to 1000.
*
* sunlight->r = colorOffset_rgb.X+colorRatioCoef_rgb.X*daynight_ratio;
* sunlight->g = colorOffset_rgb.Y+colorRatioCoef_rgb.Y*daynight_ratio;
* sunlight->b = colorOffset_rgb.Z+colorRatioCoef_rgb.Z*daynight_ratio;
*
*/
struct LightIntensity
{
/// @brief Sunlight color offset
v3f colorOffset_rgb;
/// @brief Sunlight color dayratio effect
v3f colorRatioCoef_rgb;
LightIntensity();
};
/** Describes ambient light settings for a player
*/
struct Lighting
{
AutoExposure exposure;
LightIntensity lightIntensity;
float shadow_intensity {0.0f};
float saturation {1.0f};
float volumetric_light_strength {0.0f};

View File

@ -1815,4 +1815,12 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt)
}
if (pkt->getRemainingBytes() >= 4)
*pkt >> lighting.volumetric_light_strength;
if (pkt->getRemainingBytes() >= 24) {
*pkt >> lighting.lightIntensity.colorOffset_rgb.X
>> lighting.lightIntensity.colorOffset_rgb.Y
>> lighting.lightIntensity.colorOffset_rgb.Z
>> lighting.lightIntensity.colorRatioCoef_rgb.X
>> lighting.lightIntensity.colorRatioCoef_rgb.Y
>> lighting.lightIntensity.colorRatioCoef_rgb.Z;
}
}

View File

@ -2526,7 +2526,7 @@ int ObjectRef::l_set_lighting(lua_State *L)
if (lua_istable(L, -1)) {
lighting.exposure.luminance_min = getfloatfield_default(L, -1, "luminance_min", lighting.exposure.luminance_min);
lighting.exposure.luminance_max = getfloatfield_default(L, -1, "luminance_max", lighting.exposure.luminance_max);
lighting.exposure.exposure_correction = getfloatfield_default(L, -1, "exposure_correction", lighting.exposure.exposure_correction);
lighting.exposure.exposure_correction = getfloatfield_default(L, -1, "exposure_correction", lighting.exposure.exposure_correction);
lighting.exposure.speed_dark_bright = getfloatfield_default(L, -1, "speed_dark_bright", lighting.exposure.speed_dark_bright);
lighting.exposure.speed_bright_dark = getfloatfield_default(L, -1, "speed_bright_dark", lighting.exposure.speed_bright_dark);
lighting.exposure.center_weight_power = getfloatfield_default(L, -1, "center_weight_power", lighting.exposure.center_weight_power);
@ -2539,7 +2539,26 @@ int ObjectRef::l_set_lighting(lua_State *L)
lighting.volumetric_light_strength = rangelim(lighting.volumetric_light_strength, 0.0f, 1.0f);
}
lua_pop(L, 1); // volumetric_light
}
lua_getfield(L, 2, "light_intensity");
if (lua_istable(L, -1)) {
lua_getfield(L, 3, "color_offset");
if (lua_istable(L, -1)) {
lighting.lightIntensity.colorOffset_rgb.X = getfloatfield_default(L, -1, "r", lighting.lightIntensity.colorOffset_rgb.X);
lighting.lightIntensity.colorOffset_rgb.Y = getfloatfield_default(L, -1, "g", lighting.lightIntensity.colorOffset_rgb.Y);
lighting.lightIntensity.colorOffset_rgb.Z = getfloatfield_default(L, -1, "b", lighting.lightIntensity.colorOffset_rgb.Z);
}
lua_pop(L, 1); // color_offset
lua_getfield(L, 3, "color_ratio_coef");
if (lua_istable(L, -1)) {
lighting.lightIntensity.colorRatioCoef_rgb.X = getfloatfield_default(L, -1, "r", lighting.lightIntensity.colorRatioCoef_rgb.X);
lighting.lightIntensity.colorRatioCoef_rgb.Y = getfloatfield_default(L, -1, "g", lighting.lightIntensity.colorRatioCoef_rgb.Y);
lighting.lightIntensity.colorRatioCoef_rgb.Z = getfloatfield_default(L, -1, "b", lighting.lightIntensity.colorRatioCoef_rgb.Z);
}
lua_pop(L, 1); // color_ratio_coef
}
lua_pop(L, 1); // light_intensity
}
getServer(L)->setLighting(player, lighting);
return 0;
@ -2581,6 +2600,24 @@ int ObjectRef::l_get_lighting(lua_State *L)
lua_pushnumber(L, lighting.volumetric_light_strength);
lua_setfield(L, -2, "strength");
lua_setfield(L, -2, "volumetric_light");
lua_newtable(L); // "light_intensity"
lua_newtable(L); // "color_offset"
lua_pushnumber(L, lighting.lightIntensity.colorOffset_rgb.X);
lua_setfield(L, -2, "r");
lua_pushnumber(L, lighting.lightIntensity.colorOffset_rgb.Y);
lua_setfield(L, -2, "g");
lua_pushnumber(L, lighting.lightIntensity.colorOffset_rgb.Z);
lua_setfield(L, -2, "b");
lua_setfield(L, -2, "color_offset");
lua_newtable(L); // "color_ratio_coef"
lua_pushnumber(L, lighting.lightIntensity.colorRatioCoef_rgb.X);
lua_setfield(L, -2, "r");
lua_pushnumber(L, lighting.lightIntensity.colorRatioCoef_rgb.Y);
lua_setfield(L, -2, "g");
lua_pushnumber(L, lighting.lightIntensity.colorRatioCoef_rgb.Z);
lua_setfield(L, -2, "b");
lua_setfield(L, -2, "color_ratio_coef");
lua_setfield(L, -2, "light_intensity");
return 1;
}

View File

@ -1894,9 +1894,16 @@ void Server::SendSetLighting(session_t peer_id, const Lighting &lighting)
<< lighting.exposure.speed_dark_bright
<< lighting.exposure.speed_bright_dark
<< lighting.exposure.center_weight_power;
pkt << lighting.volumetric_light_strength;
pkt << lighting.lightIntensity.colorOffset_rgb.X
<< lighting.lightIntensity.colorOffset_rgb.Y
<< lighting.lightIntensity.colorOffset_rgb.Z
<< lighting.lightIntensity.colorRatioCoef_rgb.X
<< lighting.lightIntensity.colorRatioCoef_rgb.Y
<< lighting.lightIntensity.colorRatioCoef_rgb.Z;
Send(&pkt);
}