forked from Mirrorlandia_minetest/minetest
31578303a4
* Pass perspective distortion parameters as uniforms * Set all perspective bias parameters via ShadowRenderer * Recalibrate perspective distortion and shadow range to render less shadow geometry with the same quality and observed shadow distance
140 lines
4.2 KiB
GLSL
140 lines
4.2 KiB
GLSL
uniform mat4 mWorld;
|
|
uniform vec3 dayLight;
|
|
uniform vec3 eyePosition;
|
|
uniform float animationTimer;
|
|
uniform vec4 emissiveColor;
|
|
uniform vec3 cameraOffset;
|
|
|
|
|
|
varying vec3 vNormal;
|
|
varying vec3 vPosition;
|
|
varying vec3 worldPosition;
|
|
varying lowp vec4 varColor;
|
|
#ifdef GL_ES
|
|
varying mediump vec2 varTexCoord;
|
|
#else
|
|
centroid varying vec2 varTexCoord;
|
|
#endif
|
|
|
|
#ifdef ENABLE_DYNAMIC_SHADOWS
|
|
// shadow uniforms
|
|
uniform vec3 v_LightDirection;
|
|
uniform float f_textureresolution;
|
|
uniform mat4 m_ShadowViewProj;
|
|
uniform float f_shadowfar;
|
|
uniform float f_shadow_strength;
|
|
uniform float f_timeofday;
|
|
varying float cosLight;
|
|
varying float normalOffsetScale;
|
|
varying float adj_shadow_strength;
|
|
varying float f_normal_length;
|
|
#endif
|
|
|
|
varying vec3 eyeVec;
|
|
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;
|
|
const float e = 2.718281828459;
|
|
const float BS = 10.0;
|
|
uniform float xyPerspectiveBias0;
|
|
uniform float xyPerspectiveBias1;
|
|
|
|
#ifdef ENABLE_DYNAMIC_SHADOWS
|
|
// custom smoothstep implementation because it's not defined in glsl1.2
|
|
// https://docs.gl/sl4/smoothstep
|
|
float mtsmoothstep(in float edge0, in float edge1, in float x)
|
|
{
|
|
float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
|
|
return t * t * (3.0 - 2.0 * t);
|
|
}
|
|
#endif
|
|
|
|
|
|
float directional_ambient(vec3 normal)
|
|
{
|
|
vec3 v = normal * normal;
|
|
|
|
if (normal.y < 0.0)
|
|
return dot(v, vec3(0.670820, 0.447213, 0.836660));
|
|
|
|
return dot(v, vec3(0.670820, 1.000000, 0.836660));
|
|
}
|
|
|
|
void main(void)
|
|
{
|
|
varTexCoord = (mTexture * inTexCoord0).st;
|
|
gl_Position = mWorldViewProj * inVertexPosition;
|
|
|
|
vPosition = gl_Position.xyz;
|
|
vNormal = (mWorld * vec4(inVertexNormal, 0.0)).xyz;
|
|
worldPosition = (mWorld * inVertexPosition).xyz;
|
|
eyeVec = -(mWorldView * inVertexPosition).xyz;
|
|
|
|
#if (MATERIAL_TYPE == TILE_MATERIAL_PLAIN) || (MATERIAL_TYPE == TILE_MATERIAL_PLAIN_ALPHA)
|
|
vIDiff = 1.0;
|
|
#else
|
|
// This is intentional comparison with zero without any margin.
|
|
// If normal is not equal to zero exactly, then we assume it's a valid, just not normalized vector
|
|
vIDiff = length(inVertexNormal) == 0.0
|
|
? 1.0
|
|
: directional_ambient(normalize(inVertexNormal));
|
|
#endif
|
|
|
|
#ifdef GL_ES
|
|
vec4 color = inVertexColor.bgra;
|
|
#else
|
|
vec4 color = inVertexColor;
|
|
#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
|
|
if (f_shadow_strength > 0.0) {
|
|
vec3 nNormal = normalize(vNormal);
|
|
cosLight = dot(nNormal, -v_LightDirection);
|
|
|
|
// Calculate normal offset scale based on the texel size adjusted for
|
|
// curvature of the SM texture. This code must be change together with
|
|
// getPerspectiveFactor or any light-space transformation.
|
|
vec3 eyeToVertex = worldPosition - eyePosition + cameraOffset;
|
|
// Distance from the vertex to the player
|
|
float distanceToPlayer = length(eyeToVertex - v_LightDirection * dot(eyeToVertex, v_LightDirection)) / f_shadowfar;
|
|
// perspective factor estimation according to the
|
|
float perspectiveFactor = distanceToPlayer * xyPerspectiveBias0 + xyPerspectiveBias1;
|
|
float texelSize = f_shadowfar * perspectiveFactor * perspectiveFactor /
|
|
(f_textureresolution * xyPerspectiveBias1 - perspectiveFactor * xyPerspectiveBias0);
|
|
float slopeScale = clamp(pow(1.0 - cosLight*cosLight, 0.5), 0.0, 1.0);
|
|
normalOffsetScale = texelSize * slopeScale;
|
|
|
|
if (f_timeofday < 0.2) {
|
|
adj_shadow_strength = f_shadow_strength * 0.5 *
|
|
(1.0 - mtsmoothstep(0.18, 0.2, f_timeofday));
|
|
} else if (f_timeofday >= 0.8) {
|
|
adj_shadow_strength = f_shadow_strength * 0.5 *
|
|
mtsmoothstep(0.8, 0.83, f_timeofday);
|
|
} else {
|
|
adj_shadow_strength = f_shadow_strength *
|
|
mtsmoothstep(0.20, 0.25, f_timeofday) *
|
|
(1.0 - mtsmoothstep(0.7, 0.8, f_timeofday));
|
|
}
|
|
f_normal_length = length(vNormal);
|
|
}
|
|
#endif
|
|
}
|