跳到主要内容
← Water

Water

Water Domain Warping

shader-learning 自学第 12 课:Water Domain Warping

实时渲染 · 网格 GLSL

第 12 课:Water Domain Warping

实现

uniform float iTime;
uniform sampler2D iChannel0;
uniform sampler2D iChannel1;
uniform sampler2D iChannel2;
uniform mat4 inverseViewMatrix;

const float PI = 3.14;
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;
}

vec3 sampleEnvMap(vec3 dir) {
  vec3 P = normalize(dir);

  float phi = atan(P.x, P.z);
  float theta = asin(P.y);

  float u = (phi + PI) / (2.0 * PI);
  float v = (theta + PI * 0.5) / (PI);

  return textureLod(iChannel1, vec2(u, v), 3.0).rgb;
}

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 dudv = texture(iChannel2, fract(uv - vec2(iTime * 0.02))).rg;
  dudv = dudv * 2.0 - 1.0;
  vec2 warpedUV = fract(uv - dudv * 0.01 + iTime * 0.05);
  dudv = texture(iChannel2, warpedUV).rg;
  dudv = dudv * 2.0 - 1.0;
  dudv *= 0.2;

  vec3 normal = normalize(vec3(dudv.x, 1.0, dudv.y));
  vec3 incident = normalize(vPos - viewPos);

  vec3 reflectVec = reflect(incident, normal);
  vec3 reflectColor = sampleEnvMap(reflectVec);
  reflectColor = mix(reflectColor, 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(iChannel0, 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);
}