Advertisement

Matcap Instanced Disco Geometry

| by Vladimir | 3 min read | code by Ksenia Kondrashova
Advanced

Tech & Dependencies

HTML CSS JavaScript
Three.js

Features

  • WebGL Instancing
  • Matcap Shading
  • Geometry Merging
  • Multi-view Scissor Rending

Browser Support

Chrome 60+ Edge 79+ Firefox 55+ Safari 11+

Core

This is a Matcap Instanced Disco Geometry demo. It renders multiple unique 3D geometries (Torus Knot, Icosahedron, Torus) using the WebGL Instanced Mesh technique. Instead of drawing individual planes for every mirror on the surface of the shape, it creates one InstancedMesh per object, mathematically orienting thousands of tiny reflective mirrors to mimic a faceted, crystal-like disco surface.

Specs

  • Weight: ~150 KB (Three.js core dependency).
  • Performance: Ultra-high. By using THREE.InstancedMesh, the component offloads the geometry rendering of thousands of individual mirror facets to the GPU, significantly reducing the draw call overhead.
  • Theming / Customization: Easily swap the matcap texture to change the reflective material properties (gold, chrome, crystal, etc.). Geometry is controlled by the objects array.
  • Responsiveness: Fluid. Uses setScissorTest and setViewport inside the render() loop to map a single WebGLRenderer across multiple DOM overlay nodes.
  • Web APIs: WebGL API, HTML Canvas API.
  • Graceful Degradation: Fails completely without WebGL. Requires a modern browser with GPU acceleration.

Anatomy

The system uses a sophisticated “Multi-Scene/Single-Renderer” architecture.

  • HTML (The Skeleton): A singular <canvas> element and a .container overlay. JavaScript injects .overlay-block nodes into this container.
  • CSS (The Skin): Minimalist layout. It uses CSS Grid/Flexbox to position the DOM nodes, which the JavaScript then uses as “anchors” for the 3D scene rendering.
  • JS (The Nervous System):
    1. Instancing Logic: Iterates over the vertices/normals of a source geometry to calculate the translation and rotation matrix for every single mirror facet.
    2. Scissor Rendering: A custom render() loop checks the bounding box (getBoundingClientRect) of each .overlay-block DOM node and tells the WebGL renderer to only draw inside those specific coordinate bounds.

Logic

The core logic is “Normal-Based Orientation” for instanced geometry:

for (let i = 0; i < positions.length; i += 3) {
    dummy.position.set(positions[i], positions[i + 1], positions[i + 2]);
    dummy.lookAt(positions[i] + normals[i], positions[i + 1] + normals[i + 1], positions[i + 2] + normals[i + 2]);
    dummy.updateMatrix();
    instancedMirrorMesh.setMatrixAt(i / 3, dummy.matrix);
}

Instead of simply tiling planes over the surface, the script inspects the vertex data of the base geometry. For every point, it calculates the normal vector (the direction the face is pointing). It then uses dummy.lookAt() to force the mirror plane to align perfectly with that specific normal. This ensures that every individual facet of the “disco ball” reflects light realistically based on the underlying curvature of the object.

Feel

Hyper-reflective and polished. The matcap shader trick creates the illusion of sophisticated environment mapping without the performance cost of real-time raytracing. The objects feel like polished, faceted gemstones suspended in a void. Because each scene has its own OrbitControls and independent animation speed, the experience feels like exploring a high-end digital showroom.

Advertisement