Add API to control shadow intensity from the game/mod (#11944)

* Also Disable shadows when sun/moon is hidden. Fixes #11972.
This commit is contained in:
x2048 2022-03-26 16:58:26 +01:00 committed by GitHub
parent 8d55702d13
commit 0f25fa7af6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 375 additions and 169 deletions

@ -592,9 +592,10 @@ enable_waving_plants (Waving plants) bool false
# Requires shaders to be enabled. # Requires shaders to be enabled.
enable_dynamic_shadows (Dynamic shadows) bool false enable_dynamic_shadows (Dynamic shadows) bool false
# Set the shadow strength. # Set the shadow strength gamma.
# Adjusts the intensity of in-game dynamic shadows.
# Lower value means lighter shadows, higher value means darker shadows. # Lower value means lighter shadows, higher value means darker shadows.
shadow_strength (Shadow strength) float 0.2 0.05 1.0 shadow_strength_gamma (Shadow strength gamma) float 1.0 0.1 10.0
# Maximum distance to render shadows. # Maximum distance to render shadows.
shadow_map_max_distance (Shadow map max distance in nodes to render shadows) float 120.0 10.0 1000.0 shadow_map_max_distance (Shadow map max distance in nodes to render shadows) float 120.0 10.0 1000.0

@ -16,6 +16,7 @@ uniform float animationTimer;
uniform float f_textureresolution; uniform float f_textureresolution;
uniform mat4 m_ShadowViewProj; uniform mat4 m_ShadowViewProj;
uniform float f_shadowfar; uniform float f_shadowfar;
uniform float f_shadow_strength;
varying float normalOffsetScale; varying float normalOffsetScale;
varying float adj_shadow_strength; varying float adj_shadow_strength;
varying float cosLight; varying float cosLight;
@ -483,6 +484,7 @@ void main(void)
vec4 col = vec4(color.rgb * varColor.rgb, 1.0); vec4 col = vec4(color.rgb * varColor.rgb, 1.0);
#ifdef ENABLE_DYNAMIC_SHADOWS #ifdef ENABLE_DYNAMIC_SHADOWS
if (f_shadow_strength > 0.0) {
float shadow_int = 0.0; float shadow_int = 0.0;
vec3 shadow_color = vec3(0.0, 0.0, 0.0); vec3 shadow_color = vec3(0.0, 0.0, 0.0);
vec3 posLightSpace = getLightSpacePosition(); vec3 posLightSpace = getLightSpacePosition();
@ -532,6 +534,7 @@ void main(void)
(1.0 - adjusted_night_ratio) * ( // natural light (1.0 - adjusted_night_ratio) * ( // natural light
col.rgb * (1.0 - shadow_int * (1.0 - shadow_color)) + // filtered texture color col.rgb * (1.0 - shadow_int * (1.0 - shadow_color)) + // filtered texture color
dayLight * shadow_color * shadow_int); // reflected filtered sunlight/moonlight dayLight * shadow_color * shadow_int); // reflected filtered sunlight/moonlight
}
#endif #endif
#if ENABLE_TONE_MAPPING #if ENABLE_TONE_MAPPING

@ -195,6 +195,7 @@ void main(void)
varColor = clamp(color, 0.0, 1.0); varColor = clamp(color, 0.0, 1.0);
#ifdef ENABLE_DYNAMIC_SHADOWS #ifdef ENABLE_DYNAMIC_SHADOWS
if (f_shadow_strength > 0.0) {
vec3 nNormal = normalize(vNormal); vec3 nNormal = normalize(vNormal);
cosLight = dot(nNormal, -v_LightDirection); cosLight = dot(nNormal, -v_LightDirection);
@ -223,6 +224,6 @@ void main(void)
(1.0 - mtsmoothstep(0.7, 0.8, f_timeofday)); (1.0 - mtsmoothstep(0.7, 0.8, f_timeofday));
} }
f_normal_length = length(vNormal); f_normal_length = length(vNormal);
#endif }
#endif
} }

@ -34,6 +34,8 @@ const float fogShadingParameter = 1.0 / (1.0 - fogStart);
uniform float f_textureresolution; uniform float f_textureresolution;
uniform mat4 m_ShadowViewProj; uniform mat4 m_ShadowViewProj;
uniform float f_shadowfar; uniform float f_shadowfar;
uniform float f_timeofday;
uniform float f_shadow_strength;
varying float normalOffsetScale; varying float normalOffsetScale;
varying float adj_shadow_strength; varying float adj_shadow_strength;
varying float cosLight; varying float cosLight;
@ -470,6 +472,7 @@ void main(void)
col.rgb *= vIDiff; col.rgb *= vIDiff;
#ifdef ENABLE_DYNAMIC_SHADOWS #ifdef ENABLE_DYNAMIC_SHADOWS
if (f_shadow_strength > 0.0) {
float shadow_int = 0.0; float shadow_int = 0.0;
vec3 shadow_color = vec3(0.0, 0.0, 0.0); vec3 shadow_color = vec3(0.0, 0.0, 0.0);
vec3 posLightSpace = getLightSpacePosition(); vec3 posLightSpace = getLightSpacePosition();
@ -519,6 +522,7 @@ void main(void)
(1.0 - adjusted_night_ratio) * ( // natural light (1.0 - adjusted_night_ratio) * ( // natural light
col.rgb * (1.0 - shadow_int * (1.0 - shadow_color)) + // filtered texture color col.rgb * (1.0 - shadow_int * (1.0 - shadow_color)) + // filtered texture color
dayLight * shadow_color * shadow_int); // reflected filtered sunlight/moonlight dayLight * shadow_color * shadow_int); // reflected filtered sunlight/moonlight
}
#endif #endif
#if ENABLE_TONE_MAPPING #if ENABLE_TONE_MAPPING

