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
Three.js documentation
Fresnel articles
- https://www.racoon-artworks.de/cgbasics/fresnel.php
- https://www.dorian-iten.com/fresnel/
- https://shanesimmsart.wordpress.com/2022/03/29/fresnel-reflection/
GLSL functions
Others
- Random (Book of Shaders)
Shortcuts ⌨️
Unlock content 🔓
To get access to 93 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? 🤘
That's the end of the free part 😔
To get access to 93 hours of video, a members-only Discord server and future updates, join us for only $95!
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 theclearColor
already set if you want to change the background color - An instance of
Clock
from which we get theelapsedTime
in thetick
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);
// ...
}
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