【图中效果完整代码位于文章末】
目录
在三维场景设计中,水面效果能够极大地增强视觉体验,营造出更加真实或梦幻的氛围。Three.js作为一个强大的JavaScript库,为WebGL提供了简单易用的3D图形接口,使得在网页上实现高级视觉效果成为可能。本文将指导你如何使用Three.js添加一个逼真的水面效果到你的场景中。
准备工作
首先,确保你的项目已经引入了three.js库,并且已经加载了基础场景和背景,以免水面缺少环境反射无法显示,上面动图中的环境贴图效果可以参考文章👇👉【threejs教程9】threejs加载360全景图(VR)的两种方法
接下来,你需要一张水纹法线贴图(waternormals.jpg
),用于模拟水面波动的细节。这张图片可以自定义或从网络上获取。无水印图片下载👉图片地址
添加水面效果的步骤
1.引入Water库
import { Water } from 'three/examples/jsm/objects/Water'
2.创建水面几何体
一切始于几何体。我们使用PlaneGeometry
来创建一个广阔的平面作为水面的基础形状。这个平面的尺寸设为10000x10000单位,足以覆盖大部分场景
const waterGeometry = new THREE.PlaneGeometry(10000, 10000);
3.初始化水面材质
水面的效果主要依赖于特殊的材质——在这里,我们使用Water
材质。这个材质需要一些特定的设置,比如法线贴图路径、光源方向和颜色等,以达到逼真的效果。
const water = new Water(waterGeometry, {
textureWidth: 512,
textureHeight: 512,
waterNormals: new THREE.TextureLoader().load(
'./img/waternormals.jpg',
function (texture) {
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
}
),
sunDirection: new THREE.Vector3(), // 需要根据场景设置正确的阳光方向
sunColor: 0xffffff,
waterColor: 0x001e0f,
distortionScale: 3.7,
fog: scene.fog !== undefined,
});
注意,waterNormals加载了一个法线贴图,这对于模拟水面波纹至关重要。同时,通过调整sunDirection、sunColor和waterColor等属性,你可以控制水面的光照效果和颜色。
4.设置水面旋转与添加至场景
为了让水面看起来更自然,我们将平面旋转-90度使其与X轴平行,模拟真实的水面状态。
water.rotation.x = -Math.PI / 2;
scene.add(water);
5. 动画循环:更新水面时间参数
水面效果需要随着时间变化而动态更新,因此我们需要一个动画循环来不断更新水面材质中的时间参数。
function animate() {
requestAnimationFrame(animate);
water.material.uniforms['time'].value += 1.0 / 60.0; // 每帧更新时间参数
}
animate();
这段代码启动了一个无限循环,每一帧都会调用requestAnimationFrame,并使水面材质的时间值递增,从而模拟水流的动态变化。
总结
通过上述步骤,你已经在Three.js项目中成功添加了一个基本但视觉效果出众的水面。这仅仅是一个起点,Three.js的灵活性允许你进一步定制材质属性、添加反射和折射效果、甚至是交互功能,让水面更加生动和真实。
完整代码如下
import { Water } from 'three/examples/jsm/objects/Water'
function addWater() {
const waterGeometry = new THREE.PlaneGeometry(10000, 10000)
const water = new Water(waterGeometry, {
textureWidth: 512,
textureHeight: 512,
waterNormals: new THREE.TextureLoader().load(
'./img/waternormals.jpg',
function (texture) {
texture.wrapS = texture.wrapT = THREE.RepeatWrapping
}
),
sunDirection: new THREE.Vector3(),
sunColor: 0xffffff,
waterColor: 0x001e0f,
distortionScale: 3.7,
fog: scene.fog !== undefined,
})
water.rotation.x = -Math.PI / 2
scene.add(water)
function animate() {
requestAnimationFrame(animate)
water.material.uniforms['time'].value += 1.0 / 60.0
}
animate()
}