@ -105,6 +105,7 @@ void main(void)
#ifdef ENABLE_DYNAMIC_SHADOWS #ifdef ENABLE_DYNAMIC_SHADOWS
if (f_shadow_strength > 0.0) {
vec3 nNormal = normalize(vNormal); vec3 nNormal = normalize(vNormal);
cosLight = dot(nNormal, -v_LightDirection); cosLight = dot(nNormal, -v_LightDirection);
@ -133,5 +134,6 @@ void main(void)
(1.0 - mtsmoothstep(0.7, 0.8, f_timeofday)); (1.0 - mtsmoothstep(0.7, 0.8, f_timeofday));
} }
f_normal_length = length(vNormal); f_normal_length = length(vNormal);
}
#endif #endif
} }

@ -7019,6 +7019,13 @@ object you are working with still exists.
* Returns `false` if failed. * Returns `false` if failed.
* Resource intensive - use sparsely * Resource intensive - use sparsely
* To get blockpos, integer divide pos by 16 * To get blockpos, integer divide pos by 16
* `set_lighting(light_definition)`: sets lighting for the player
* `light_definition` is a table with the following optional fields:
* `shadows` is a table that controls ambient shadows
* `intensity` sets the intensity of the shadows from 0 (no shadows, default) to 1 (blackness)
* Returns true on success.
* `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`.
`PcgRandom` `PcgRandom`
----------- -----------

@ -7,6 +7,7 @@ experimental = {}
dofile(minetest.get_modpath("experimental").."/detached.lua") dofile(minetest.get_modpath("experimental").."/detached.lua")
dofile(minetest.get_modpath("experimental").."/items.lua") dofile(minetest.get_modpath("experimental").."/items.lua")
dofile(minetest.get_modpath("experimental").."/commands.lua") dofile(minetest.get_modpath("experimental").."/commands.lua")
dofile(minetest.get_modpath("experimental").."/lighting.lua")
function experimental.print_to_everything(msg) function experimental.print_to_everything(msg)
minetest.log("action", msg) minetest.log("action", msg)

@ -0,0 +1,8 @@
core.register_chatcommand("set_lighting", {
params = "shadow_intensity",
description = "Set lighting parameters.",
func = function(player_name, param)
local shadow_intensity = tonumber(param)
minetest.get_player_by_name(player_name):set_lighting({shadows = { intensity = shadow_intensity} })
end
})

@ -227,6 +227,7 @@ public:
void handleCommand_PlayerSpeed(NetworkPacket *pkt); void handleCommand_PlayerSpeed(NetworkPacket *pkt);
void handleCommand_MediaPush(NetworkPacket *pkt); void handleCommand_MediaPush(NetworkPacket *pkt);
void handleCommand_MinimapModes(NetworkPacket *pkt); void handleCommand_MinimapModes(NetworkPacket *pkt);
void handleCommand_SetLighting(NetworkPacket *pkt);
void ProcessData(NetworkPacket *pkt); void ProcessData(NetworkPacket *pkt);

@ -4037,7 +4037,12 @@ void Game::updateShadows()
float in_timeofday = fmod(runData.time_of_day_smooth, 1.0f); float in_timeofday = fmod(runData.time_of_day_smooth, 1.0f);
float timeoftheday = fmod(getWickedTimeOfDay(in_timeofday) + 0.75f, 0.5f) + 0.25f; float timeoftheday = getWickedTimeOfDay(in_timeofday);
bool is_day = timeoftheday > 0.25 && timeoftheday < 0.75;
bool is_shadow_visible = is_day ? sky->getSunVisible() : sky->getMoonVisible();
shadow->setShadowIntensity(is_shadow_visible ? client->getEnv().getLocalPlayer()->getLighting().shadow_intensity : 0.0f);
timeoftheday = fmod(timeoftheday + 0.75f, 0.5f) + 0.25f;
const float offset_constant = 10000.0f; const float offset_constant = 10000.0f;
v3f light(0.0f, 0.0f, -1.0f); v3f light(0.0f, 0.0f, -1.0f);

