详尽Shader模拟水面及webgl源码(二)二维平面波

Demo地址:http://www.ibiblio.org/e-notes/webgl/gpu/flat_wave.htm,源码自己扒 

效果就像是从上往下俯瞰水面中的涟漪。

实现这种效果用到了数学物理方程的一些概念,如有需要,推荐阅读梁昆淼所编写的《数学物理方法(第四版)》。

计算机可以通过计算一些特定点的方程来计算水面的波动效果。例如下图的Gerstner Wave,点的运动符合某个方程。

在本章的2d水波中,这些点使用的方程为如下公式。每个点的颜色与这个点的xy坐标以及时间t有关,式子中的(r - r0)^2当然就算某一点到原点距离的平方啦。

这是海洋科学中使用了基于经验的统计学模型。

编写程序时,不必每次都计算一遍这个方程,可以根据上次计算的结果与这次计算的结果来计算下一次的结果。

程序103行给出了具体的计算方式。虽然每个像素都有RGBA四个通道,但现在只需要将初步计算的结果放在r通道中。

var n1 = n-1, h = 1/n1, t = 0;
     pix = new Float32Array(4*n*n);
     for(var i = 0; i<n; i++)
       for(var j = 0; j<n; j++){
         var x = h*(j-n/2),  y = h*(i-n/2);
         pix[t++] = 50*Math.exp(-5000*(x*x + y*y));
         pix[t++] = 0; pix[t++] = 0; pix[t++] = 0;
       }

在第一个片元着色器计算偏微分方程。 

<script id="shader-fs" type="x-shader/x-fragment"> 
precision highp float;
  uniform sampler2D samp;
  uniform sampler2D samp1;
  varying vec2 vTexCoord;
  const float d = 1./512., dth2 = .2;
void main(void) {
   float u = texture2D(samp, vTexCoord).r;
   float u1  = texture2D(samp1, vTexCoord).r;
   u = 2.*u1 - u +
     (texture2D(samp1, vec2(vTexCoord.x, vTexCoord.y + d) ).r +
      texture2D(samp1, vec2(vTexCoord.x, vTexCoord.y - d) ).r +
      texture2D(samp1, vec2(vTexCoord.x + d, vTexCoord.y) ).r +
      texture2D(samp1, vec2(vTexCoord.x - d, vTexCoord.y) ).r +
      - 4.*u1)*dth2;
   gl_FragColor = vec4(u, 0., 0., 0. );
}
</script> 

第二个片元着色器将结果打印到屏幕上

<script id="shader-fs-show" type="x-shader/x-fragment"> 
precision highp float;
  uniform sampler2D samp;
  varying vec2 vTexCoord;
void main(void) {
   float c = texture2D(samp, vTexCoord).r;
   if (c < 0.) gl_FragColor = vec4(0., 0., -c, 1.);
   else gl_FragColor = vec4(c, 0., 0., 1.);
}
</script> 

参考:https://zhuanlan.zhihu.com/p/31670275

发布了194 篇原创文章 · 获赞 8 · 访问量 9864

猜你喜欢

转载自blog.csdn.net/qq_43439240/article/details/104212236