Introduction
In this article, we’ll break down a custom holographic shader effect in Three.js, using GLSL shaders to achieve a glitchy, sci-fi aesthetic. We’ll explore the Vertex Shader, Fragment Shader, and the JavaScript setup, highlighting key techniques such as:
- Procedural distortion (glitch effect)
- Fresnel shading for a glowing outline
- Animated holographic stripes
By the end, you’ll have a holographic sphere that looks futuristic and dynamic.
1. JavaScript Setup in Three.js
Initializing the Mesh
The THREE.Mesh is created using:
- SphereGeometry (a simple sphere)
- ShaderMaterial (custom shaders)
mesh = new THREE.Mesh(
new THREE.SphereGeometry(10, 64, 64), // High detail sphere
new THREE.ShaderMaterial({
uniforms: {
u_time: new THREE.Uniform(0), // Animation time
u_col: new THREE.Uniform(new THREE.Color(0x00ffff)), // Holographic cyan color
},
vertexShader: vShader,
fragmentShader: fShader,
transparent: true,
side: THREE.DoubleSide, // Render both sides of the sphere
depthWrite: false, // Prevents depth issues with transparency
blending: THREE.AdditiveBlending, // Soft glow effect
// wireframe: true, // Uncomment to debug geometry
})
);
scene.add(mesh);
Animation Loop
- Updates time (
u_time) for shader animation - Rotates the sphere for dynamic motion
- Uses
Stats.jsfor performance monitoring
let stats = new Stats();
document.body.appendChild(stats.dom);
function animate() {
let elapsedTime = clock.getElapsedTime();
mesh.material.uniforms.u_time.value = elapsedTime; // Pass time to shader
mesh.rotation.y += 0.001; // Slow rotation
stats.update();
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
2. Vertex Shader: Adding the Glitch Effect
Purpose
The vertex shader manipulates vertex positions to create a randomized glitch effect by slightly displacing vertices over time.
Key Features
- Random 2D function: Generates random displacement for glitching
- Sinusoidal distortion: Adds a wave-like movement to the glitch
- Position jittering: Makes the sphere’s surface distort randomly over time
Vertex Shader Code
uniform float u_time;
varying vec3 vNorm;
varying vec3 vPos;
// Generates pseudo-random numbers based on a 2D coordinate
float random2d(vec2 coord) {
return fract(sin(dot(coord.xy, vec2(12.9898, 78.233))) * 43758.5453);
}
void main() {
vec4 modelPosition = modelMatrix * vec4(position, 1.0);
// Time-based glitch effect
float glitchTime = u_time - modelPosition.y;
float glitchStrength = sin(glitchTime) + sin(glitchTime * 3.45) + sin(glitchTime * 8.76);
glitchStrength /= 3.0;
glitchStrength = smoothstep(0.8, 1.0, glitchStrength);
glitchStrength *= 0.1; // Strength of distortion
// Apply random displacement
modelPosition.x += (random2d(modelPosition.xz + u_time) - .5) * glitchStrength;
modelPosition.z += (random2d(modelPosition.zx + u_time) - .5) * glitchStrength;
gl_Position = projectionMatrix * viewMatrix * modelPosition;
vec4 modelNorm = modelMatrix * vec4(normal, 0.0);
vNorm = modelNorm.xyz;
vPos = modelPosition.xyz;
}
Explanation
- The
random2dfunction generates pseudo-random noise for displacement. - Sinusoidal distortion (
sin(glitchTime)) adds a smooth yet erratic effect. - Smoothstep function ensures a natural transition in glitch strength.
- Position jittering (
random2d(...)) makes the object appear dynamically distorted.
3. Fragment Shader: Holographic Effect
Purpose
The fragment shader controls the color and shading effects, using Fresnel shading and striped holographic patterns.
Key Features
- Fresnel effect: A soft glow on the edges for a sci-fi look
- Holographic stripes: Animated horizontal scan lines
- Transparency and glow blending: Creates a floating light-like effect
Fragment Shader Code
uniform float u_time;
uniform vec3 u_col;
varying vec3 vPos;
varying vec3 vNorm;
void main() {
vec3 normal = normalize(vNorm);
if (!gl_FrontFacing) {
normal = -normal; // Fix normal for inside faces
}
// Moving stripes effect
float stripes = mod((vPos.y - u_time * 0.02) * 5.0, 1.0);
stripes = pow(stripes, 3.0); // Softens stripe edges
// Fresnel effect for glow
vec3 viewDir = normalize(vPos - cameraPosition);
float fresnel = dot(viewDir, normal) + 1.0;
fresnel = pow(fresnel, 2.0);
// Fade effect towards edges
float fallOff = 1.0 - smoothstep(0.8, 0.0, fresnel);
// Combining effects
float holo = stripes * fresnel;
holo += fresnel * 1.25; // Amplifies glow
holo *= fallOff; // Smooth blending
gl_FragColor = vec4(u_col, holo); // Final color output
#include <tonemapping_fragment>
#include <colorspace_fragment>
}
Explanation
- Stripes Animation
- Uses
mod()to create moving scan lines along the Y-axis. pow(stripes, 3.0)makes them softer and more natural.- Fresnel Glow Effect
dot(viewDir, normal)calculates the angle-based glow intensity.pow(fresnel, 2.0)amplifies the glow effect.- Edge Fading (Fall-off)
- Smoothstep ensures that the glow fades out smoothly near the edges.
- Final Color Output
- The glow effect (
holo) is multiplied byfallOfffor better blending. - Uses
THREE.jstonemapping and colorspace for proper rendering.
Final Output
This shader produces a glowing, glitchy holographic sphere, complete with:
- Dynamic time-based distortion
- Animated holographic stripes
- Smooth Fresnel glow on edges
- Transparent, floating effect