@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "environment.h" #include "environment.h"
#include "constants.h" #include "constants.h"
#include "settings.h" #include "settings.h"
#include "lighting.h"
#include <list> #include <list>
class Client; class Client;
@ -158,6 +159,8 @@ public:
added_velocity += vel; added_velocity += vel;
} }
inline Lighting& getLighting() { return m_lighting; }
private: private:
void accelerate(const v3f &target_speed, const f32 max_increase_H, void accelerate(const v3f &target_speed, const f32 max_increase_H,
const f32 max_increase_V, const bool use_pitch); const f32 max_increase_V, const bool use_pitch);
@ -209,4 +212,5 @@ private:
GenericCAO *m_cao = nullptr; GenericCAO *m_cao = nullptr;
Client *m_client; Client *m_client;
Lighting m_lighting;
}; };

@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/ */
#include <cstring> #include <cstring>
#include <cmath>
#include "client/shadows/dynamicshadowsrender.h" #include "client/shadows/dynamicshadowsrender.h"
#include "client/shadows/shadowsScreenQuad.h" #include "client/shadows/shadowsScreenQuad.h"
#include "client/shadows/shadowsshadercallbacks.h" #include "client/shadows/shadowsshadercallbacks.h"
@ -33,9 +34,13 @@ ShadowRenderer::ShadowRenderer(IrrlichtDevice *device, Client *client) :
m_device(device), m_smgr(device->getSceneManager()), m_device(device), m_smgr(device->getSceneManager()),
m_driver(device->getVideoDriver()), m_client(client), m_current_frame(0) m_driver(device->getVideoDriver()), m_client(client), m_current_frame(0)
{ {
m_shadows_supported = true; // assume shadows supported. We will check actual support in initialize
m_shadows_enabled = true; m_shadows_enabled = true;
m_shadow_strength = g_settings->getFloat("shadow_strength"); m_shadow_strength_gamma = g_settings->getFloat("shadow_strength_gamma");
if (std::isnan(m_shadow_strength_gamma))
m_shadow_strength_gamma = 1.0f;
m_shadow_strength_gamma = core::clamp(m_shadow_strength_gamma, 0.1f, 10.0f);
m_shadow_map_max_distance = g_settings->getFloat("shadow_map_max_distance"); m_shadow_map_max_distance = g_settings->getFloat("shadow_map_max_distance");
@ -49,6 +54,9 @@ ShadowRenderer::ShadowRenderer(IrrlichtDevice *device, Client *client) :
ShadowRenderer::~ShadowRenderer() ShadowRenderer::~ShadowRenderer()
{ {
// call to disable releases dynamically allocated resources
disable();
if (m_shadow_depth_cb) if (m_shadow_depth_cb)
delete m_shadow_depth_cb; delete m_shadow_depth_cb;
if (m_shadow_mix_cb) if (m_shadow_mix_cb)
@ -72,15 +80,25 @@ ShadowRenderer::~ShadowRenderer()
m_driver->removeTexture(shadowMapClientMapFuture); m_driver->removeTexture(shadowMapClientMapFuture);
} }
void ShadowRenderer::disable()
{
m_shadows_enabled = false;
if (shadowMapTextureFinal) {
m_driver->setRenderTarget(shadowMapTextureFinal, true, true,
video::SColor(255, 255, 255, 255));
m_driver->setRenderTarget(0, true, true);
}
}
void ShadowRenderer::initialize() void ShadowRenderer::initialize()
{ {
auto *gpu = m_driver->getGPUProgrammingServices(); auto *gpu = m_driver->getGPUProgrammingServices();
// we need glsl // we need glsl
if (m_shadows_enabled && gpu && m_driver->queryFeature(video::EVDF_ARB_GLSL)) { if (m_shadows_supported && gpu && m_driver->queryFeature(video::EVDF_ARB_GLSL)) {
createShaders(); createShaders();
} else { } else {
m_shadows_enabled = false; m_shadows_supported = false;
warningstream << "Shadows: GLSL Shader not supported on this system." warningstream << "Shadows: GLSL Shader not supported on this system."
<< std::endl; << std::endl;
@ -94,6 +112,8 @@ void ShadowRenderer::initialize()
m_texture_format_color = m_shadow_map_texture_32bit m_texture_format_color = m_shadow_map_texture_32bit
? video::ECOLOR_FORMAT::ECF_G32R32F ? video::ECOLOR_FORMAT::ECF_G32R32F
: video::ECOLOR_FORMAT::ECF_G16R16F; : video::ECOLOR_FORMAT::ECF_G16R16F;
m_shadows_enabled &= m_shadows_supported;
} }
@ -124,6 +144,16 @@ f32 ShadowRenderer::getMaxShadowFar() const
return 0.0f; return 0.0f;
} }
void ShadowRenderer::setShadowIntensity(float shadow_intensity)
{
m_shadow_strength = pow(shadow_intensity, 1.0f / m_shadow_strength_gamma);
if (m_shadow_strength > 1E-2)
enable();
else
disable();
}
void ShadowRenderer::addNodeToShadowList( void ShadowRenderer::addNodeToShadowList(
scene::ISceneNode *node, E_SHADOW_MODE shadowMode) scene::ISceneNode *node, E_SHADOW_MODE shadowMode)
{ {
@ -153,6 +183,7 @@ void ShadowRenderer::updateSMTextures()
shadowMapTextureDynamicObjects = getSMTexture( shadowMapTextureDynamicObjects = getSMTexture(
std::string("shadow_dynamic_") + itos(m_shadow_map_texture_size), std::string("shadow_dynamic_") + itos(m_shadow_map_texture_size),
m_texture_format, true); m_texture_format, true);
assert(shadowMapTextureDynamicObjects != nullptr);
} }
if (!shadowMapClientMap) { if (!shadowMapClientMap) {
@ -161,6 +192,7 @@ void ShadowRenderer::updateSMTextures()
std::string("shadow_clientmap_") + itos(m_shadow_map_texture_size), std::string("shadow_clientmap_") + itos(m_shadow_map_texture_size),
m_shadow_map_colored ? m_texture_format_color : m_texture_format, m_shadow_map_colored ? m_texture_format_color : m_texture_format,
true); true);
assert(shadowMapClientMap != nullptr);
} }
if (!shadowMapClientMapFuture && m_map_shadow_update_frames > 1) { if (!shadowMapClientMapFuture && m_map_shadow_update_frames > 1) {
@ -168,6 +200,7 @@ void ShadowRenderer::updateSMTextures()
std::string("shadow_clientmap_bb_") + itos(m_shadow_map_texture_size), std::string("shadow_clientmap_bb_") + itos(m_shadow_map_texture_size),
m_shadow_map_colored ? m_texture_format_color : m_texture_format, m_shadow_map_colored ? m_texture_format_color : m_texture_format,
true); true);
assert(shadowMapClientMapFuture != nullptr);
} }
if (m_shadow_map_colored && !shadowMapTextureColors) { if (m_shadow_map_colored && !shadowMapTextureColors) {
@ -175,6 +208,7 @@ void ShadowRenderer::updateSMTextures()
std::string("shadow_colored_") + itos(m_shadow_map_texture_size), std::string("shadow_colored_") + itos(m_shadow_map_texture_size),
m_shadow_map_colored ? m_texture_format_color : m_texture_format, m_shadow_map_colored ? m_texture_format_color : m_texture_format,
true); true);
assert(shadowMapTextureColors != nullptr);
} }
// The merge all shadowmaps texture // The merge all shadowmaps texture
@ -194,6 +228,7 @@ void ShadowRenderer::updateSMTextures()
shadowMapTextureFinal = getSMTexture( shadowMapTextureFinal = getSMTexture(
std::string("shadowmap_final_") + itos(m_shadow_map_texture_size), std::string("shadowmap_final_") + itos(m_shadow_map_texture_size),
frt, true); frt, true);
assert(shadowMapTextureFinal != nullptr);
} }
if (!m_shadow_node_array.empty() && !m_light_list.empty()) { if (!m_shadow_node_array.empty() && !m_light_list.empty()) {
@ -270,6 +305,10 @@ void ShadowRenderer::update(video::ITexture *outputTarget)
updateSMTextures(); updateSMTextures();
if (shadowMapTextureFinal == nullptr) {
return;
}
if (!m_shadow_node_array.empty() && !m_light_list.empty()) { if (!m_shadow_node_array.empty() && !m_light_list.empty()) {
for (DirectionalLight &light : m_light_list) { for (DirectionalLight &light : m_light_list) {
@ -307,19 +346,23 @@ void ShadowRenderer::drawDebug()
/* this code just shows shadows textures in screen and in ONLY for debugging*/ /* this code just shows shadows textures in screen and in ONLY for debugging*/
#if 0 #if 0
// this is debug, ignore for now. // this is debug, ignore for now.
if (shadowMapTextureFinal)
m_driver->draw2DImage(shadowMapTextureFinal, m_driver->draw2DImage(shadowMapTextureFinal,
core::rect<s32>(0, 50, 128, 128 + 50), core::rect<s32>(0, 50, 128, 128 + 50),
core::rect<s32>({0, 0}, shadowMapTextureFinal->getSize())); core::rect<s32>({0, 0}, shadowMapTextureFinal->getSize()));
if (shadowMapClientMap)
m_driver->draw2DImage(shadowMapClientMap, m_driver->draw2DImage(shadowMapClientMap,
core::rect<s32>(0, 50 + 128, 128, 128 + 50 + 128), core::rect<s32>(0, 50 + 128, 128, 128 + 50 + 128),
core::rect<s32>({0, 0}, shadowMapTextureFinal->getSize())); core::rect<s32>({0, 0}, shadowMapTextureFinal->getSize()));
if (shadowMapTextureDynamicObjects)
m_driver->draw2DImage(shadowMapTextureDynamicObjects, m_driver->draw2DImage(shadowMapTextureDynamicObjects,
core::rect<s32>(0, 128 + 50 + 128, 128, core::rect<s32>(0, 128 + 50 + 128, 128,
128 + 50 + 128 + 128), 128 + 50 + 128 + 128),
core::rect<s32>({0, 0}, shadowMapTextureDynamicObjects->getSize())); core::rect<s32>({0, 0}, shadowMapTextureDynamicObjects->getSize()));
if (m_shadow_map_colored) { if (m_shadow_map_colored && shadowMapTextureColors) {
m_driver->draw2DImage(shadowMapTextureColors, m_driver->draw2DImage(shadowMapTextureColors,
core::rect<s32>(128,128 + 50 + 128 + 128, core::rect<s32>(128,128 + 50 + 128 + 128,
@ -469,13 +512,13 @@ void ShadowRenderer::createShaders()
if (depth_shader == -1) { if (depth_shader == -1) {
std::string depth_shader_vs = getShaderPath("shadow_shaders", "pass1_vertex.glsl"); std::string depth_shader_vs = getShaderPath("shadow_shaders", "pass1_vertex.glsl");
if (depth_shader_vs.empty()) { if (depth_shader_vs.empty()) {
m_shadows_enabled = false; m_shadows_supported = false;
errorstream << "Error shadow mapping vs shader not found." << std::endl; errorstream << "Error shadow mapping vs shader not found." << std::endl;
return; return;
} }
std::string depth_shader_fs = getShaderPath("shadow_shaders", "pass1_fragment.glsl"); std::string depth_shader_fs = getShaderPath("shadow_shaders", "pass1_fragment.glsl");
if (depth_shader_fs.empty()) { if (depth_shader_fs.empty()) {
m_shadows_enabled = false; m_shadows_supported = false;
errorstream << "Error shadow mapping fs shader not found." << std::endl; errorstream << "Error shadow mapping fs shader not found." << std::endl;
return; return;
} }
@ -490,7 +533,7 @@ void ShadowRenderer::createShaders()
if (depth_shader == -1) { if (depth_shader == -1) {
// upsi, something went wrong loading shader. // upsi, something went wrong loading shader.
delete m_shadow_depth_cb; delete m_shadow_depth_cb;
m_shadows_enabled = false; m_shadows_supported = false;
errorstream << "Error compiling shadow mapping shader." << std::endl; errorstream << "Error compiling shadow mapping shader." << std::endl;
return; return;
} }
@ -506,13 +549,13 @@ void ShadowRenderer::createShaders()
if (depth_shader_entities == -1) { if (depth_shader_entities == -1) {
std::string depth_shader_vs = getShaderPath("shadow_shaders", "pass1_vertex.glsl"); std::string depth_shader_vs = getShaderPath("shadow_shaders", "pass1_vertex.glsl");
if (depth_shader_vs.empty()) { if (depth_shader_vs.empty()) {
m_shadows_enabled = false; m_shadows_supported = false;
errorstream << "Error shadow mapping vs shader not found." << std::endl; errorstream << "Error shadow mapping vs shader not found." << std::endl;
return; return;
} }
std::string depth_shader_fs = getShaderPath("shadow_shaders", "pass1_fragment.glsl"); std::string depth_shader_fs = getShaderPath("shadow_shaders", "pass1_fragment.glsl");
if (depth_shader_fs.empty()) { if (depth_shader_fs.empty()) {
m_shadows_enabled = false; m_shadows_supported = false;
errorstream << "Error shadow mapping fs shader not found." << std::endl; errorstream << "Error shadow mapping fs shader not found." << std::endl;
return; return;
} }
@ -525,7 +568,7 @@ void ShadowRenderer::createShaders()
if (depth_shader_entities == -1) { if (depth_shader_entities == -1) {
// upsi, something went wrong loading shader. // upsi, something went wrong loading shader.
m_shadows_enabled = false; m_shadows_supported = false;
errorstream << "Error compiling shadow mapping shader (dynamic)." << std::endl; errorstream << "Error compiling shadow mapping shader (dynamic)." << std::endl;
return; return;
} }
@ -539,14 +582,14 @@ void ShadowRenderer::createShaders()
if (mixcsm_shader == -1) { if (mixcsm_shader == -1) {
std::string depth_shader_vs = getShaderPath("shadow_shaders", "pass2_vertex.glsl"); std::string depth_shader_vs = getShaderPath("shadow_shaders", "pass2_vertex.glsl");
if (depth_shader_vs.empty()) { if (depth_shader_vs.empty()) {
m_shadows_enabled = false; m_shadows_supported = false;
errorstream << "Error cascade shadow mapping fs shader not found." << std::endl; errorstream << "Error cascade shadow mapping fs shader not found." << std::endl;
return; return;
} }
std::string depth_shader_fs = getShaderPath("shadow_shaders", "pass2_fragment.glsl"); std::string depth_shader_fs = getShaderPath("shadow_shaders", "pass2_fragment.glsl");
if (depth_shader_fs.empty()) { if (depth_shader_fs.empty()) {
m_shadows_enabled = false; m_shadows_supported = false;
errorstream << "Error cascade shadow mapping fs shader not found." << std::endl; errorstream << "Error cascade shadow mapping fs shader not found." << std::endl;
return; return;
} }
@ -565,7 +608,7 @@ void ShadowRenderer::createShaders()
// upsi, something went wrong loading shader. // upsi, something went wrong loading shader.
delete m_shadow_mix_cb; delete m_shadow_mix_cb;
delete m_screen_quad; delete m_screen_quad;
m_shadows_enabled = false; m_shadows_supported = false;
errorstream << "Error compiling cascade shadow mapping shader." << std::endl; errorstream << "Error compiling cascade shadow mapping shader." << std::endl;
return; return;
} }
@ -579,13 +622,13 @@ void ShadowRenderer::createShaders()
if (m_shadow_map_colored && depth_shader_trans == -1) { if (m_shadow_map_colored && depth_shader_trans == -1) {
std::string depth_shader_vs = getShaderPath("shadow_shaders", "pass1_trans_vertex.glsl"); std::string depth_shader_vs = getShaderPath("shadow_shaders", "pass1_trans_vertex.glsl");
if (depth_shader_vs.empty()) { if (depth_shader_vs.empty()) {
m_shadows_enabled = false; m_shadows_supported = false;
errorstream << "Error shadow mapping vs shader not found." << std::endl; errorstream << "Error shadow mapping vs shader not found." << std::endl;
return; return;
} }
std::string depth_shader_fs = getShaderPath("shadow_shaders", "pass1_trans_fragment.glsl"); std::string depth_shader_fs = getShaderPath("shadow_shaders", "pass1_trans_fragment.glsl");
if (depth_shader_fs.empty()) { if (depth_shader_fs.empty()) {
m_shadows_enabled = false; m_shadows_supported = false;
errorstream << "Error shadow mapping fs shader not found." << std::endl; errorstream << "Error shadow mapping fs shader not found." << std::endl;
return; return;
} }
@ -601,7 +644,7 @@ void ShadowRenderer::createShaders()
// upsi, something went wrong loading shader. // upsi, something went wrong loading shader.
delete m_shadow_depth_trans_cb; delete m_shadow_depth_trans_cb;
m_shadow_map_colored = false; m_shadow_map_colored = false;
m_shadows_enabled = false; m_shadows_supported = false;
errorstream << "Error compiling colored shadow mapping shader." << std::endl; errorstream << "Error compiling colored shadow mapping shader." << std::endl;
return; return;
} }

@ -82,11 +82,12 @@ public:
} }
bool is_active() const { return m_shadows_enabled; } bool is_active() const { return m_shadows_enabled && shadowMapTextureFinal != nullptr; }
void setTimeOfDay(float isDay) { m_time_day = isDay; }; void setTimeOfDay(float isDay) { m_time_day = isDay; };
void setShadowIntensity(float shadow_intensity);
s32 getShadowSamples() const { return m_shadow_samples; } s32 getShadowSamples() const { return m_shadow_samples; }
float getShadowStrength() const { return m_shadow_strength; } float getShadowStrength() const { return m_shadows_enabled ? m_shadow_strength : 0.0f; }
float getTimeOfDay() const { return m_time_day; } float getTimeOfDay() const { return m_time_day; }
private: private:
@ -101,6 +102,9 @@ private:
void mixShadowsQuad(); void mixShadowsQuad();
void updateSMTextures(); void updateSMTextures();
void disable();
void enable() { m_shadows_enabled = m_shadows_supported; }
// a bunch of variables // a bunch of variables
IrrlichtDevice *m_device{nullptr}; IrrlichtDevice *m_device{nullptr};
scene::ISceneManager *m_smgr{nullptr}; scene::ISceneManager *m_smgr{nullptr};
@ -116,12 +120,14 @@ private:
std::vector<NodeToApply> m_shadow_node_array; std::vector<NodeToApply> m_shadow_node_array;
float m_shadow_strength; float m_shadow_strength;
float m_shadow_strength_gamma;
float m_shadow_map_max_distance; float m_shadow_map_max_distance;
float m_shadow_map_texture_size; float m_shadow_map_texture_size;
float m_time_day{0.0f}; float m_time_day{0.0f};
int m_shadow_samples; int m_shadow_samples;
bool m_shadow_map_texture_32bit; bool m_shadow_map_texture_32bit;
bool m_shadows_enabled; bool m_shadows_enabled;
bool m_shadows_supported;
bool m_shadow_map_colored; bool m_shadow_map_colored;
u8 m_map_shadow_update_frames; /* Use this number of frames to update map shaodw */ u8 m_map_shadow_update_frames; /* Use this number of frames to update map shaodw */
u8 m_current_frame{0}; /* Current frame */ u8 m_current_frame{0}; /* Current frame */

@ -65,6 +65,7 @@ public:
} }
void setSunVisible(bool sun_visible) { m_sun_params.visible = sun_visible; } void setSunVisible(bool sun_visible) { m_sun_params.visible = sun_visible; }
bool getSunVisible() const { return m_sun_params.visible; }
void setSunTexture(const std::string &sun_texture, void setSunTexture(const std::string &sun_texture,
const std::string &sun_tonemap, ITextureSource *tsrc); const std::string &sun_tonemap, ITextureSource *tsrc);
void setSunScale(f32 sun_scale) { m_sun_params.scale = sun_scale; } void setSunScale(f32 sun_scale) { m_sun_params.scale = sun_scale; }
@ -72,6 +73,7 @@ public:
void setSunriseTexture(const std::string &sunglow_texture, ITextureSource* tsrc); void setSunriseTexture(const std::string &sunglow_texture, ITextureSource* tsrc);
void setMoonVisible(bool moon_visible) { m_moon_params.visible = moon_visible; } void setMoonVisible(bool moon_visible) { m_moon_params.visible = moon_visible; }
bool getMoonVisible() const { return m_moon_params.visible; }
void setMoonTexture(const std::string &moon_texture, void setMoonTexture(const std::string &moon_texture,
const std::string &moon_tonemap, ITextureSource *tsrc); const std::string &moon_tonemap, ITextureSource *tsrc);
void setMoonScale(f32 moon_scale) { m_moon_params.scale = moon_scale; } void setMoonScale(f32 moon_scale) { m_moon_params.scale = moon_scale; }

@ -266,7 +266,7 @@ void set_default_settings()
// Effects Shadows // Effects Shadows
settings->setDefault("enable_dynamic_shadows", "false"); settings->setDefault("enable_dynamic_shadows", "false");
settings->setDefault("shadow_strength", "0.2"); settings->setDefault("shadow_strength_gamma", "1.0");
settings->setDefault("shadow_map_max_distance", "200.0"); settings->setDefault("shadow_map_max_distance", "200.0");
settings->setDefault("shadow_map_texture_size", "2048"); settings->setDefault("shadow_map_texture_size", "2048");
settings->setDefault("shadow_map_texture_32bit", "true"); settings->setDefault("shadow_map_texture_32bit", "true");

27
src/lighting.h Normal file

@ -0,0 +1,27 @@
/*
Minetest
Copyright (C) 2021 x2048, Dmitry Kostenko <codeforsmile@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.
*/
#pragma once
/** Describes ambient light settings for a player
*/
struct Lighting
{
float shadow_intensity {0.0f};
};

@ -123,6 +123,7 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] =
{ "TOCLIENT_SRP_BYTES_S_B", TOCLIENT_STATE_NOT_CONNECTED, &Client::handleCommand_SrpBytesSandB }, // 0x60 { "TOCLIENT_SRP_BYTES_S_B", TOCLIENT_STATE_NOT_CONNECTED, &Client::handleCommand_SrpBytesSandB }, // 0x60
{ "TOCLIENT_FORMSPEC_PREPEND", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_FormspecPrepend }, // 0x61, { "TOCLIENT_FORMSPEC_PREPEND", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_FormspecPrepend }, // 0x61,
{ "TOCLIENT_MINIMAP_MODES", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_MinimapModes }, // 0x62, { "TOCLIENT_MINIMAP_MODES", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_MinimapModes }, // 0x62,
{ "TOCLIENT_SET_LIGHTING", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_SetLighting }, // 0x63,
}; };
const static ServerCommandFactory null_command_factory = { "TOSERVER_NULL", 0, false }; const static ServerCommandFactory null_command_factory = { "TOSERVER_NULL", 0, false };

@ -1682,3 +1682,11 @@ void Client::handleCommand_MinimapModes(NetworkPacket *pkt)
if (m_minimap) if (m_minimap)
m_minimap->setModeIndex(mode); m_minimap->setModeIndex(mode);
} }
void Client::handleCommand_SetLighting(NetworkPacket *pkt)
{
Lighting& lighting = m_env.getLocalPlayer()->getLighting();
if (pkt->getRemainingBytes() >= 4)
*pkt >> lighting.shadow_intensity;
}

@ -762,7 +762,12 @@ enum ToClientCommand
std::string extra std::string extra
*/ */
TOCLIENT_NUM_MSG_TYPES = 0x63, TOCLIENT_SET_LIGHTING = 0x63,
/*
f32 shadow_intensity
*/
TOCLIENT_NUM_MSG_TYPES = 0x64,
}; };
enum ToServerCommand enum ToServerCommand

@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "player.h" #include "player.h"
#include "skyparams.h" #include "skyparams.h"
#include "lighting.h"
class PlayerSAO; class PlayerSAO;
@ -125,6 +126,10 @@ public:
*frame_speed = local_animation_speed; *frame_speed = local_animation_speed;
} }
void setLighting(const Lighting &lighting) { m_lighting = lighting; }
const Lighting& getLighting() const { return m_lighting; }
void setDirty(bool dirty) { m_dirty = true; } void setDirty(bool dirty) { m_dirty = true; }
u16 protocol_version = 0; u16 protocol_version = 0;
@ -160,5 +165,7 @@ private:
MoonParams m_moon_params; MoonParams m_moon_params;
StarParams m_star_params; StarParams m_star_params;
Lighting m_lighting;
session_t m_peer_id = PEER_ID_INEXISTENT; session_t m_peer_id = PEER_ID_INEXISTENT;
}; };

@ -2295,6 +2295,47 @@ int ObjectRef::l_set_minimap_modes(lua_State *L)
return 0; return 0;
} }
// set_lighting(self, lighting)
int ObjectRef::l_set_lighting(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
RemotePlayer *player = getplayer(ref);
if (player == nullptr)
return 0;
luaL_checktype(L, 2, LUA_TTABLE);
Lighting lighting = player->getLighting();
lua_getfield(L, 2, "shadows");
if (lua_istable(L, -1)) {
lighting.shadow_intensity = getfloatfield_default(L, -1, "intensity", lighting.shadow_intensity);
}
lua_pop(L, -1);
getServer(L)->setLighting(player, lighting);
lua_pushboolean(L, true);
return 1;
}
// get_lighting(self)
int ObjectRef::l_get_lighting(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
RemotePlayer *player = getplayer(ref);
if (player == nullptr)
return 0;
const Lighting &lighting = player->getLighting();
lua_newtable(L); // result
lua_newtable(L); // "shadows"
lua_pushnumber(L, lighting.shadow_intensity);
lua_setfield(L, -2, "intensity");
lua_setfield(L, -2, "shadows");
return 1;
}
ObjectRef::ObjectRef(ServerActiveObject *object): ObjectRef::ObjectRef(ServerActiveObject *object):
m_object(object) m_object(object)
{} {}
@ -2448,5 +2489,7 @@ luaL_Reg ObjectRef::methods[] = {
luamethod(ObjectRef, get_eye_offset), luamethod(ObjectRef, get_eye_offset),
luamethod(ObjectRef, send_mapblock), luamethod(ObjectRef, send_mapblock),
luamethod(ObjectRef, set_minimap_modes), luamethod(ObjectRef, set_minimap_modes),
luamethod(ObjectRef, set_lighting),
luamethod(ObjectRef, get_lighting),
{0,0} {0,0}
}; };

