Merge fb3d75b4672479a1a00a4612ddc91bf53f045a42 into b23042839b

This commit is contained in:
Andrey 2024-05-16 00:38:08 -03:00 committed by GitHub
commit d76d0e4de8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 264 additions and 140 deletions

View File

@ -6,6 +6,8 @@ uniform vec3 dayLight;
uniform highp vec3 cameraOffset;
uniform float animationTimer;
uniform vec3 ambientLight;
varying vec3 vNormal;
varying vec3 vPosition;
// World position in the visible world (i.e. relative to the cameraOffset.)
@ -220,6 +222,8 @@ void main(void)
color.b += max(0.0, 0.021 - abs(0.2 * brightness - 0.021) +
0.07 * brightness);
color.rgb += ambientLight;
varColor = clamp(color, 0.0, 1.0);
#ifdef ENABLE_DYNAMIC_SHADOWS

View File

@ -2,6 +2,7 @@ uniform mat4 mWorld;
uniform vec3 dayLight;
uniform float animationTimer;
uniform lowp vec4 emissiveColor;
uniform vec3 ambientLight;
varying vec3 vNormal;
varying vec3 vPosition;
@ -129,6 +130,8 @@ void main(void)
color.b += max(0.0, 0.021 - abs(0.2 * brightness - 0.021) +
0.07 * brightness);
color.rgb += ambientLight;
varColor = clamp(color, 0.0, 1.0);

View File

@ -8387,6 +8387,14 @@ child will follow movement and rotation of that bone.
* `set_lighting(light_definition)`: sets lighting for the player
* Passing no arguments resets lighting to its default values.
* `light_definition` is a table with the following optional fields:
* `ambient_light` is a ColorSpec controlling color of global ambient light;
(default: `{a = 255, r = 0, g = 0, b = 0}` / last set value).
* It works only if shaders are enabled.
* Alpha is ignored (it is always set to 255).
* Note: Total light is clamped before being applied.
This means that when an object is fully lit, ambient light
will take no effect. Setting ambient light to `"#FFFFFF"`
will make all objects be fully lit at all times ("fullbright").
* `saturation` sets the saturation (vividness; default: `1.0`).
* values > 1 increase the saturation
* values in [0,1] decrease the saturation

View File

