SPACEto play / pauseARROW RIGHTorLto go forwardARROW LEFTorJto go backwardARROW UPto increase volumeARROW DOWNto decrease volumeFto toggle fullscreenMto toggle mute0 to 9to 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-guiwith theclearColoralready set if you want to change the background color - An instance of
Clockfrom which we get theelapsedTimein thetickfunction - The
vite-plugin-glsldependency to handle GLSL files OrbitControlsto 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 installto install dependencies
(if your terminal warns you about vulnerabilities, ignore it) -
Run
npm run devto 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