00:00/00:00
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

Unlock content 🔓

To get access to 91 hours of video, a members-only Discord server, subtitles, lesson resources, future updates and much more join us for only $95!

Want to learn more? 👋

43%

That's the end of the free part 😔

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

Next lesson
33.

Hologram

Difficulty Hard

Introduction 00:00

In this lesson we are going to learn how to create holographic material that is often used in Sci-Fi movies such as Star Wars:

Most of the effect is done in the fragment shader, but there is also a glitch effect on the vertex shader, making the vertices go a little crazy in waves.

We are going to rely quite a lot on the Fresnel effect that enables visual variations according to the angle between the face and the camera angle. More about this in due time.

Setup 00:28

The starter already contains the following:

  • 3 rotating objects: a sphere, Suzanne and a torus knot
  • A single instance of MeshBasicMaterial for all 3 objects
  • An instance of lil-gui with the clearColor already set if you want to change the background color
  • An instance of Clock from which we get the elapsedTime in the tick function
  • The vite-plugin-glsl dependency to handle GLSL files
  • OrbitControls to rotate around

Material 01:37

Let’s start by changing the MeshBasicMaterial to ShaderMaterial:

const material = new THREE.ShaderMaterial()

The objects become red because of the default vertex and fragment shaders provided by Three.js.

Create the shader files

In src/, create a shaders/ folder and, in that src/shaders/ folder, create a holographic/ folder.

In the src/shaders/holographic/ folder, create a vertex.glsl file and add the minimum program we need to position the vertices:

void main()
{
    // Position
    vec4 modelPosition = modelMatrix * vec4(position, 1.0);

    // Final position
    gl_Position = projectionMatrix * viewMatrix * modelPosition;
}

We’ve separated the modelPosition because we need to work on it before applying the other matrices. It’ll make more sense shortly.

Still in the src/shaders/holographic/ folder, create a fragment.glsl file and add the minimum program we need to color the fragments in yellow:

void main()
{
    // Final color
    gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
}

To that fragment shader, we are going to add two #include at the very end of the main() function:

void main()
{
    // Final color
    gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
    #include <tonemapping_fragment>
    #include <colorspace_fragment>
}

Those are instructions for Three.js that will inject corresponding chunks to handle tone mapping, and color spacing as explained in the previous lessons.

Use the shader files

Back in src/script.js, import both shaders as holographicVertexShader and holographicFragmentShader:

import holographicVertexShader from './shaders/holographic/vertex.glsl'
import holographicFragmentShader from './shaders/holographic/fragment.glsl'

Send those shaders to the ShaderMaterial using the vertexShader and fragmentShader properties:

const material = new THREE.ShaderMaterial({
    vertexShader: holographicVertexShader,
    fragmentShader: holographicFragmentShader
})

Stripes 06:47

Let’s start with the fragment shader.

Pattern

We are going to draw a striped pattern. We want to create small gradients that keep on repeating as we go up.

The technique is very similar to one of the very first patterns from the Shader Patterns lesson:

But instead of relying on the UV coordinates, we are going to use the modelPosition.

In vertex.glsl, create a vec3 vPosition varying and assign the modelPosition to it:

varying vec3 vPosition;

void main()
{
    // Position
    vec4 modelPosition = modelMatrix * vec4(position, 1.0);

    // Final position
    gl_Position = projectionMatrix * viewMatrix * modelPosition;

    // Varyings
    vPosition = modelPosition.xyz;
}

Note that vPosition is a vec3 while modelPosition is a vec4 which is why we extract only the xyz (called swizzling).

In fragment.glsl, retrieve the vPosition and send it to the gl_FragColor to make sure it’s working:

varying vec3 vPosition;

void main()
{
    // Final color
    gl_FragColor = vec4(vPosition, 1.0);
    // ...
}

Want to learn more?

That's the end of the free part 😔

To get access to 91 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
  • Unzip it
  • Open your terminal and go to the unzip folder
  • Run npm install to install dependencies
    (if your terminal warns you about vulnerabilities, ignore it)
  • Run npm run dev to launch the local server
    (project should open on your default browser 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

If you get stuck and need help, join the members-only Discord server:

Discord