@ -14,6 +14,14 @@ local lighting_sections = {
{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},
}
},
{
n = "ambient_light", d = "Ambient Light",
entries = {
{n = "r", d = "Red", min = 0, max = 255},
{n = "g", d = "Green", min = 0, max = 255},
{n = "b", d = "Blue", min = 0, max = 255}
}
}
}
@ -61,7 +69,7 @@ minetest.register_chatcommand("set_lighting", {
local form = {
"formspec_version[2]",
"size[15,30]",
"size[15,32]",
"position[0.99,0.15]",
"anchor[1,0]",
"padding[0.05,0.1]",
@ -137,4 +145,4 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
player:hud_change(hud_id, "text", debug_value)
player:set_lighting(lighting)
end)
end)

View File

@ -57,6 +57,7 @@ set(client_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/inputhandler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/joystick_controller.cpp
${CMAKE_CURRENT_SOURCE_DIR}/keycode.cpp
${CMAKE_CURRENT_SOURCE_DIR}/light_colors.cpp
${CMAKE_CURRENT_SOURCE_DIR}/localplayer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mapblock_mesh.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mesh.cpp

View File

@ -38,6 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "porting.h"
#include <algorithm>
#include "client/renderingengine.h"
#include "light_colors.h"
/*
ClientEnvironment
@ -262,7 +263,12 @@ 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);
video::SColor ambient_light(255, 0, 0, 0);
if (g_settings->getBool("enable_shaders"))
ambient_light = lplayer->getLighting().ambient_light;
final_color_blend(&lplayer->light_color, light, day_night_ratio, ambient_light);
}
/*

View File

@ -48,6 +48,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "client/shader.h"
#include "client/minimap.h"
#include <quaternion.h>
#include "light_colors.h"
class Settings;
struct ToolCapabilities;

View File

@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "client/renderingengine.h"
#include "client.h"
#include "noise.h"
#include "light_colors.h"
// Distance of light extrapolation (for oversized nodes)
// After this distance, it gives up and considers light level constant

View File

@ -79,6 +79,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "hud.h"
#include "clientdynamicinfo.h"
#include <IAnimatedMeshSceneNode.h>
#include "light_colors.h"
#if USE_SOUND
#include "client/sound/sound_openal.h"
@ -382,6 +383,7 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter
CachedPixelShaderSetting<float>
m_animation_timer_delta_pixel{"animationTimerDelta"};
CachedPixelShaderSetting<float, 3> m_day_light{"dayLight"};
CachedVertexShaderSetting<float, 3> m_ambient_light{"ambientLight"};
CachedPixelShaderSetting<float, 3> m_minimap_yaw{"yawVec"};
CachedPixelShaderSetting<float, 3> m_camera_offset_pixel{"cameraOffset"};
CachedVertexShaderSetting<float, 3> m_camera_offset_vertex{"cameraOffset"};
@ -473,6 +475,11 @@ public:
get_sunlight_color(&sunlight, daynight_ratio);
m_day_light.set(sunlight, services);
auto lighting = m_client->getEnv().getLocalPlayer()->getLighting();
video::SColorf ambient_light_f(lighting.ambient_light);
m_ambient_light.set(ambient_light_f, services);
u32 animation_timer = m_client->getEnv().getFrameTime() % 1000000;
float animation_timer_f = (float)animation_timer / 100000.f;
m_animation_timer_vertex.set(&animation_timer_f, services);
@ -504,7 +511,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),
@ -522,7 +529,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);
@ -1441,7 +1447,7 @@ void Game::copyServerClientCache()
{
// It would be possible to let the client directly read the media files
// from where the server knows they are. But aside from being more complicated
// it would also *not* fill the media cache and cause slower joining of
// it would also *not* fill the media cache and cause slower joining of
// remote servers.
// (Imagine that you launch a game once locally and then connect to a server.)

View File

@ -0,0 +1,98 @@
/*
Minetest
Copyright (C) 2024 Andrey2470T, AndreyT <andreyt2203@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "light_colors.h"
video::SColor encode_light(u16 light, u8 emissive_light)
{
// Get components
u32 day = (light & 0xff);
u32 night = (light >> 8);
// Add emissive light
night += emissive_light * 2.5f;
if (night > 255)
night = 255;
// Since we don't know if the day light is sunlight or
// artificial light, assume it is artificial when the night
// light bank is also lit.
if (day < night)
day = 0;
else
day = day - night;
u32 sum = day + night;
// Ratio of sunlight:
u32 r;
if (sum > 0)
r = day * 255 / sum;
else
r = 0;
// Average light:
float b = (day + night) / 2;
return video::SColor(r, b, b, b);
}
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 final_color_blend(video::SColor *result,
u16 light, u32 daynight_ratio, video::SColor ambientLight)
{
video::SColorf dayLight;
get_sunlight_color(&dayLight, daynight_ratio);
final_color_blend(result,
encode_light(light, 0), dayLight, ambientLight);
}
void final_color_blend(video::SColor *result,
const video::SColor &data, const video::SColorf &dayLight,
video::SColor ambientLight)
{
static const video::SColorf artificialColor(1.04f, 1.04f, 1.04f);
video::SColorf c(data);
f32 n = 1 - c.a;
f32 r = c.r * (c.a * dayLight.r + n * artificialColor.r) * 2.0f;
f32 g = c.g * (c.a * dayLight.g + n * artificialColor.g) * 2.0f;
f32 b = c.b * (c.a * dayLight.b + n * artificialColor.b) * 2.0f;
// Emphase blue a bit in darker places
// Each entry of this array represents a range of 8 blue levels
static const u8 emphase_blue_when_dark[32] = {
1, 4, 6, 6, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
b += emphase_blue_when_dark[irr::core::clamp((s32) ((r + g + b) / 3 * 255),
0, 255) / 8] / 255.0f;
// Add ambient light
r += ambientLight.getRed() / 255.f;
g += ambientLight.getGreen() / 255.f;
b += ambientLight.getBlue() / 255.f;
result->setRed(core::clamp((s32)(r * 255.f), 0, 255));
result->setGreen(core::clamp((s32)(g * 255.f), 0, 255));
result->setBlue(core::clamp((s32)(b * 255.f), 0, 255));
}

61
src/client/light_colors.h Normal file
View File

@ -0,0 +1,61 @@
/*
Minetest
Copyright (C) 2024 Andrey2470T, AndreyT <andreyt2203@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "irrlichttypes_extrabloated.h"
/*!
* Encodes light of a node.
* The result is not the final color, but a
* half-baked vertex color.
* You have to multiply the resulting color
* with the node's color.
*
* \param light the first 8 bits are day light,
* the last 8 bits are night light
* \param emissive_light amount of light the surface emits,
* from 0 to LIGHT_SUN.
*/
video::SColor encode_light(u16 light, u8 emissive_light);
/*!
* Returns the sunlight's color from the current
* day-night ratio.
*/
void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio);
/*!
* Gives the final SColor shown on screen.
*
* \param result output color
* \param light first 8 bits are day light, second 8 bits are
* night light
*/
void final_color_blend(video::SColor *result,
u16 light, u32 daynight_ratio, video::SColor ambientLight=video::SColor(255,0,0,0));
/*!
* Gives the final SColor shown on screen.
*
* \param result output color
* \param data the half-baked vertex color
* \param dayLight color of the sunlight
*/
void final_color_blend(video::SColor *result,
const video::SColor &data, const video::SColorf &dayLight,
video::SColor ambientLight=video::SColor(255,0,0,0));

View File

@ -34,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <algorithm>
#include <cmath>
#include "client/texturesource.h"
#include "light_colors.h"
/*
MeshMakeData
@ -281,49 +282,6 @@ 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 final_color_blend(video::SColor *result,
u16 light, u32 daynight_ratio)
{
video::SColorf dayLight;
get_sunlight_color(&dayLight, daynight_ratio);
final_color_blend(result,
encode_light(light, 0), dayLight);
}
void final_color_blend(video::SColor *result,
const video::SColor &data, const video::SColorf &dayLight)
{
static const video::SColorf artificialColor(1.04f, 1.04f, 1.04f);
video::SColorf c(data);
f32 n = 1 - c.a;
f32 r = c.r * (c.a * dayLight.r + n * artificialColor.r) * 2.0f;
f32 g = c.g * (c.a * dayLight.g + n * artificialColor.g) * 2.0f;
f32 b = c.b * (c.a * dayLight.b + n * artificialColor.b) * 2.0f;
// Emphase blue a bit in darker places
// Each entry of this array represents a range of 8 blue levels
static const u8 emphase_blue_when_dark[32] = {
1, 4, 6, 6, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
b += emphase_blue_when_dark[irr::core::clamp((s32) ((r + g + b) / 3 * 255),
0, 255) / 8] / 255.0f;
result->setRed(core::clamp((s32) (r * 255.0f), 0, 255));
result->setGreen(core::clamp((s32) (g * 255.0f), 0, 255));
result->setBlue(core::clamp((s32) (b * 255.0f), 0, 255));
}
/*
Mesh generation helpers
@ -808,7 +766,7 @@ MapBlockMesh::~MapBlockMesh()
}
bool MapBlockMesh::animate(bool faraway, float time, int crack,
u32 daynight_ratio)
u32 daynight_ratio)
{
if (!m_has_animation) {
m_animation_force_timer = 100000;
@ -880,7 +838,7 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack,
video::S3DVertex *vertices = (video::S3DVertex *)buf->getVertices();
for (const auto &j : daynight_diff.second)
final_color_blend(&(vertices[j.first].Color), j.second,
day_color);
day_color);
}
m_last_daynight_ratio = daynight_ratio;
}
@ -949,34 +907,6 @@ void MapBlockMesh::consolidateTransparentBuffers()
}
}
video::SColor encode_light(u16 light, u8 emissive_light)
{
// Get components
u32 day = (light & 0xff);
u32 night = (light >> 8);
// Add emissive light
night += emissive_light * 2.5f;
if (night > 255)
night = 255;
// Since we don't know if the day light is sunlight or
// artificial light, assume it is artificial when the night
// light bank is also lit.
if (day < night)
day = 0;
else
day = day - night;
u32 sum = day + night;
// Ratio of sunlight:
u32 r;
if (sum > 0)
r = day * 255 / sum;
else
r = 0;
// Average light:
float b = (day + night) / 2;
return video::SColor(r, b, b, b);
}
u8 get_solid_sides(MeshMakeData *data)
{
std::unordered_map<v3s16, u8> results;

View File

@ -284,52 +284,12 @@ private:
std::vector<PartialMeshBuffer> m_transparent_buffers;
};
/*!
* Encodes light of a node.
* The result is not the final color, but a
* half-baked vertex color.
* You have to multiply the resulting color
* with the node's color.
*
* \param light the first 8 bits are day light,
* the last 8 bits are night light
* \param emissive_light amount of light the surface emits,
* from 0 to LIGHT_SUN.
*/
video::SColor encode_light(u16 light, u8 emissive_light);
// Compute light at node
u16 getInteriorLight(MapNode n, s32 increment, const NodeDefManager *ndef);
u16 getFaceLight(MapNode n, MapNode n2, const NodeDefManager *ndef);
u16 getSmoothLightSolid(const v3s16 &p, const v3s16 &face_dir, const v3s16 &corner, MeshMakeData *data);
u16 getSmoothLightTransparent(const v3s16 &p, const v3s16 &corner, MeshMakeData *data);
/*!
* Returns the sunlight's color from the current
* day-night ratio.
*/
void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio);
/*!
* Gives the final SColor shown on screen.
*
* \param result output color
* \param light first 8 bits are day light, second 8 bits are
* night light
*/
void final_color_blend(video::SColor *result,
u16 light, u32 daynight_ratio);
/*!
* Gives the final SColor shown on screen.
*
* \param result output color
* \param data the half-baked vertex color
* \param dayLight color of the sunlight
*/
void final_color_blend(video::SColor *result,
const video::SColor &data, const video::SColorf &dayLight);
// Retrieves the TileSpec of a face of a node
// Adds MATERIAL_FLAG_CRACK if the node is cracked
// TileSpec should be passed as reference due to the underlying TileFrame and its vector

