1,介绍
使用Three.js引入Water.js,实现模拟河流水面,水管流水。
效果图如下:
参考案例:
three.js webgl - shaders - ocean (threejs.org)
https://threejs.org/examples/webgl_shaders_ocean.html
three.js - water (threejs.org)
https://threejs.org/examples/webgl_water.html
2,实现说明
1,河流实现需要创建一个不规则几何体,然后创建Water对象传入几何体
2,模拟水管水流需要创建两个管子,一根管子模拟水流,一根管子包在外面
// 创建一个平滑的二维样条曲线 const curve = new THREE.SplineCurve([ new THREE.Vector2(1520, 2850), new THREE.Vector2(420, 180), new THREE.Vector2(220, 280), new THREE.Vector2(100, -380), new THREE.Vector2(-500, 780), ]); // 返回曲线上给定位置的点集合 const points = curve.getPoints(1000); // 点创建一条平滑的三维样条曲线 const curves = new THREE.CatmullRomCurve3([ new THREE.Vector3(100, 0, 100), new THREE.Vector3(0, 0, 100), new THREE.Vector3(0, -100, 100), ]); // 创建管子几何体 const geometryTube1 = new THREE.TubeGeometry(curves, 200, 10, 50); const geometryTube = new THREE.TubeGeometry(curves, 200, 9, 50); // 创建材质 const materialTube = new THREE.MeshBasicMaterial({ color: "#00aa00", // 管子颜色 transparent: true, // 管子是否透明 side: THREE.DoubleSide, opacity: 0.5, // 管子透明度 }); // 创建管子物体对象 const meshTube = new THREE.Mesh(geometryTube1, materialTube); meshTube.position.x = -300; meshTube.rotation.y = Math.PI; // 添加到场景 scene.add(meshTube); water = new Water(geometryTube, { textureWidth: 112, // 水浑浊程度,密度 textureHeight: 112, // 水浑浊程度,密度 waterNormals: new THREE.TextureLoader().load('assets/textures/waternormals.jpg', function(texture) { texture.wrapS = texture.wrapT = THREE.RepeatWrapping; }), waterColor: "#ffffff", }); water.position.x = -300; water.rotation.y = Math.PI; scene.add(water); let splineShape = new THREE.Shape(points); let geometry = new THREE.ShapeGeometry(splineShape); water1 = new Water(geometry, { textureWidth: 1512, // 水浑浊程度,密度 textureHeight: 1512, // 水浑浊程度,密度 waterNormals: new THREE.TextureLoader().load('assets/textures/waternormals.jpg', function(texture) { texture.wrapS = texture.wrapT = THREE.RepeatWrapping; }), waterColor: "#ffffff", // 水颜色 }); water1.position.y = -90; water1.position.x = -200; water1.rotation.x = Math.PI * -0.5; scene.add(water1);
最后注意水面是否可以有波动效果,在 render添加如下代码
water.material.uniforms['time'].value += 2.0 / 60.0;