three.js实现水波模拟
时间: 2023-11-07 15:02:35 浏览: 139
要实现水波模拟,可以使用three.js中的ShaderMaterial和RenderTarget实现。以下是实现步骤:
1. 创建一个平面Geometry和一个ShaderMaterial。
```
const geometry = new THREE.PlaneBufferGeometry(200, 200, 256, 256);
const material = new THREE.ShaderMaterial({
uniforms: {
time: { value: 0.0 },
resolution: { value: new THREE.Vector2() }
},
vertexShader: document.getElementById('vertexShader').textContent,
fragmentShader: document.getElementById('fragmentShader').textContent
});
```
2. 创建一个RenderTarget,用于存储水波的纹理。
```
const renderTarget = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight);
```
3. 在渲染循环中,先将平面渲染到RenderTarget中。
```
renderer.setRenderTarget(renderTarget);
renderer.render(scene, camera);
```
4. 然后将RenderTarget的纹理传递给ShaderMaterial,并更新时间uniform。
```
material.uniforms.time.value += 0.1;
material.uniforms.resolution.value.set(window.innerWidth, window.innerHeight);
material.uniforms.texture.value = renderTarget.texture;
```
5. 最后再将平面渲染到屏幕上。
```
renderer.setRenderTarget(null);
renderer.render(scene, camera);
```
6. 在vertexShader和fragmentShader中实现水波效果。可以参考以下代码:
```
// vertexShader
varying vec2 vUv;
void main() {
vUv = uv;
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
gl_Position = projectionMatrix * mvPosition;
}
// fragmentShader
uniform float time;
uniform vec2 resolution;
uniform sampler2D texture;
varying vec2 vUv;
void main() {
vec2 uv = vUv;
vec4 texel = texture2D(texture, uv);
float depth = texel.r * 50.0;
float speed = 0.1;
float frequency = 10.0;
float amplitude = 0.1;
float noise = 0.0;
for (int i = 0; i < 4; i++) {
noise += abs(sin((uv.x + uv.y + time * speed) * frequency * (i + 1.0))) * amplitude / (i + 1.0);
}
uv.x += noise * 0.1;
uv.y += noise * 0.1;
float wave = sin(uv.x * 10.0 + time * 2.0) * sin(uv.y * 10.0 + time * 2.0) * depth;
gl_FragColor = vec4(0.2, 0.5, 0.8, 1.0) + vec4(wave, wave, wave, 0.0);
}
```
7. 最后可以根据需要添加一些控制,例如鼠标交互控制波浪的强度和方向等。
阅读全文