00:00/00:00TIME LEFT
Choosing the a bcd
3:22
00:03:22

Shortcuts

  • SPACE to play / pause
  • ARROW RIGHT or L to go forward
  • ARROW LEFT or J to go backward
  • ARROW UP to increase volume
  • ARROW DOWN to decrease volume
  • F to toggle fullscreen
  • M to toggle mute
  • 0 to 9 to go to the corresponding part of the video
  • SHIFT + , to decrease playback speed
  • SHIFT + . or ; to increase playback speed

Want to learn more?

That's the end of the free part 😔

To get access to 45 hours of video, a members-only Discord server and future updates, join us for only $95!

29.

Raging sea

Difficulty Hard

Downloads

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 Webpack 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;

    // ...
}

Want to learn more?

That's the end of the free part 😔

To get access to 45 hours of video, a members-only Discord server and future updates, join us for only $95!

How to use it

  • Download the Starter pack or Final project
    (if your browser detects a menace, do not worry, it is not)
  • Unzip it
  • Open your terminal and go to the unzip folder
  • Run npm install command to install dependencies
  • Run npm run dev to launch the local server
    (your browser should start automatically)

You can now 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

Any trouble? Go to the discord server: