precision mediump float; varying vec4 clipSpace; uniform sampler2D reflectionTexture; uniform sampler2D refractionTexture; uniform sampler2D dudvMap; uniform sampler2D normalMap; uniform sampler2D depthMap; uniform float uReflectivity; uniform vec4 uTint; uniform float uDUDVOffset; uniform vec3 uLightColor; varying vec2 uv; varying vec3 toCameraVector; varying vec3 fromLightVector; const float waterDistortionStrength = 0.02; const float shineDamper = 20.0; const float reflectivity = 0.6; const float near = 0.1; const float far = 10000.0; void main() { vec2 ndc = (clipSpace.xy / clipSpace.w) / 2.0 + 0.5; vec2 refractTexCoords = vec2(ndc.x, ndc.y); vec2 reflectTexCoords = vec2(ndc.x, -ndc.y); float depth = 2.0 * texture2D(depthMap, refractTexCoords).r - 1.0; float floorDistance = 2.0 * near * far / (far + near - depth * (far - near)); depth = 2.0 * gl_FragCoord.z - 1.0; float waterDistance = 2.0 * near * far / (far + near - depth * (far - near)); float waterDepth = floorDistance - waterDistance; vec2 distortedTexCoords = texture2D(dudvMap, vec2(uv.x + uDUDVOffset, uv.y)).rg * 0.1; distortedTexCoords = uv + vec2(distortedTexCoords.x, distortedTexCoords.y + uDUDVOffset); // Between -1 and 1 vec2 totalDistortion = (texture2D(dudvMap, distortedTexCoords).rg * 2.0 - 1.0) * waterDistortionStrength; refractTexCoords += totalDistortion; reflectTexCoords += totalDistortion; refractTexCoords = clamp(refractTexCoords, 0.001, 0.999); reflectTexCoords.x = clamp(reflectTexCoords.x, 0.001, 0.999); reflectTexCoords.y = clamp(reflectTexCoords.y, -0.999, -0.001); reflectTexCoords.y = 1.0 + reflectTexCoords.y; vec4 reflectColor = texture2D(reflectionTexture, reflectTexCoords); vec4 refractColor = texture2D(refractionTexture, refractTexCoords); vec3 viewVector = normalize(toCameraVector); float refractiveFactor = dot(viewVector, vec3(0.0, 1.0, 0.0)); refractiveFactor = pow(refractiveFactor, uReflectivity); vec4 normalMapColor = texture2D(normalMap, distortedTexCoords); vec3 normal = vec3(normalMapColor.r * 2.0 - 1.0, normalMapColor.b, normalMapColor.g * 2.0 - 1.0); normal = normalize(normal); vec3 reflectedLight = reflect(normalize(fromLightVector), normal); float specular = max(dot(reflectedLight, viewVector), 0.0); specular = pow(specular, shineDamper); vec3 specularHighlights = uLightColor * specular * reflectivity; gl_FragColor = mix(reflectColor, refractColor, refractiveFactor); gl_FragColor = mix(gl_FragColor, vec4(uTint.xyz, 1.0), uTint.w) + vec4(specularHighlights, 0.0); }