uniform mat4 mWorld; // Color of the light emitted by the sun. uniform vec3 dayLight; uniform vec3 eyePosition; // The cameraOffset is the current center of the visible world. uniform vec3 cameraOffset; uniform float animationTimer; varying vec3 vNormal; varying vec3 vPosition; // World position in the visible world (i.e. relative to the cameraOffset.) // This can be used for many shader effects without loss of precision. // If the absolute position is required it can be calculated with // cameraOffset + worldPosition (for large coordinates the limits of float // precision must be considered). varying vec3 worldPosition; varying lowp vec4 varColor; // The centroid keyword ensures that after interpolation the texture coordinates // lie within the same bounds when MSAA is en- and disabled. // This fixes the stripes problem with nearest-neighbour textures and MSAA. #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); const float e = 2.718281828459; const float BS = 10.0; const float bias0 = 0.9; const float bias1 = 1.0 - bias0; #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 smoothCurve(float x) { return x * x * (3.0 - 2.0 * x); } float triangleWave(float x) { return abs(fract(x + 0.5) * 2.0 - 1.0); } float smoothTriangleWave(float x) { return smoothCurve(triangleWave(x)) * 2.0 - 1.0; } // OpenGL < 4.3 does not support continued preprocessor lines #if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_OPAQUE || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_BASIC) && ENABLE_WAVING_WATER // // Simple, fast noise function. // See: https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83 // vec4 perm(vec4 x) { return mod(((x * 34.0) + 1.0) * x, 289.0); } float snoise(vec3 p) { vec3 a = floor(p); vec3 d = p - a; d = d * d * (3.0 - 2.0 * d); vec4 b = a.xxyy + vec4(0.0, 1.0, 0.0, 1.0); vec4 k1 = perm(b.xyxy); vec4 k2 = perm(k1.xyxy + b.zzww); vec4 c = k2 + a.zzzz; vec4 k3 = perm(c); vec4 k4 = perm(c + 1.0); vec4 o1 = fract(k3 * (1.0 / 41.0)); vec4 o2 = fract(k4 * (1.0 / 41.0)); vec4 o3 = o2 * d.z + o1 * (1.0 - d.z); vec2 o4 = o3.yw * d.x + o3.xz * (1.0 - d.x); return o4.y * d.y + o4.x * (1.0 - d.y); } #endif void main(void) { varTexCoord = inTexCoord0.st; float disp_x; float disp_z; // OpenGL < 4.3 does not support continued preprocessor lines #if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES) || (MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS) vec4 pos2 = mWorld * inVertexPosition; float tOffset = (pos2.x + pos2.y) * 0.001 + pos2.z * 0.002; disp_x = (smoothTriangleWave(animationTimer * 23.0 + tOffset) + smoothTriangleWave(animationTimer * 11.0 + tOffset)) * 0.4; disp_z = (smoothTriangleWave(animationTimer * 31.0 + tOffset) + smoothTriangleWave(animationTimer * 29.0 + tOffset) + smoothTriangleWave(animationTimer * 13.0 + tOffset)) * 0.5; #endif worldPosition = (mWorld * inVertexPosition).xyz; // OpenGL < 4.3 does not support continued preprocessor lines #if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_OPAQUE || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_BASIC) && ENABLE_WAVING_WATER // Generate waves with Perlin-type noise. // The constants are calibrated such that they roughly // correspond to the old sine waves. vec4 pos = inVertexPosition; vec3 wavePos = worldPosition + cameraOffset; // The waves are slightly compressed along the z-axis to get // wave-fronts along the x-axis. wavePos.x /= WATER_WAVE_LENGTH * 3.0; wavePos.z /= WATER_WAVE_LENGTH * 2.0; wavePos.z += animationTimer * WATER_WAVE_SPEED * 10.0; pos.y += (snoise(wavePos) - 1.0) * WATER_WAVE_HEIGHT * 5.0; gl_Position = mWorldViewProj * pos; #elif MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES vec4 pos = inVertexPosition; pos.x += disp_x; pos.y += disp_z * 0.1; pos.z += disp_z; gl_Position = mWorldViewProj * pos; #elif MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS vec4 pos = inVertexPosition; if (varTexCoord.y < 0.05) { pos.x += disp_x; pos.z += disp_z; } gl_Position = mWorldViewProj * pos; #else gl_Position = mWorldViewProj * inVertexPosition; #endif vPosition = gl_Position.xyz; eyeVec = -(mWorldView * inVertexPosition).xyz; vNormal = inVertexNormal; // Calculate color. // Red, green and blue components are pre-multiplied with // the brightness, so now we have to multiply these // colors with the color of the incoming light. // The pre-baked colors are halved to prevent overflow. #ifdef GL_ES vec4 color = inVertexColor.bgra; #else vec4 color = inVertexColor; #endif // 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 * bias0 + bias1; float texelSize = f_shadowfar * perspectiveFactor * perspectiveFactor / (f_textureresolution * bias1 - perspectiveFactor * bias0); 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 }