oceanPostProcess.fragment.fx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /*
  2. * "Seascape" by Alexander Alekseev aka TDM - 2014
  3. * Babylon.js integration by luaacro https://twitter.com/Luaacro
  4. * License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
  5. * Contact: tdmaav@gmail.com
  6. */
  7. // Uniforms
  8. uniform sampler2D textureSampler;
  9. uniform sampler2D positionSampler;
  10. #ifdef REFLECTION_ENABLED
  11. uniform sampler2D reflectionSampler;
  12. #endif
  13. #ifdef REFRACTION_ENABLED
  14. uniform sampler2D refractionSampler;
  15. #endif
  16. uniform float time;
  17. uniform vec2 resolution;
  18. uniform vec3 cameraRotation;
  19. uniform vec3 cameraPosition;
  20. // Varyings
  21. varying vec2 vUV;
  22. // Constants
  23. const int NUM_STEPS = 8;
  24. const float PI = 3.141592;
  25. const float EPSILON = 1e-3;
  26. #define EPSILON_NRM (0.1 / resolution.x)
  27. // Sea
  28. const int ITER_GEOMETRY = 8;
  29. const int ITER_FRAGMENT = 5;
  30. const float SEA_HEIGHT = 0.6;
  31. const float SEA_CHOPPY = 4.0;
  32. const float SEA_SPEED = 0.8;
  33. const float SEA_FREQ = 0.16;
  34. const vec3 SEA_BASE = vec3(0.1,0.19,0.22);
  35. const vec3 SEA_WATER_COLOR = vec3(0.8,0.9,0.6);
  36. #define SEA_TIME (1.0 + time * SEA_SPEED)
  37. const mat2 octave_m = mat2(1.6,1.2,-1.2,1.6);
  38. // Math
  39. mat3 fromEuler(vec3 ang)
  40. {
  41. vec2 a1 = vec2(sin(ang.x),cos(ang.x));
  42. vec2 a2 = vec2(sin(ang.y),cos(ang.y));
  43. vec2 a3 = vec2(sin(ang.z),cos(ang.z));
  44. mat3 m;
  45. m[0] = vec3(a1.y*a3.y+a1.x*a2.x*a3.x,a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x);
  46. m[1] = vec3(-a2.y*a1.x,a1.y*a2.y,a2.x);
  47. m[2] = vec3(a3.y*a1.x*a2.x+a1.y*a3.x,a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y);
  48. return m;
  49. }
  50. float hash( vec2 p )
  51. {
  52. float h = dot(p,vec2(127.1,311.7));
  53. return fract(sin(h)*43758.5453123);
  54. }
  55. float noise( in vec2 p )
  56. {
  57. vec2 i = floor( p );
  58. vec2 f = fract( p );
  59. vec2 u = f*f*(3.0-2.0*f);
  60. return -1.0+2.0*mix( mix( hash( i + vec2(0.0,0.0) ),
  61. hash( i + vec2(1.0,0.0) ), u.x),
  62. mix( hash( i + vec2(0.0,1.0) ),
  63. hash( i + vec2(1.0,1.0) ), u.x), u.y);
  64. }
  65. // Lighting
  66. float diffuse(vec3 n,vec3 l,float p)
  67. {
  68. return pow(dot(n,l) * 0.4 + 0.6,p);
  69. }
  70. float specular(vec3 n,vec3 l,vec3 e,float s)
  71. {
  72. float nrm = (s + 8.0) / (PI * 8.0);
  73. return pow(max(dot(reflect(e,n),l),0.0),s) * nrm;
  74. }
  75. // Sea
  76. float sea_octave(vec2 uv, float choppy)
  77. {
  78. uv += noise(uv);
  79. vec2 wv = 1.0-abs(sin(uv));
  80. vec2 swv = abs(cos(uv));
  81. wv = mix(wv,swv,wv);
  82. return pow(1.0-pow(wv.x * wv.y,0.65),choppy);
  83. }
  84. float map(vec3 p)
  85. {
  86. float freq = SEA_FREQ;
  87. float amp = SEA_HEIGHT;
  88. float choppy = SEA_CHOPPY;
  89. vec2 uv = p.xz; uv.x *= 0.75;
  90. float d, h = 0.0;
  91. for(int i = 0; i < ITER_GEOMETRY; i++)
  92. {
  93. d = sea_octave((uv+SEA_TIME)*freq,choppy);
  94. d += sea_octave((uv-SEA_TIME)*freq,choppy);
  95. h += d * amp;
  96. uv *= octave_m; freq *= 1.9; amp *= 0.22;
  97. choppy = mix(choppy,1.0,0.2);
  98. }
  99. return p.y - h;
  100. }
  101. float map_detailed(vec3 p)
  102. {
  103. float freq = SEA_FREQ;
  104. float amp = SEA_HEIGHT;
  105. float choppy = SEA_CHOPPY;
  106. vec2 uv = p.xz; uv.x *= 0.75;
  107. float d, h = 0.0;
  108. for(int i = 0; i < ITER_FRAGMENT; i++)
  109. {
  110. d = sea_octave((uv+SEA_TIME)*freq,choppy);
  111. d += sea_octave((uv-SEA_TIME)*freq,choppy);
  112. h += d * amp;
  113. uv *= octave_m; freq *= 1.9; amp *= 0.22;
  114. choppy = mix(choppy,1.0,0.2);
  115. }
  116. return p.y - h;
  117. }
  118. vec3 getSeaColor(vec3 p, vec3 n, vec3 l, vec3 eye, vec3 dist)
  119. {
  120. float fresnel = clamp(1.0 - dot(n, -eye), 0.0, 1.0);
  121. fresnel = pow(fresnel, 3.0) * 0.65;
  122. #if defined(REFLECTION_ENABLED) || defined(REFRACTION_ENABLED)
  123. vec2 reflectionUv = vec2(vUV.x, vUV.y + normalize(n).y);
  124. #endif
  125. #ifdef REFLECTION_ENABLED
  126. vec3 reflected = texture2D(reflectionSampler, reflectionUv).rgb * (1.0 - fresnel);
  127. #else
  128. vec3 eyeNormal = reflect(eye, n);
  129. eyeNormal.y = max(eyeNormal.y,0.0);
  130. vec3 reflected = vec3(pow(1.0-eyeNormal.y,2.0), 1.0-eyeNormal.y, 0.6+(1.0-eyeNormal.y)*0.4);
  131. #endif
  132. #ifdef REFRACTION_ENABLED
  133. vec3 refracted = SEA_BASE + diffuse(n, l, 80.0) * SEA_WATER_COLOR * 0.12;
  134. refracted += (texture2D(refractionSampler, reflectionUv).rgb * fresnel);
  135. #else
  136. vec3 refracted = SEA_BASE + diffuse(n, l, 80.0) * SEA_WATER_COLOR * 0.12;
  137. #endif
  138. vec3 color = mix(refracted, reflected, fresnel);
  139. float atten = max(1.0 - dot(dist, dist) * 0.001, 0.0);
  140. color += SEA_WATER_COLOR * (p.y - SEA_HEIGHT) * 0.18 * atten;
  141. color += vec3(specular(n,l,eye,60.0));
  142. return color;
  143. }
  144. // Tracing
  145. vec3 getNormal(vec3 p, float eps)
  146. {
  147. vec3 n;
  148. n.y = map_detailed(p);
  149. n.x = map_detailed(vec3(p.x+eps,p.y,p.z)) - n.y;
  150. n.z = map_detailed(vec3(p.x,p.y,p.z+eps)) - n.y;
  151. n.y = eps;
  152. return normalize(n);
  153. }
  154. float heightMapTracing(vec3 ori, vec3 dir, out vec3 p)
  155. {
  156. float tm = 0.0;
  157. float tx = 1000.0;
  158. float hx = map(ori + dir * tx);
  159. if(hx > 0.0) return tx;
  160. float hm = map(ori + dir * tm);
  161. float tmid = 0.0;
  162. for(int i = 0; i < NUM_STEPS; i++)
  163. {
  164. tmid = mix(tm,tx, hm/(hm-hx));
  165. p = ori + dir * tmid;
  166. float hmid = map(p);
  167. if(hmid < 0.0)
  168. {
  169. tx = tmid;
  170. hx = hmid;
  171. }
  172. else
  173. {
  174. tm = tmid;
  175. hm = hmid;
  176. }
  177. }
  178. return tmid;
  179. }
  180. // Main
  181. void main()
  182. {
  183. #ifdef NOT_SUPPORTED
  184. // Just work as a pass through
  185. gl_FragColor = texture2D(textureSampler, vUV);
  186. #else
  187. vec2 uv = vUV;
  188. uv = uv * 2.0 - 1.0;
  189. uv.x *= resolution.x / resolution.y;
  190. // ray
  191. vec3 ang = vec3(cameraRotation.z, cameraRotation.x, cameraRotation.y);
  192. vec3 ori = vec3(cameraPosition.x, cameraPosition.y, -cameraPosition.z);
  193. vec3 dir = normalize(vec3(uv.xy, -3.0));
  194. dir = normalize(dir) * fromEuler(ang);
  195. // Tracing
  196. vec3 p;
  197. heightMapTracing(ori, dir, p);
  198. vec3 dist = p - ori;
  199. vec3 n = getNormal(p, dot(dist, dist) * EPSILON_NRM);
  200. vec3 light = normalize(vec3(0.0, 1.0, 0.8));
  201. // Color
  202. float seaFact = clamp(max(ori.y, 0.0), 0.0, 1.0);
  203. vec3 position = texture2D(positionSampler, vUV).rgb;
  204. vec3 baseColor = texture2D(textureSampler, vUV).rgb;
  205. vec3 color = baseColor;
  206. if (max(position.y, 0.0) < p.y)
  207. {
  208. // Sea above
  209. color = mix(
  210. baseColor,
  211. getSeaColor(p, n, light, dir, dist),
  212. pow(smoothstep(0.0, -0.05, dir.y), 0.3)
  213. ) * seaFact;
  214. }
  215. color = mix(
  216. color,
  217. baseColor * SEA_BASE + diffuse(n, n, 80.0) * SEA_WATER_COLOR * 0.12,
  218. 1.0 - seaFact
  219. );
  220. // post
  221. gl_FragColor = vec4(pow(color, vec3(0.75)), 1.0);
  222. #endif
  223. }