Three.js documentation
Others
Shortcuts ⌨️
SPACE
to play / pauseARROW RIGHT
orL
to go forwardARROW LEFT
orJ
to go backwardARROW UP
to increase volumeARROW DOWN
to decrease volumeF
to toggle fullscreenM
to toggle mute0 to 9
to go to the corresponding part of the videoSHIFT
+,
to decrease playback speedSHIFT
+.
or;
to increase playback speed
Subtitles 💬
Subtitles are only available for members
To get access to 72 hours of video, a members-only Discord server and future updates, join us for only $95!
Want to learn more? 👍
That's the end of the free part 😔
To get access to 72 hours of video, a members-only Discord server and future updates, join us for only $95!
Raging sea
Difficulty Hard
Introduction 00:00
Now that we know how to use shaders and draw some patterns let's make fair use of it and create a raging sea.
We are going to animate the waves and keep control of the parameters with the debug panel.
Setup 00:36
For now, all we have is a rotated plane using MeshBasicMaterial. The geometry has a 128x128
subdivision. We are going to animate the vertices to get the waves and we need quite a lot of vertices. 128x128
might not be enough, but we will increase the value if required.
Base 01:14
Let's replace the material by a ShaderMaterial:
const waterMaterial = new THREE.ShaderMaterial()
Our project configuration already supports GLSL files, but we need to create these files.
Create the vertex shader in /src/shaders/water/vertex.glsl
:
void main()
{
vec4 modelPosition = modelMatrix * vec4(position, 1.0);
vec4 viewPosition = viewMatrix * modelPosition;
vec4 projectedPosition = projectionMatrix * viewPosition;
gl_Position = projectedPosition;
}
Now create the fragment shader in /src/shaders/water/fragment.glsl
:
void main()
{
gl_FragColor = vec4(0.5, 0.8, 1.0, 1.0);
}
Finally, import those shaders in your script and use them in a ShaderMaterial:
// ...
import waterVertexShader from './shaders/water/vertex.glsl'
import waterFragmentShader from './shaders/water/fragment.glsl'
// ...
const waterMaterial = new THREE.ShaderMaterial({
vertexShader: waterVertexShader,
fragmentShader: waterFragmentShader
})
You should get a blue plane. If not, check the logs.
If you did all of this from memory, congratulation, you are a genius. If not, it's perfectly normal, and you only need time.
Big waves 08:35
We begin with the big waves to get significant results quickly. What's better than a sinus to create waves?
In the vertex shader, let's move the y
value of the modelPosition
with a sin(...)
based on the x
:
vec4 modelPosition = modelMatrix * vec4(position, 1.0);
modelPosition.y += sin(modelPosition.x);
The displacement and frequency should be way too high. Instead of just multiplying the values numbers coming out from nowhere in the shader, we will use uniforms to have more control over them.
Let's start with the elevation.
Elevation
Add a uBigWavesElevation
uniform to the ShaderMaterial:
const waterMaterial = new THREE.ShaderMaterial({
vertexShader: waterVertexShader,
fragmentShader: waterFragmentShader,
uniforms:
{
uBigWavesElevation: { value: 0.2 }
}
})
We can now retrieve and use the uBigWavesElevation
uniform in the vertex shader:
uniform float uBigWavesElevation;
void main()
{
// ...
modelPosition.y += sin(modelPosition.x) * uBigWavesElevation;
// ...
}
How to use it 🤔
- Download the Starter pack or Final project
- Unzip it
- Open your terminal and go to the unzip folder
-
Run
npm install
to install dependencies
(if your terminal warn you about vulnerabilities, ignore it) -
Run
npm run dev
to launch the local server
(your browser should start automatically) - Start coding
- The JS is located in src/script.js
- The HTML is located in src/index.html
- The CSS is located in src/style.css