@ -376,4 +376,10 @@ private:
// set_minimap_modes(self, modes, wanted_mode) // set_minimap_modes(self, modes, wanted_mode)
static int l_set_minimap_modes(lua_State *L); static int l_set_minimap_modes(lua_State *L);
// set_lighting(self, lighting)
static int l_set_lighting(lua_State *L);
// get_lighting(self)
static int l_get_lighting(lua_State *L);
}; };

@ -1795,6 +1795,16 @@ void Server::SendOverrideDayNightRatio(session_t peer_id, bool do_override,
Send(&pkt); Send(&pkt);
} }
void Server::SendSetLighting(session_t peer_id, const Lighting &lighting)
{
NetworkPacket pkt(TOCLIENT_SET_LIGHTING,
4, peer_id);
pkt << lighting.shadow_intensity;
Send(&pkt);
}
void Server::SendTimeOfDay(session_t peer_id, u16 time, f32 time_speed) void Server::SendTimeOfDay(session_t peer_id, u16 time, f32 time_speed)
{ {
NetworkPacket pkt(TOCLIENT_TIME_OF_DAY, 0, peer_id); NetworkPacket pkt(TOCLIENT_TIME_OF_DAY, 0, peer_id);
@ -3386,6 +3396,13 @@ void Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
SendOverrideDayNightRatio(player->getPeerId(), do_override, ratio); SendOverrideDayNightRatio(player->getPeerId(), do_override, ratio);
} }
void Server::setLighting(RemotePlayer *player, const Lighting &lighting)
{
sanity_check(player);
player->setLighting(lighting);
SendSetLighting(player->getPeerId(), lighting);
}
void Server::notifyPlayers(const std::wstring &msg) void Server::notifyPlayers(const std::wstring &msg)
{ {
SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(msg)); SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(msg));

