Improve lighting of entities.

Pass correct natural & artificial light to the shaders
Use natural/artificial light ratio for correct rendering of shadows
This commit is contained in:
Dmitry Kostenko 2021-11-04 03:03:10 +01:00 committed by x2048
parent f2cccf8da7
commit 54dccc480e
5 changed files with 50 additions and 25 deletions

@ -471,7 +471,7 @@ void main(void)
color = base.rgb; color = base.rgb;
vec4 col = vec4(color.rgb, base.a); vec4 col = vec4(color.rgb, base.a);
col.rgb *= varColor.rgb; col.rgb *= varColor.rgb;
col.rgb *= emissiveColor.rgb * vIDiff; col.rgb *= vIDiff;
#ifdef ENABLE_DYNAMIC_SHADOWS #ifdef ENABLE_DYNAMIC_SHADOWS
float shadow_int = 0.0; float shadow_int = 0.0;

@ -1,7 +1,9 @@
uniform mat4 mWorld; uniform mat4 mWorld;
uniform vec3 dayLight;
uniform vec3 eyePosition; uniform vec3 eyePosition;
uniform float animationTimer; uniform float animationTimer;
uniform vec4 emissiveColor;
varying vec3 vNormal; varying vec3 vNormal;
varying vec3 vPosition; varying vec3 vPosition;
@ -29,9 +31,9 @@ centroid varying vec2 varTexCoord;
varying vec3 eyeVec; varying vec3 eyeVec;
varying float nightRatio; varying float nightRatio;
// Color of the light emitted by the light sources.
const vec3 artificialLight = vec3(1.04, 1.04, 1.04);
varying float vIDiff; varying float vIDiff;
const float e = 2.718281828459; const float e = 2.718281828459;
const float BS = 10.0; const float BS = 10.0;
@ -75,14 +77,30 @@ void main(void)
? 1.0 ? 1.0
: directional_ambient(normalize(inVertexNormal)); : directional_ambient(normalize(inVertexNormal));
#endif #endif
nightRatio = 0.0;
#ifdef GL_ES #ifdef GL_ES
varColor = inVertexColor.bgra; vec4 color = inVertexColor.bgra;
#else #else
varColor = inVertexColor; vec4 color = inVertexColor;
#endif #endif
color *= emissiveColor;
// The alpha gives the ratio of sunlight in the incoming light.
nightRatio = 1.0 - color.a;
color.rgb = color.rgb * (color.a * dayLight.rgb +
nightRatio * artificialLight.rgb) * 2.0;
color.a = 1.0;
// Emphase blue a bit in darker places
// See C++ implementation in mapblock_mesh.cpp final_color_blend()
float brightness = (color.r + color.g + color.b) / 3.0;
color.b += max(0.0, 0.021 - abs(0.2 * brightness - 0.021) +
0.07 * brightness);
varColor = clamp(color, 0.0, 1.0);
#ifdef ENABLE_DYNAMIC_SHADOWS #ifdef ENABLE_DYNAMIC_SHADOWS
vec3 nNormal = normalize(vNormal); vec3 nNormal = normalize(vNormal);
cosLight = dot(nNormal, -v_LightDirection); cosLight = dot(nNormal, -v_LightDirection);

