Matcap

매트캡

Faking a material’s shading and reflections with a single pre-baked sphere texture, without any lighting calculation.

Also known as: Material captureMeshMatcapMaterialSpherical reflection map
···
js
import * as THREE from 'three';
function makeMatcap() {
  const size = 256;
  const c = document.createElement('canvas');
  c.width = size; c.height = size;
  const ctx = c.getContext('2d');
  ctx.fillStyle = '#14141f';
  ctx.fillRect(0, 0, size, size);
  const cx = size / 2, cy = size / 2, r = size / 2;
  const base = ctx.createRadialGradient(cx - r * 0.3, cy - r * 0.35, r * 0.05, cx, cy, r);
  base.addColorStop(0, '#dfe7ff');
  base.addColorStop(0.35, '#7f8fe0');
  base.addColorStop(0.7, '#3a3f8a');
  base.addColorStop(1, '#0d0d20');
  ctx.fillStyle = base;
  ctx.fillRect(0, 0, size, size);
  const spec = ctx.createRadialGradient(cx - r * 0.32, cy - r * 0.38, 0, cx - r * 0.32, cy - r * 0.38, r * 0.22);
  spec.addColorStop(0, 'rgba(255,255,255,0.95)');
  spec.addColorStop(1, 'rgba(255,255,255,0)');
  ctx.fillStyle = spec;
  ctx.fillRect(0, 0, size, size);
  return c;
}
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x0b0b14);
const camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100);
camera.position.set(0, 0, 5);
const matcapTex = new THREE.CanvasTexture(makeMatcap());
matcapTex.colorSpace = THREE.SRGBColorSpace;
const mesh = new THREE.Mesh(new THREE.SphereGeometry(1.4, 64, 64), new THREE.MeshMatcapMaterial({ matcap: matcapTex }));
scene.add(mesh);
function resize() { renderer.setSize(innerWidth, innerHeight); camera.aspect = innerWidth / innerHeight; camera.updateProjectionMatrix(); }
addEventListener('resize', resize); resize();
renderer.setAnimationLoop((t) => {
  mesh.rotation.y = t * 0.0004;
  mesh.rotation.x = Math.sin(t * 0.0002) * 0.3;
  renderer.render(scene, camera);
});

A matcap (material capture) texture is one photo of a sphere lit from the front. At render time, the surface normal’s view-space x/y is used directly as the UV into that texture — "a face pointing this way gets the color at this spot on the stored sphere photo." One lookup, nothing else.

That’s why MeshMatcapMaterial can show metal, clay or glass-like looks with zero lights in the scene, at very low cost. This demo skips image files entirely and paints a few radial gradients with the canvas 2D API to build the matcap texture, then hands it to Three as a CanvasTexture.

The catch: the lighting is baked into the texture, so it never moves even as the camera orbits — no real shadows, no relation to actual light direction. Great for fast previews or a stylized look; reach for a PBR material when you need believable lighting.

When to use

Fast prototypes, stylized sculpt/clay looks, and ultra-lightweight scenes where you don’t want to set up lights.