@ -69,6 +69,7 @@ struct SkyboxParams;
struct SunParams; struct SunParams;
struct MoonParams; struct MoonParams;
struct StarParams; struct StarParams;
struct Lighting;
class ServerThread; class ServerThread;
class ServerModManager; class ServerModManager;
class ServerInventoryManager; class ServerInventoryManager;
@ -333,6 +334,8 @@ public:
void overrideDayNightRatio(RemotePlayer *player, bool do_override, float brightness); void overrideDayNightRatio(RemotePlayer *player, bool do_override, float brightness);
void setLighting(RemotePlayer *player, const Lighting &lighting);
/* con::PeerHandler implementation. */ /* con::PeerHandler implementation. */
void peerAdded(con::Peer *peer); void peerAdded(con::Peer *peer);
void deletingPeer(con::Peer *peer, bool timeout); void deletingPeer(con::Peer *peer, bool timeout);
@ -459,6 +462,7 @@ private:
void SendSetStars(session_t peer_id, const StarParams &params); void SendSetStars(session_t peer_id, const StarParams &params);
void SendCloudParams(session_t peer_id, const CloudParams &params); void SendCloudParams(session_t peer_id, const CloudParams &params);
void SendOverrideDayNightRatio(session_t peer_id, bool do_override, float ratio); void SendOverrideDayNightRatio(session_t peer_id, bool do_override, float ratio);
void SendSetLighting(session_t peer_id, const Lighting &lighting);
void broadcastModChannelMessage(const std::string &channel, void broadcastModChannelMessage(const std::string &channel,
const std::string &message, session_t from_peer); const std::string &message, session_t from_peer);