@ -864,7 +864,8 @@ void GenericCAO::updateLight(u32 day_night_ratio)
if (m_glow < 0) if (m_glow < 0)
return; return;
u8 light_at_pos = 0; u16 light_at_pos = 0;
u8 light_at_pos_intensity = 0;
bool pos_ok = false; bool pos_ok = false;
v3s16 pos[3]; v3s16 pos[3];
@ -873,28 +874,33 @@ void GenericCAO::updateLight(u32 day_night_ratio)
bool this_ok; bool this_ok;
MapNode n = m_env->getMap().getNode(pos[i], &this_ok); MapNode n = m_env->getMap().getNode(pos[i], &this_ok);
if (this_ok) { if (this_ok) {
u8 this_light = n.getLightBlend(day_night_ratio, m_client->ndef()); u16 this_light = getInteriorLight(n, 0, m_client->ndef());
light_at_pos = MYMAX(light_at_pos, this_light); u8 this_light_intensity = MYMAX(this_light & 0xFF, (this_light >> 8) && 0xFF);
if (this_light_intensity > light_at_pos_intensity) {
light_at_pos = this_light;
light_at_pos_intensity = this_light_intensity;
}
pos_ok = true; pos_ok = true;
} }
} }
if (!pos_ok) if (!pos_ok)
light_at_pos = blend_light(day_night_ratio, LIGHT_SUN, 0); light_at_pos = LIGHT_SUN;
video::SColor light = encode_light(light_at_pos, m_glow);
if (!m_enable_shaders)
final_color_blend(&light, light_at_pos, day_night_ratio);
u8 light = decode_light(light_at_pos + m_glow);
if (light != m_last_light) { if (light != m_last_light) {
m_last_light = light; m_last_light = light;
setNodeLight(light); setNodeLight(light);
} }
} }
void GenericCAO::setNodeLight(u8 light) void GenericCAO::setNodeLight(const video::SColor &light_color)
{ {
video::SColor color(255, light, light, light);
if (m_prop.visual == "wielditem" || m_prop.visual == "item") { if (m_prop.visual == "wielditem" || m_prop.visual == "item") {
if (m_wield_meshnode) if (m_wield_meshnode)
m_wield_meshnode->setNodeLightColor(color); m_wield_meshnode->setNodeLightColor(light_color);
return; return;
} }
@ -906,7 +912,7 @@ void GenericCAO::setNodeLight(u8 light)
scene::IMesh *mesh = m_meshnode->getMesh(); scene::IMesh *mesh = m_meshnode->getMesh();
for (u32 i = 0; i < mesh->getMeshBufferCount(); ++i) { for (u32 i = 0; i < mesh->getMeshBufferCount(); ++i) {
scene::IMeshBuffer *buf = mesh->getMeshBuffer(i); scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
buf->getMaterial().EmissiveColor = color; buf->getMaterial().EmissiveColor = light_color;
} }
} else { } else {
scene::ISceneNode *node = getSceneNode(); scene::ISceneNode *node = getSceneNode();
@ -915,16 +921,16 @@ void GenericCAO::setNodeLight(u8 light)
for (u32 i = 0; i < node->getMaterialCount(); ++i) { for (u32 i = 0; i < node->getMaterialCount(); ++i) {
video::SMaterial &material = node->getMaterial(i); video::SMaterial &material = node->getMaterial(i);
material.EmissiveColor = color; material.EmissiveColor = light_color;
} }
} }
} else { } else {
if (m_meshnode) { if (m_meshnode) {
setMeshColor(m_meshnode->getMesh(), color); setMeshColor(m_meshnode->getMesh(), light_color);
} else if (m_animated_meshnode) { } else if (m_animated_meshnode) {
setAnimatedMeshColor(m_animated_meshnode, color); setAnimatedMeshColor(m_animated_meshnode, light_color);
} else if (m_spritenode) { } else if (m_spritenode) {
m_spritenode->setColor(color); m_spritenode->setColor(light_color);
} }
} }
} }

@ -125,7 +125,7 @@ private:
std::string m_current_texture_modifier = ""; std::string m_current_texture_modifier = "";
bool m_visuals_expired = false; bool m_visuals_expired = false;
float m_step_distance_counter = 0.0f; float m_step_distance_counter = 0.0f;
u8 m_last_light = 255; video::SColor m_last_light = video::SColor(0xFFFFFFFF);
bool m_is_visible = false; bool m_is_visible = false;
s8 m_glow = 0; s8 m_glow = 0;
// Material // Material
@ -245,7 +245,7 @@ public:
void updateLight(u32 day_night_ratio); void updateLight(u32 day_night_ratio);
void setNodeLight(u8 light); void setNodeLight(const video::SColor &light);
/* Get light position(s). /* Get light position(s).
* returns number of positions written into pos[], which must have space * returns number of positions written into pos[], which must have space

@ -515,9 +515,10 @@ void WieldMeshSceneNode::setNodeLightColor(video::SColor color)
material.EmissiveColor = color; material.EmissiveColor = color;
} }
} }
else {
setColor(color); setColor(color);
} }
}
void WieldMeshSceneNode::render() void WieldMeshSceneNode::render()
{ {