View File

@ -35,6 +35,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "client.h"
#include "settings.h"
#include "profiler.h"
#include "client/mapblock_mesh.h"
#include "light_colors.h"
ClientParticleTexture::ClientParticleTexture(const ServerParticleTexture& p, ITextureSource *tsrc)
{
@ -185,11 +187,16 @@ video::SColor Particle::updateLight(ClientEnvironment *env)
else
light = blend_light(env->getDayNightRatio(), LIGHT_SUN, 0);
u8 m_light = decode_light(light + m_p.glow);
light = decode_light(light + m_p.glow);
video::SColor light_color{0xFFFFFFFF};
final_color_blend(&light_color, static_cast<u16>(light) * 255, env->getDayNightRatio(),
env->getLocalPlayer()->getLighting().ambient_light);
return video::SColor(255,
m_light * m_base_color.getRed() / 255,
m_light * m_base_color.getGreen() / 255,
m_light * m_base_color.getBlue() / 255);
light_color.getRed() * m_base_color.getRed() / 255,
light_color.getGreen() * m_base_color.getGreen() / 255,
light_color.getBlue() * m_base_color.getBlue() / 255);
}
void Particle::updateVertices(ClientEnvironment *env, video::SColor color)

View File

@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
#pragma once
#include "irrlichttypes_bloated.h"
/**
@ -46,11 +47,11 @@ struct AutoExposure
AutoExposure();
};
/** Describes ambient light settings for a player
*/
struct Lighting
{
AutoExposure exposure;
/// @brief Ambient light color & intensity for nodes & entities. Alpha is ignored.
video::SColor ambient_light {255, 0, 0, 0};
float shadow_intensity {0.0f};
float saturation {1.0f};
float volumetric_light_strength {0.0f};

View File

@ -1801,18 +1801,28 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt)
{
Lighting& lighting = m_env.getLocalPlayer()->getLighting();
if (pkt->getRemainingBytes() >= 4)
*pkt >> lighting.shadow_intensity;
if (pkt->getRemainingBytes() >= 4)
*pkt >> lighting.saturation;
if (pkt->getRemainingBytes() >= 24) {
*pkt >> lighting.exposure.luminance_min
>> lighting.exposure.luminance_max
>> lighting.exposure.exposure_correction
>> lighting.exposure.speed_dark_bright
>> lighting.exposure.speed_bright_dark
>> lighting.exposure.center_weight_power;
}
if (pkt->getRemainingBytes() >= 4)
*pkt >> lighting.volumetric_light_strength;
if (pkt->getRemainingBytes() < 4)
return;
*pkt >> lighting.shadow_intensity;
if (pkt->getRemainingBytes() < 4)
return;
*pkt >> lighting.saturation;
if (pkt->getRemainingBytes() < 24)
return;
*pkt >> lighting.exposure.luminance_min
>> lighting.exposure.luminance_max
>> lighting.exposure.exposure_correction
>> lighting.exposure.speed_dark_bright
>> lighting.exposure.speed_bright_dark
>> lighting.exposure.center_weight_power;
if (pkt->getRemainingBytes() < 4)
return;
*pkt >> lighting.volumetric_light_strength;
if (pkt->getRemainingBytes() < 4)
return;
*pkt >> lighting.ambient_light;
}

