
Lab notes
This experiment builds a custom holographic material from scratch—not a texture overlay, but a full `ShaderMaterial` where the look comes from math: stripes, silhouette falloff (Fresnel), transparency, additive glow, and a timed vertex glitch. One material is shared across a sphere, a torus knot, and a loaded Suzanne so the effect reads as a reusable sci‑fi shader, not a one-off mesh trick.
A hologram sells volume, energy, and instability. Faint scan lines move through space, edges brighten where the surface glances away from the camera, soft fade keeps it from reading as solid plastic, and occasional horizontal tearing sells the glitch. That perception is encoded in the GPU pipeline: vertex for instability, fragment for light and energy, material flags for how fragments blend into the scene.
One material, three meshes
The scene is simple on purpose: sphere on the left, Suzanne in the center (from `suzanne.glb`), torus knot on the right. They all share one `ShaderMaterial` with uniforms `uTime` and `uColor`. lil-gui exposes hologram tint and clear color so the look stays editable while objects slowly rotate.
Material flags do as much work as the GLSL. `transparent: true` lets alpha drive visibility. `side: THREE.DoubleSide` keeps the effect readable from both faces. `depthWrite: false` softens self-occlusion and sorting artifacts. `blending: THREE.AdditiveBlending` stacks light so bright bands glow instead of covering what sits behind them.
Vertex stage: space, normals, glitch
Vertices go through a clean model → world → view → clip chain. Getting that wrong (for example multiplying `modelMatrix` twice via `modelViewMatrix` on an already-transformed position) makes meshes orbit the wrong center instead of spinning in place.
Glitch timing is tied to height: `uTime - modelPosition.y`, so distortion bands sweep vertically. Several sines at different frequencies are averaged into irregular pulses; `smoothstep` gates strength so tearing only fires when the pulse is strong. Random 2D noise then offsets x and z by that strength—short bursts of horizontal instability, not constant static.
World-space normals leave the vertex stage with `w = 0.0` so translation does not skew them. That matters later for Fresnel on a double-sided mesh.
Fragment stage: stripes, Fresnel, glow
`mod` on world y (shifted by `uTime`) builds repeating scan bands; `pow(..., 3.0)` sharpens them into thin bright lines. Fresnel compares view direction with the normalized, front-face–corrected normal—grazing angles push silhouette glow, the classic hologram rim.
Stripes are modulated by Fresnel, extra Fresnel is added, then a `smoothstep` falloff softens the outer rim so energy fades instead of cutting off hard. Final output is `vec4(uColor, holographic)`: RGB is tint, alpha is hologram energy. With additive blending, that alpha becomes glow contribution. Tone-mapping and colorspace includes keep the Three.js color pipeline honest.
What the GPU is really teaching
Custom `ShaderMaterial` gives control `MeshStandardMaterial` will not. World-space varyings make stripes follow space instead of UV unwrap quirks. Fresnel is a cheap emissive rim without scene lights. Front-face normal flips keep double-sided meshes Fresnel-correct. Additive blending plus disabled depth write is what makes soft holographic layering possible. Multi-sine timing plus noise is what makes glitches feel intermittent instead of noisy.
Open the live build, rotate the trio, and nudge the color. If the rim holds, the stripes track space, and the glitch fires in short bursts, the experiment did its job: a reusable GPU hologram—scan stripes, Fresnel glow, additive transparency, height-timed vertex tears—applied to primitives and a loaded model alike.