返回

让水面动起来——水面波动效果的实现思路

前端

俗话说:遇事不决,量子力学写虽得儿。趁此机会,本篇文章就来与小伙伴们分享动态波浪 Shader 的原理和制作思路吧。要注意的是,这是一篇偏入门的文章,写得会相对比较详细,尽量让不懂 Shader 的小白也可以看懂 ,这也是我写文章的一贯风格。

正弦曲线是三角函数中的一种 ,其图像为一条光滑的波浪线。正弦曲线的方程为:

y = A \sin(Bx + C) + D

其中,A 为振幅,B 为角速度,C 为相位角,D 为垂直偏移量。

我们可以使用正弦曲线来创建波浪效果 。首先,我们需要创建一个平面,然后使用正弦曲线来修改平面的顶点位置。这样,当我们渲染平面时,它就会看起来像波浪一样。

在 Shader 中,我们可以使用以下代码来创建波浪效果:

uniform float time;
uniform float amplitude;
uniform float frequency;
uniform float phase;
uniform float offset;

void main() {
  float x = position.x;
  float y = position.y;
  float z = position.z;

  float wave = amplitude * sin(frequency * (x + time) + phase) + offset;

  y += wave;

  gl_Position = projectionMatrix * modelViewMatrix * vec4(x, y, z, 1.0);
}

在上面的代码中:

  • time 是一个 uniform 变量,它存储着当前时间。
  • amplitude 是一个 uniform 变量,它存储着波浪的振幅。
  • frequency 是一个 uniform 变量,它存储着波浪的频率。
  • phase 是一个 uniform 变量,它存储着波浪的相位角。
  • offset 是一个 uniform 变量,它存储着波浪的垂直偏移量。
  • position 是一个 varying 变量,它存储着顶点的世界坐标。
  • projectionMatrix 是一个 uniform 变量,它存储着投影矩阵。
  • modelViewMatrix 是一个 uniform 变量,它存储着模型视图矩阵。
  • gl_Position 是一个内建变量,它存储着顶点的裁剪空间坐标。

我们可以在 Three.js 中使用上面的代码来创建动态波浪效果。 首先,我们需要创建一个平面几何体:

var geometry = new THREE.PlaneGeometry(10, 10, 100, 100);

然后,我们需要创建一个材质。 材质中包含了上面的 Shader 代码:

var material = new THREE.ShaderMaterial({
  uniforms: {
    time: { value: 0.0 },
    amplitude: { value: 1.0 },
    frequency: { value: 2.0 },
    phase: { value: 0.0 },
    offset: { value: 0.0 }
  },
  vertexShader: `
    uniform float time;
    uniform float amplitude;
    uniform float frequency;
    uniform float phase;
    uniform float offset;

    void main() {
      float x = position.x;
      float y = position.y;
      float z = position.z;

      float wave = amplitude * sin(frequency * (x + time) + phase) + offset;

      y += wave;

      gl_Position = projectionMatrix * modelViewMatrix * vec4(x, y, z, 1.0);
    }
  `,
  fragmentShader: `
    void main() {
      gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
    }
  `
});

最后,我们需要创建一个网格对象并将其添加到场景中。 网格对象由几何体和材质组成:

var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

现在,当我们渲染场景时,平面就会看起来像波浪一样。

动态波浪效果是一个非常酷炫的效果。 它可以被用于创建各种各样的场景,比如海洋、湖泊、河流等。如果您想学习如何创建动态波浪效果,那么本文就是一个很好的起点。