유리 트랜스미션

Glass transmission

투명한 척 알파값으로 흐리게 하는 대신, 뒤 배경을 실제로 굴절시켜 비치게 만드는 물리 기반 유리 재질.

다른 이름: 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는 그냥 배경과 색을 섞을 뿐 굴절이 없어 "반투명한 색깔"처럼 보입니다. MeshPhysicalMaterial의 transmission(0~1)은 다릅니다 — 값을 1로 두면 렌더러가 매 프레임 그 오브젝트 "뒤"를 별도로 한 번 더 렌더링해 텍스처로 만들고, 그 텍스처를 표면의 법선과 roughness·ior(굴절률)에 따라 휘어서(굴절시켜) 다시 그립니다. 그래서 뒤에 있는 물체가 유리 형태를 따라 진짜로 휘어 보입니다.

주요 파라미터는 ior(굴절률, 유리는 1.5 근처), thickness(빛이 통과하는 두께 — 클수록 굴절이 강해짐), roughness(0에 가까울수록 선명한 유리, 커질수록 젖빛 유리)입니다. 반사까지 자연스러우려면 environment-map 항목과 같은 환경 텍스처가 필요합니다 — 반사할 게 없으면 유리가 밋밋해 보입니다.

데모는 색이 있는 배경 판 앞에 유리 아이코사헤드론을 놓아 굴절로 뒤 패턴이 휘는 걸 보여줍니다. transmission은 오브젝트마다 추가 렌더 패스를 발생시켜 비용이 크므로, 화면에 유리 오브젝트를 너무 많이 두지 않는 게 좋습니다.

언제 쓰나

유리병·안경·액체 등 실제 굴절이 있는 투명 재질을 사실적으로 보여줘야 할 때.