Water.glsl 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. #include "Uniforms.glsl"
  2. #include "Samplers.glsl"
  3. #include "Transform.glsl"
  4. #include "ScreenPos.glsl"
  5. #include "Fog.glsl"
  6. #ifndef GL_ES
  7. varying vec4 vScreenPos;
  8. varying vec2 vReflectUV;
  9. varying vec2 vWaterUV;
  10. varying vec4 vEyeVec;
  11. #else
  12. varying highp vec4 vScreenPos;
  13. varying highp vec2 vReflectUV;
  14. varying highp vec2 vWaterUV;
  15. varying highp vec4 vEyeVec;
  16. #endif
  17. varying vec3 vNormal;
  18. #ifdef COMPILEVS
  19. uniform vec2 cNoiseSpeed;
  20. uniform float cNoiseTiling;
  21. #endif
  22. #ifdef COMPILEPS
  23. uniform float cNoiseStrength;
  24. uniform float cFresnelPower;
  25. uniform vec3 cWaterTint;
  26. #endif
  27. void VS()
  28. {
  29. mat4 modelMatrix = iModelMatrix;
  30. vec3 worldPos = GetWorldPos(modelMatrix);
  31. gl_Position = GetClipPos(worldPos);
  32. vScreenPos = GetScreenPos(gl_Position);
  33. // GetQuadTexCoord() returns a vec2 that is OK for quad rendering; multiply it with output W
  34. // coordinate to make it work with arbitrary meshes such as the water plane (perform divide in pixel shader)
  35. // Also because the quadTexCoord is based on the clip position, and Y is flipped when rendering to a texture
  36. // on OpenGL, must flip again to cancel it out
  37. vReflectUV = GetQuadTexCoord(gl_Position);
  38. vReflectUV.y = 1.0 - vReflectUV.y;
  39. vReflectUV *= gl_Position.w;
  40. vWaterUV = iTexCoord * cNoiseTiling + cElapsedTime * cNoiseSpeed;
  41. vNormal = GetWorldNormal(modelMatrix);
  42. vEyeVec = vec4(cCameraPos - worldPos, GetDepth(gl_Position));
  43. }
  44. void PS()
  45. {
  46. vec2 refractUV = vScreenPos.xy / vScreenPos.w;
  47. vec2 reflectUV = vReflectUV.xy / vScreenPos.w;
  48. vec2 noise = (texture2D(sNormalMap, vWaterUV).rg - 0.5) * cNoiseStrength;
  49. refractUV += noise;
  50. // Do not shift reflect UV coordinate upward, because it will reveal the clipping of geometry below water
  51. if (noise.y < 0.0)
  52. noise.y = 0.0;
  53. reflectUV += noise;
  54. float fresnel = pow(1.0 - clamp(dot(normalize(vEyeVec.xyz), vNormal), 0.0, 1.0), cFresnelPower);
  55. vec3 refractColor = texture2D(sEnvMap, refractUV).rgb * cWaterTint;
  56. vec3 reflectColor = texture2D(sDiffMap, reflectUV).rgb;
  57. vec3 finalColor = mix(refractColor, reflectColor, fresnel);
  58. gl_FragColor = vec4(GetFog(finalColor, GetFogFactor(vEyeVec.w)), 1.0);
  59. }