Water in ThreeJS

The Three.js Water addon is a specialized shader that simulates the appearance and behavior of water. It is based on the ShaderMaterial and Reflector classes in Three.js, offering a high degree of realism by combining multiple visual effects:

  • Reflection: The water surface reflects the surrounding environment, creating a mirror-like effect.
  • Refraction: Light passing through the water is bent, distorting the view of objects beneath the surface.
  • Wave Animation: The addon simulates the movement of water waves, creating a dynamic surface that reacts to time.

These effects work together to create a convincing water surface that can be used in a variety of environments, from oceans and lakes to small ponds and pools.

Setting Up the Water Addon

To use the Water addon, you first need to include the necessary files and set up a basic Three.js scene. Here’s how you can get started:

  1. Include the Water Addon: First, make sure to include the Water script in your project. You can find it in the Three.js examples or download it from the Three.js GitHub repository.
Import { Water } from 'three/examples/jsm/objects/Water.js';
import { Sky } from 'three/examples/jsm/objects/Sky.js';

Create a Basic Scene:

Set up a basic Three.js scene with a camera, renderer, and light source.

import * as THREE from ‘three’;
// Create a scene
const scene = new THREE.Scene();

// Set up the camera
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);
camera.position.set(30, 30, 100);

// Set up the renderer
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// Add lighting
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(50, 50, 50);
scene.add(light);

Creating the Water Surface

With the basic setup in place, you can now create the water surface using the Water addon. The water surface is typically represented by a plane geometry with the Water shader applied to it.

// Create a water surface
const waterGeometry = new THREE.PlaneGeometry(10000, 10000);

// Set up the Water object
const water = new Water(waterGeometry, {
  color: 0x001e0f,
  scale: 4,
  flowDirection: new THREE.Vector2(1, 1),
  textureWidth: 512,
  textureHeight: 512,
});

// Rotate the water surface to be horizontal
water.rotation.x = -Math.PI / 2;

// Add the water to the scene
scene.add(water);

In this example, the water surface is created as a large plane. The Water constructor takes several parameters:

  • color: The base color of the water.
  • scale: Controls the scale of the wave patterns.
  • flowDirection: A vector that determines the direction in which the water flows.
  • textureWidth and textureHeight: Set the resolution of the water texture. Higher values provide better detail but require more processing power.

Adding a Skybox

To enhance the realism of the water surface, you can add a skybox. The skybox will be reflected in the water, creating a natural-looking horizon.

// Create a skybox using the Sky addon
const sky = new Sky();
sky.scale.setScalar(10000);
scene.add(sky);

// Set the skybox parameters
const skyUniforms = sky.material.uniforms;
skyUniforms['turbidity'].value = 10;
skyUniforms['rayleigh'].value = 2;
skyUniforms['mieCoefficient'].value = 0.005;
skyUniforms['mieDirectionalG'].value = 0.8;

// Set the sun position
const sun = new THREE.Vector3();
const theta = Math.PI * (0.49);
const phi = 2 * Math.PI * (0.25);

sun.x = Math.cos(phi);
sun.y = Math.sin(phi) * Math.sin(theta);
sun.z = Math.sin(phi) * Math.cos(theta);

sky.material.uniforms['sunPosition'].value.copy(sun);

The Sky addon is used to create a dynamic skybox that can simulate different times of day and atmospheric conditions. The sun’s position is calculated and set in the skybox, which is then reflected on the water surface.

Animating the Water

To make the water appear dynamic, you need to animate the water surface by updating its properties in the render loop.

function animate() {
  requestAnimationFrame(animate);
  
  // Update the water’s time uniform to animate the waves
  water.material.uniforms[‘time’].value += 0.05;
  renderer.render(scene, camera);
}
animate();

By continuously updating the time uniform of the water material, the wave patterns on the water surface will animate, creating a lifelike effect of moving water.

Customizing the Water Effect

The Three.js Water addon is highly customizable. Here are a few ways you can tweak the water’s appearance:

  • Wave Speed and Direction: Modify the flowDirection and time to change the speed and direction of the water’s movement.
  • Wave Scale: Adjust the scale parameter to increase or decrease the size of the waves.
  • Color: Change the color parameter to simulate different water types, from clear blue oceans to murky green lakes.
  • Reflectivity: Control the reflectivity of the water by modifying the reflectivity property in the water material.
water.material.uniforms[‘flowDirection’].value.set(0.5, 0.5);
water.material.uniforms[‘scale’].value = 2;
water.material.uniforms[‘reflectivity’].value = 0.8;

These adjustments allow you to fine-tune the water surface to fit the specific aesthetic and environmental requirements of your scene.

Leave a comment

Your email address will not be published. Required fields are marked *