View File

@ -2534,6 +2534,13 @@ int ObjectRef::l_set_lighting(lua_State *L)
}
lua_pop(L, 1); // shadows
lua_getfield(L, 2, "ambient_light");
if (!lua_isnil(L, -1)) {
read_color(L, -1, &lighting.ambient_light);
lighting.ambient_light.setAlpha(255); // alpha should always be 255
}
lua_pop(L, 1); // ambient light
getfloatfield(L, -1, "saturation", lighting.saturation);
lua_getfield(L, 2, "exposure");
@ -2553,7 +2560,7 @@ 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
}
}
getServer(L)->setLighting(player, lighting);
return 0;
@ -2575,6 +2582,16 @@ int ObjectRef::l_get_lighting(lua_State *L)
lua_pushnumber(L, lighting.shadow_intensity);
lua_setfield(L, -2, "intensity");
lua_setfield(L, -2, "shadows");
lua_newtable(L); // "ambient_light"
lua_pushnumber(L, lighting.ambient_light.getRed());
lua_setfield(L, -2, "r");
lua_pushnumber(L, lighting.ambient_light.getGreen());
lua_setfield(L, -2, "g");
lua_pushnumber(L, lighting.ambient_light.getBlue());
lua_setfield(L, -2, "b");
lua_pushnumber(L, 255);
lua_setfield(L, -2, "a");
lua_setfield(L, -2, "ambient_light");
lua_pushnumber(L, lighting.saturation);
lua_setfield(L, -2, "saturation");
lua_newtable(L); // "exposure"

View File

@ -1895,6 +1895,8 @@ void Server::SendSetLighting(session_t peer_id, const Lighting &lighting)
pkt << lighting.volumetric_light_strength;
pkt << lighting.ambient_light;
Send(&pkt);
}