返回
让水面动起来——水面波动效果的实现思路
前端
2023-11-12 19:39:31
俗话说:遇事不决,量子力学写虽得儿。趁此机会,本篇文章就来与小伙伴们分享动态波浪 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);
现在,当我们渲染场景时,平面就会看起来像波浪一样。
动态波浪效果是一个非常酷炫的效果。 它可以被用于创建各种各样的场景,比如海洋、湖泊、河流等。如果您想学习如何创建动态波浪效果,那么本文就是一个很好的起点。