Glass transmission

유리 트랜스미션

A physically based glass material that actually refracts what’s behind it, instead of faking transparency with alpha.

Also known as: MeshPhysicalMaterialtransmissionRefraction
···
js
import * as THREE from 'three';
import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js';
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(0x08060f);
const camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100);
camera.position.set(0, 0.3, 4.6);

const pmrem = new THREE.PMREMGenerator(renderer);
scene.environment = pmrem.fromScene(new RoomEnvironment(), 0.04).texture;

const backdrop = new THREE.Mesh(
  new THREE.PlaneGeometry(18, 7, 12, 6),
  new THREE.MeshBasicMaterial({ vertexColors: true, side: THREE.DoubleSide })
);
const posAttr = backdrop.geometry.attributes.position;
const colors = [];
const c1 = new THREE.Color(0xff5c8a), c2 = new THREE.Color(0x5b5bf7), c3 = new THREE.Color(0x18c29c);
for (let i = 0; i < posAttr.count; i++) {
  const x = posAttr.getX(i), y = posAttr.getY(i);
  const mixed = c1.clone().lerp(c2, x / 18 + 0.5).lerp(c3, y / 7 + 0.5);
  colors.push(mixed.r, mixed.g, mixed.b);
}
backdrop.geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
backdrop.position.z = -1.6;
scene.add(backdrop);

const glass = new THREE.Mesh(
  new THREE.IcosahedronGeometry(1.15, 4),
  new THREE.MeshPhysicalMaterial({
    roughness: 0.05,
    metalness: 0,
    transmission: 1,
    thickness: 1.2,
    ior: 1.5,
    envMapIntensity: 1,
    clearcoat: 1,
    clearcoatRoughness: 0.1,
  })
);
scene.add(glass);

function resize() { renderer.setSize(innerWidth, innerHeight); camera.aspect = innerWidth / innerHeight; camera.updateProjectionMatrix(); }
addEventListener('resize', resize); resize();
renderer.setAnimationLoop((t) => {
  glass.rotation.y = t * 0.00035;
  glass.rotation.x = Math.sin(t * 0.0002) * 0.3;
  renderer.render(scene, camera);
});

material.transparent + opacity just blends with whatever’s behind — no refraction, so it reads as "translucent color." MeshPhysicalMaterial’s transmission (0–1) is different: set it to 1 and the renderer separately re-renders what’s "behind" that object into a texture every frame, then redraws it bent (refracted) according to the surface normal, roughness, and ior (refractive index). So whatever is behind genuinely appears to warp along the glass’s shape.

The key parameters are ior (refractive index, glass sits near 1.5), thickness (how much material light travels through — more means stronger refraction), and roughness (near 0 for clear glass, higher for frosted). For reflections to look right too, you need an environment texture like in the environment-map entry — with nothing to reflect, glass looks flat.

The demo places a glass icosahedron in front of a colorful backdrop panel so you can see the pattern behind it bend through refraction. Transmission triggers an extra render pass per object, so it gets expensive fast — keep the number of glass objects on screen modest.

When to use

When a transparent material — a glass bottle, lenses, liquid — needs to read as physically real refraction, not just faded color.