トップへ(mam-mam.net/)

Rendering Flowing Water in Three.js | Water.js Usage and Implementation Examples

Japanese

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>

Back to the list of 3D content with JavaScript