mirror of https://github.com/minetest/minetest.git
Add support for change sun light color in night and day.
This commit is contained in:
parent
a7908da968
commit
60d1927b04
|
@ -39,6 +39,7 @@ core.features = {
|
||||||
dynamic_add_media_filepath = true,
|
dynamic_add_media_filepath = true,
|
||||||
lsystem_decoration_type = true,
|
lsystem_decoration_type = true,
|
||||||
item_meta_range = true,
|
item_meta_range = true,
|
||||||
|
light_intensity = true,
|
||||||
}
|
}
|
||||||
|
|
||||||
function core.has_feature(arg)
|
function core.has_feature(arg)
|
||||||
|
|
|
@ -5431,6 +5431,8 @@ Utilities
|
||||||
lsystem_decoration_type = true,
|
lsystem_decoration_type = true,
|
||||||
-- Overrideable pointing range using the itemstack meta key `"range"` (5.9.0)
|
-- Overrideable pointing range using the itemstack meta key `"range"` (5.9.0)
|
||||||
item_meta_range = true,
|
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")
|
* `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)
|
* `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.
|
* 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.
|
* `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`.
|
* Result is a table with the same fields as `light_definition` in `set_lighting`.
|
||||||
|
|
|
@ -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 result = "{\n"
|
||||||
local section_count = 0
|
local section_count = 0
|
||||||
for _,section in ipairs(lighting_sections) do
|
for _,section in ipairs(recipe) do
|
||||||
section_count = section_count + 1
|
section_count = section_count + 1
|
||||||
|
|
||||||
local parameters = section.entries or {}
|
local parameters = section.entries or {}
|
||||||
local state = lighting[section.n] or {}
|
local state = data[section.n] or {}
|
||||||
|
|
||||||
result = result.." "..section.n.." = {\n"
|
result = result.." "..section.n.." = {\n"
|
||||||
|
|
||||||
|
@ -40,7 +25,7 @@ local function dump_lighting(lighting)
|
||||||
|
|
||||||
result = result.." }"
|
result = result.." }"
|
||||||
|
|
||||||
if section_count < #lighting_sections then
|
if section_count < #recipe then
|
||||||
result = result..","
|
result = result..","
|
||||||
end
|
end
|
||||||
result = result.."\n"
|
result = result.."\n"
|
||||||
|
@ -49,74 +34,59 @@ local function dump_lighting(lighting)
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_chatcommand("set_lighting", {
|
local function buildGUI(player, data, recipe, gui_name)
|
||||||
params = "",
|
local form = {
|
||||||
description = "Tune lighting parameters",
|
"formspec_version[2]",
|
||||||
func = function(player_name, param)
|
"size[15,30]",
|
||||||
local player = minetest.get_player_by_name(player_name);
|
"position[0.99,0.15]",
|
||||||
if not player then return end
|
"anchor[1,0]",
|
||||||
|
"padding[0.05,0.1]",
|
||||||
|
"no_prepend[]"
|
||||||
|
};
|
||||||
|
|
||||||
local lighting = player:get_lighting()
|
local line = 1
|
||||||
local exposure = lighting.exposure or {}
|
for _,section in ipairs(recipe) do
|
||||||
|
local parameters = section.entries or {}
|
||||||
|
local state = data[section.n] or {}
|
||||||
|
|
||||||
local form = {
|
table.insert(form, "label[1,"..line..";"..section.d.."]")
|
||||||
"formspec_version[2]",
|
line = line + 1
|
||||||
"size[15,30]",
|
|
||||||
"position[0.99,0.15]",
|
|
||||||
"anchor[1,0]",
|
|
||||||
"padding[0.05,0.1]",
|
|
||||||
"no_prepend[]"
|
|
||||||
};
|
|
||||||
|
|
||||||
local line = 1
|
for _,v in ipairs(parameters) do
|
||||||
for _,section in ipairs(lighting_sections) do
|
table.insert(form, "label[2,"..line..";"..v.d.."]")
|
||||||
local parameters = section.entries or {}
|
table.insert(form, "scrollbaroptions[min=0;max=1000;smallstep=10;largestep=100;thumbsize=10]")
|
||||||
local state = lighting[section.n] or {}
|
local value = state[v.n]
|
||||||
|
if v.type == "log2" then
|
||||||
table.insert(form, "label[1,"..line..";"..section.d.."]")
|
value = math.log(value or 1) / math.log(2)
|
||||||
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
|
|
||||||
end
|
end
|
||||||
|
local sb_scale = math.floor(1000 * (math.max(v.min, value or 0) - v.min) / (v.max - v.min))
|
||||||
line = line + 1
|
table.insert(form, "scrollbar[2,"..(line+0.7)..";12,1;horizontal;"..section.n.."."..v.n..";"..sb_scale.."]")
|
||||||
|
line = line + 2.7
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.show_formspec(player_name, "lighting", table.concat(form))
|
line = line + 1
|
||||||
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)
|
|
||||||
end
|
end
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
minetest.show_formspec(player:get_player_name(), gui_name, table.concat(form))
|
||||||
if formname ~= "lighting" then return end
|
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 function receiveFields(player, fields, data, recipe, gui_name)
|
||||||
|
local hud_id = player:get_meta():get_int(gui_name.."_hud")
|
||||||
local hud_id = player:get_meta():get_int("lighting_hud")
|
|
||||||
|
|
||||||
if fields.quit then
|
if fields.quit then
|
||||||
player:hud_remove(hud_id)
|
player:hud_remove(hud_id)
|
||||||
player:get_meta():set_int("lighting_hud", -1)
|
player:get_meta():set_int(gui_name.."_hud", -1)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local lighting = player:get_lighting()
|
for _,section in ipairs(recipe) do
|
||||||
for _,section in ipairs(lighting_sections) do
|
|
||||||
local parameters = section.entries or {}
|
local parameters = section.entries or {}
|
||||||
|
|
||||||
local state = (lighting[section.n] or {})
|
local state = (data[section.n] or {})
|
||||||
lighting[section.n] = state
|
data[section.n] = state
|
||||||
|
|
||||||
for _,v in ipairs(parameters) do
|
for _,v in ipairs(parameters) do
|
||||||
|
|
||||||
|
@ -133,8 +103,96 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local debug_value = dump_lighting(lighting)
|
local debug_value = dumpByRecipe(data, recipe)
|
||||||
player:hud_change(hud_id, "text", debug_value)
|
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)
|
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)
|
||||||
|
|
||||||
|
|
|
@ -262,7 +262,8 @@ void ClientEnvironment::step(float dtime)
|
||||||
|
|
||||||
u16 light = getInteriorLight(node_at_lplayer, 0, m_client->ndef());
|
u16 light = getInteriorLight(node_at_lplayer, 0, m_client->ndef());
|
||||||
lplayer->light_color = encode_light(light, 0); // this transfers light.alpha
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -719,6 +719,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||||
const float animation_time = m_client->getAnimationTime();
|
const float animation_time = m_client->getAnimationTime();
|
||||||
const int crack = m_client->getCrackLevel();
|
const int crack = m_client->getCrackLevel();
|
||||||
const u32 daynight_ratio = m_client->getEnv().getDayNightRatio();
|
const u32 daynight_ratio = m_client->getEnv().getDayNightRatio();
|
||||||
|
const Lighting &lighting = m_client->getEnv().getLocalPlayer()->getLighting();
|
||||||
|
|
||||||
const v3f camera_position = m_camera_position;
|
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)) {
|
mesh_animate_count < (m_control.range_all ? 200 : 50)) {
|
||||||
|
|
||||||
bool animated = block_mesh->animate(faraway, animation_time,
|
bool animated = block_mesh->animate(faraway, animation_time,
|
||||||
crack, daynight_ratio);
|
crack, daynight_ratio, lighting.lightIntensity);
|
||||||
if (animated)
|
if (animated)
|
||||||
mesh_animate_count++;
|
mesh_animate_count++;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -908,8 +908,10 @@ void GenericCAO::updateLight(u32 day_night_ratio)
|
||||||
// based on the entity glow.
|
// based on the entity glow.
|
||||||
if (m_enable_shaders)
|
if (m_enable_shaders)
|
||||||
light = encode_light(light_at_pos, m_prop.glow);
|
light = encode_light(light_at_pos, m_prop.glow);
|
||||||
else
|
else {
|
||||||
final_color_blend(&light, light_at_pos, day_night_ratio);
|
const LightIntensity &lightIntensity = m_env->getLocalPlayer()->getLighting().lightIntensity;
|
||||||
|
final_color_blend(&light, light_at_pos, day_night_ratio, lightIntensity);
|
||||||
|
}
|
||||||
|
|
||||||
if (light != m_last_light) {
|
if (light != m_last_light) {
|
||||||
m_last_light = light;
|
m_last_light = light;
|
||||||
|
|
|
@ -470,8 +470,9 @@ public:
|
||||||
void onSetConstants(video::IMaterialRendererServices *services) override
|
void onSetConstants(video::IMaterialRendererServices *services) override
|
||||||
{
|
{
|
||||||
u32 daynight_ratio = (float)m_client->getEnv().getDayNightRatio();
|
u32 daynight_ratio = (float)m_client->getEnv().getDayNightRatio();
|
||||||
|
const auto &lighting = m_client->getEnv().getLocalPlayer()->getLighting();
|
||||||
video::SColorf sunlight;
|
video::SColorf sunlight;
|
||||||
get_sunlight_color(&sunlight, daynight_ratio);
|
get_sunlight_color(&sunlight, daynight_ratio, lighting.lightIntensity);
|
||||||
m_day_light.set(sunlight, services);
|
m_day_light.set(sunlight, services);
|
||||||
|
|
||||||
u32 animation_timer = m_client->getEnv().getFrameTime() % 1000000;
|
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_vertex.set(m_texel_size0, services);
|
||||||
m_texel_size0_pixel.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::array<float, 7> exposure_buffer = {
|
||||||
std::pow(2.0f, exposure_params.luminance_min),
|
std::pow(2.0f, exposure_params.luminance_min),
|
||||||
std::pow(2.0f, exposure_params.luminance_max),
|
std::pow(2.0f, exposure_params.luminance_max),
|
||||||
|
@ -527,7 +528,6 @@ public:
|
||||||
m_bloom_strength_pixel.set(&m_bloom_strength, services);
|
m_bloom_strength_pixel.set(&m_bloom_strength, services);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto &lighting = m_client->getEnv().getLocalPlayer()->getLighting();
|
|
||||||
float saturation = lighting.saturation;
|
float saturation = lighting.saturation;
|
||||||
m_saturation_pixel.set(&saturation, services);
|
m_saturation_pixel.set(&saturation, services);
|
||||||
|
|
||||||
|
@ -3458,8 +3458,9 @@ PointedThing Game::updatePointedThing(
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 daynight_ratio = client->getEnv().getDayNightRatio();
|
u32 daynight_ratio = client->getEnv().getDayNightRatio();
|
||||||
|
const Lighting &lighting = client->getEnv().getLocalPlayer()->getLighting();
|
||||||
video::SColor c;
|
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
|
// Modify final color a bit with time
|
||||||
u32 timer = client->getEnv().getFrameTime() % 5000;
|
u32 timer = client->getEnv().getFrameTime() % 5000;
|
||||||
|
|
|
@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "util/directiontables.h"
|
#include "util/directiontables.h"
|
||||||
#include "client/meshgen/collector.h"
|
#include "client/meshgen/collector.h"
|
||||||
#include "client/renderingengine.h"
|
#include "client/renderingengine.h"
|
||||||
|
#include "client/localplayer.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
@ -281,19 +282,17 @@ u16 getSmoothLightTransparent(const v3s16 &p, const v3s16 &corner, MeshMakeData
|
||||||
return getSmoothLightCombined(p, dirs, data);
|
return getSmoothLightCombined(p, dirs, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio){
|
void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio, const LightIntensity &lightIntensity){
|
||||||
f32 rg = daynight_ratio / 1000.0f - 0.04f;
|
sunlight->r = lightIntensity.colorOffset_rgb.X+lightIntensity.colorRatioCoef_rgb.X*daynight_ratio;
|
||||||
f32 b = (0.98f * daynight_ratio) / 1000.0f + 0.078f;
|
sunlight->g = lightIntensity.colorOffset_rgb.Y+lightIntensity.colorRatioCoef_rgb.Y*daynight_ratio;
|
||||||
sunlight->r = rg;
|
sunlight->b = lightIntensity.colorOffset_rgb.Z+lightIntensity.colorRatioCoef_rgb.Z*daynight_ratio;
|
||||||
sunlight->g = rg;
|
|
||||||
sunlight->b = b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void final_color_blend(video::SColor *result,
|
void final_color_blend(video::SColor *result,
|
||||||
u16 light, u32 daynight_ratio)
|
u16 light, u32 daynight_ratio, const LightIntensity &lightIntensity)
|
||||||
{
|
{
|
||||||
video::SColorf dayLight;
|
video::SColorf dayLight;
|
||||||
get_sunlight_color(&dayLight, daynight_ratio);
|
get_sunlight_color(&dayLight, daynight_ratio, lightIntensity);
|
||||||
final_color_blend(result,
|
final_color_blend(result,
|
||||||
encode_light(light, 0), dayLight);
|
encode_light(light, 0), dayLight);
|
||||||
}
|
}
|
||||||
|
@ -742,8 +741,9 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs
|
||||||
if (!m_enable_shaders) {
|
if (!m_enable_shaders) {
|
||||||
// Extract colors for day-night animation
|
// Extract colors for day-night animation
|
||||||
// Dummy sunlight to handle non-sunlit areas
|
// Dummy sunlight to handle non-sunlit areas
|
||||||
|
const LightIntensity &lightIntensity = client->getEnv().getLocalPlayer()->getLighting().lightIntensity;
|
||||||
video::SColorf sunlight;
|
video::SColorf sunlight;
|
||||||
get_sunlight_color(&sunlight, 0);
|
get_sunlight_color(&sunlight, 0, lightIntensity);
|
||||||
|
|
||||||
std::map<u32, video::SColor> colors;
|
std::map<u32, video::SColor> colors;
|
||||||
const u32 vertex_count = p.vertices.size();
|
const u32 vertex_count = p.vertices.size();
|
||||||
|
@ -834,7 +834,7 @@ MapBlockMesh::~MapBlockMesh()
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MapBlockMesh::animate(bool faraway, float time, int crack,
|
bool MapBlockMesh::animate(bool faraway, float time, int crack,
|
||||||
u32 daynight_ratio)
|
u32 daynight_ratio, const LightIntensity &lightIntensity)
|
||||||
{
|
{
|
||||||
if (!m_has_animation) {
|
if (!m_has_animation) {
|
||||||
m_animation_force_timer = 100000;
|
m_animation_force_timer = 100000;
|
||||||
|
@ -896,7 +896,7 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack,
|
||||||
// Day-night transition
|
// Day-night transition
|
||||||
if (!m_enable_shaders && (daynight_ratio != m_last_daynight_ratio)) {
|
if (!m_enable_shaders && (daynight_ratio != m_last_daynight_ratio)) {
|
||||||
video::SColorf day_color;
|
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) {
|
for (auto &daynight_diff : m_daynight_diffs) {
|
||||||
auto *mesh = m_mesh[daynight_diff.first.first];
|
auto *mesh = m_mesh[daynight_diff.first.first];
|
||||||
|
|
|
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "util/numeric.h"
|
#include "util/numeric.h"
|
||||||
#include "client/tile.h"
|
#include "client/tile.h"
|
||||||
#include "voxel.h"
|
#include "voxel.h"
|
||||||
|
#include "lighting.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
@ -190,7 +191,7 @@ public:
|
||||||
// daynight_ratio: 0 .. 1000
|
// daynight_ratio: 0 .. 1000
|
||||||
// crack: -1 .. CRACK_ANIMATION_LENGTH-1 (-1 for off)
|
// crack: -1 .. CRACK_ANIMATION_LENGTH-1 (-1 for off)
|
||||||
// Returns true if anything has been changed.
|
// 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()
|
scene::IMesh *getMesh()
|
||||||
{
|
{
|
||||||
|
@ -308,7 +309,7 @@ u16 getSmoothLightTransparent(const v3s16 &p, const v3s16 &corner, MeshMakeData
|
||||||
* Returns the sunlight's color from the current
|
* Returns the sunlight's color from the current
|
||||||
* day-night ratio.
|
* 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.
|
* Gives the final SColor shown on screen.
|
||||||
|
@ -318,7 +319,7 @@ void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio);
|
||||||
* night light
|
* night light
|
||||||
*/
|
*/
|
||||||
void final_color_blend(video::SColor *result,
|
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.
|
* Gives the final SColor shown on screen.
|
||||||
|
|
|
@ -27,3 +27,8 @@ AutoExposure::AutoExposure()
|
||||||
speed_bright_dark(1000.f),
|
speed_bright_dark(1000.f),
|
||||||
center_weight_power(1.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}
|
||||||
|
{}
|
||||||
|
|
|
@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "irr_v3d.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parameters for automatic exposure compensation
|
* Parameters for automatic exposure compensation
|
||||||
|
@ -46,11 +47,33 @@ struct AutoExposure
|
||||||
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
|
/** Describes ambient light settings for a player
|
||||||
*/
|
*/
|
||||||
struct Lighting
|
struct Lighting
|
||||||
{
|
{
|
||||||
AutoExposure exposure;
|
AutoExposure exposure;
|
||||||
|
LightIntensity lightIntensity;
|
||||||
float shadow_intensity {0.0f};
|
float shadow_intensity {0.0f};
|
||||||
float saturation {1.0f};
|
float saturation {1.0f};
|
||||||
float volumetric_light_strength {0.0f};
|
float volumetric_light_strength {0.0f};
|
||||||
|
|
|
@ -1815,4 +1815,12 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt)
|
||||||
}
|
}
|
||||||
if (pkt->getRemainingBytes() >= 4)
|
if (pkt->getRemainingBytes() >= 4)
|
||||||
*pkt >> lighting.volumetric_light_strength;
|
*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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2526,7 +2526,7 @@ int ObjectRef::l_set_lighting(lua_State *L)
|
||||||
if (lua_istable(L, -1)) {
|
if (lua_istable(L, -1)) {
|
||||||
lighting.exposure.luminance_min = getfloatfield_default(L, -1, "luminance_min", lighting.exposure.luminance_min);
|
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.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_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.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);
|
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);
|
lighting.volumetric_light_strength = rangelim(lighting.volumetric_light_strength, 0.0f, 1.0f);
|
||||||
}
|
}
|
||||||
lua_pop(L, 1); // volumetric_light
|
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);
|
getServer(L)->setLighting(player, lighting);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2581,6 +2600,24 @@ int ObjectRef::l_get_lighting(lua_State *L)
|
||||||
lua_pushnumber(L, lighting.volumetric_light_strength);
|
lua_pushnumber(L, lighting.volumetric_light_strength);
|
||||||
lua_setfield(L, -2, "strength");
|
lua_setfield(L, -2, "strength");
|
||||||
lua_setfield(L, -2, "volumetric_light");
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1894,9 +1894,16 @@ void Server::SendSetLighting(session_t peer_id, const Lighting &lighting)
|
||||||
<< lighting.exposure.speed_dark_bright
|
<< lighting.exposure.speed_dark_bright
|
||||||
<< lighting.exposure.speed_bright_dark
|
<< lighting.exposure.speed_bright_dark
|
||||||
<< lighting.exposure.center_weight_power;
|
<< lighting.exposure.center_weight_power;
|
||||||
|
|
||||||
pkt << lighting.volumetric_light_strength;
|
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);
|
Send(&pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue