Expressing Water with Water.js[r145]
For those who want to render realistic water surfaces in Three.js.
This article clearly introduces how to reproduce flowing water movement and reflections using Water.js, along with actual code examples.
In Three.js, Water2.js can be used to represent still water, while Water.js can be used to represent flowing water.
This page demonstrates how to express flowing water using Water.js.
To use Water.js, you need to make it available by including:
<script src="./js/Water.js"></script>
Left mouse drag rotates, right mouse drag moves the camera, and the wheel zooms in/out.
Swipe to rotate, drag with two fingers on the screen to move the camera, and pinch in/out to zoom.
Double-click/tap also provides a focus function.
Source Code
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0,user-scalable=yes"> <script src="./js/three.min.js"></script> <script src="./js/ArcballControls.js"></script> <script src="./js/Sky.js"></script> <script src="./js/Water.js"></script> <script> var scene,camera,controls,water; var main = function () { // Get target canvas and retrieve width and height let can=document.getElementById('can'); let w = parseInt(can.style.width);// get width let h = parseInt(can.style.height);// get height // ■ Scene scene = new THREE.Scene(); // ■ Camera // THREE.PerspectiveCamera( field of view (deg), aspect ratio, near clipping plane, far clipping plane ); camera = new THREE.PerspectiveCamera(20, w/h, 0.1, 10000); camera.position.set(-30, 80, 200);// set camera position //camera.rotation.set(0,0,0);// set camera rotation (0,0,0) camera.lookAt(new THREE.Vector3(0, 0, 0));// set camera to look at (0,0,0) scene.add(camera);// add camera to scene // ■ Renderer renderer = new THREE.WebGLRenderer({canvas:can, antialias: true});// enable antialiasing renderer.setSize(w, h); renderer.setClearColor(0x000000, 1);// set background color // ■ Lights ------------------------------------------------ // Ambient light (applies light from all directions, prevents completely black shadows) var AmbientLight=new THREE.AmbientLight(0xffffff,0.4); scene.add( AmbientLight );// add ambient light to scene // SpotLight(color, intensity, distance, angle, penumbra[0-1], decay[1,1]) const spotLight=new THREE.SpotLight(0xffffff, 2,1000,Math.PI/8, 0.4, 1); spotLight.position.set(100,400,300); spotLight.target.position.set(0,0,0); scene.add(spotLight); scene.add(spotLight.target); // ■ Lambert material (non-glossy material affected by lights) let material=new THREE.MeshLambertMaterial({color:0x6699FF}); // ■ Box geometry (width, height, depth) let boxGeometry=new THREE.BoxGeometry(40,30,20); // ■ Create mesh from geometry and Lambert material let mesh=new THREE.Mesh(boxGeometry,material); scene.add(mesh);// add mesh to scene // ■ Sky let sky=new THREE.Sky(); sky.scale.setScalar(50000); sky.material.uniforms.turbidity.value=0.8;// atmospheric transparency sky.material.uniforms.rayleigh.value=0.4;// number of incident photons sky.material.uniforms.mieCoefficient.value=0.005;// scattering coefficient sky.material.uniforms.mieDirectionalG.value=0.8; // scattering directional G sky.material.uniforms.sunPosition.value.x= 10000;// sun position sky.material.uniforms.sunPosition.value.y= 30000;// sun position sky.material.uniforms.sunPosition.value.z=-40000;// sun position scene.add(sky); // ■ Water const waterGeometry = new THREE.PlaneGeometry(1000,1000,1,1); water=new THREE.Water( waterGeometry, { textureWidth: 512, textureHeight:512, // Use the image file located in "examples\textures\water" from the extracted three.js.zip waterNormals: new THREE.TextureLoader().load( './three_r145/img/Water_2_M_Normal.jpg', function (texture) { texture.wrapS=THREE.RepeatWrapping; texture.wrapT=THREE.RepeatWrapping; } ), alpha: 0.90, // opacity waterColor: 0x3344CC, sunColor: 0xFFFFFF, distortionScale: 3.0, // distortion scale side:THREE.FrontSide, } ); water.rotation.x=-Math.PI/2; water.position.set(0,-20,0); water.material.uniforms.sunDirection.value.copy( sky.material.uniforms.sunPosition.value ).normalize(); scene.add(water); // ■ Create Arcball controls (camera moves with mouse drag, wheel, etc.) controls = new THREE.ArcballControls(camera, renderer.domElement, scene); // If adjustNearFar is true, near/far clipping planes are adjusted to maintain visibility when zooming controls.adjustNearFar=true; controls.enableAnimations=true;// enable animation for rotation/focus controls.enableGrid=true;// show grid during pan operation controls.setGizmosVisible(true);// show gizmos (wireframe sphere for rotation center) renderLoop(); } function renderLoop () { requestAnimationFrame( renderLoop ); water.material.uniforms.time.value += 1.0 / 60.0; renderer.render( scene, camera ); } window.addEventListener( 'DOMContentLoaded', main, false ); </script> </head> <body> <canvas id="can" style="width:500px; height:300px;-ms-touch-action:none;touch-action:none;"> </canvas> </body> </html>
