第 9 课:Water Reflection
实现
uniform float iTime;
uniform sampler2D iChannel0;
uniform sampler2D iChannel1;
uniform sampler2D iChannel2;
uniform mat4 inverseViewMatrix;
const float PI = 3.14;
const float frequency = 8.0;
const float amplitude = 0.02;
const float speed = -5.0;
const float maxDistance = 0.5;
const float refractiveIndex = 1.33;
const float distortionScale = 0.25;
in vec2 vUv;
in vec3 vPos;
out vec4 FragColor;
vec3 getViewPos() {
return (inverseViewMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
}
float getAmplitude(vec2 pos, vec2 origin) {
float distanceToOrigin = distance(pos, origin);
return amplitude * clamp((1.0 - distanceToOrigin / maxDistance), 0.0, 1.0);
}
vec2 getDistortion(vec2 pos, vec2 origin) {
float distanceToOrigin = distance(pos, origin);
float t = distanceToOrigin * 2.0 * PI * frequency + iTime * speed;
float distortion = sin(t) * getAmplitude(pos, origin);
return vec2(distortion);
}
vec3 getNormal(vec2 pos, vec2 origin) {
float A = getAmplitude(pos, origin);
float dist = distance(pos, origin);
float S = 2.0 * PI * frequency;
float T = iTime * speed;
float dfdx = A * cos(dist * S + T) * S * (pos.x - origin.x) / dist;
float dfdz = A * cos(dist * S + T) * S * (pos.y - origin.y) / dist;
return normalize(vec3(-dfdx, 1.0, -dfdz));
}
vec2 mirrorRepeat(vec2 coords) {
vec2 txy = fract(coords);
return mix(txy, 1.0 - txy, step(1.0, mod(coords.xy, 2.0)));
}
void main() {
vec2 uv = vUv;
vec3 viewPos = getViewPos();
vec2 w1 = vec2(0.3);
vec2 w2 = vec2(0.7);
vec3 normal = normalize(getNormal(uv, w1) + getNormal(uv, w2));
vec2 distortion = getDistortion(uv, vec2(0.3));
distortion += getDistortion(uv, vec2(0.7));
vec2 texCoords = uv + distortion;
vec3 incident = normalize(vPos + vec3(0.0, distortion.x, 0.0) - viewPos);
vec3 V = incident;
vec3 N = normal;
vec3 reflectionVector = V - 2.0 * (dot(N,V))*N;
float reflectionCoords_u = (atan(reflectionVector.x, reflectionVector.z)+ PI)/(2.0*PI);
float reflectionCoords_v = (asin(reflectionVector.y)+ PI/2.0)/(PI);
vec3 envMapReflectColor = texture(iChannel2, vec2(reflectionCoords_u, reflectionCoords_v)).rgb;
vec3 reflectColor = mix(envMapReflectColor, vec3(0.6, 0.8, 1.0), 0.25);
float eta = 1.0 / refractiveIndex;
vec3 refractedRay = refract(incident, normal, eta);
vec2 offset = refractedRay.xy * distortionScale;
vec3 refractColor = texture(iChannel1, mirrorRepeat(uv + offset)).rgb;
refractColor *= vec3(0.4, 0.6, 1.0);
float F0 = 0.02;
float F = F0 + (1.0 - F0) * pow(1.0 - dot(-incident, normal), 1.0);
FragColor = vec4(mix(refractColor, reflectColor, F), 1.0);
}