Three.js 기초
Three.js는 WebGL을 쉽게 사용할 수 있게 해주는 JavaScript 3D 라이브러리입니다. 복잡한 WebGL API를 추상화하여 직관적인 API로 3D 그래픽을 구현할 수 있습니다.
기본 구성 요소
import * as THREE from 'three';
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x1a1a2e);
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.set(0, 2, 5);
const renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);
3D 객체 생성
const boxGeometry = new THREE.BoxGeometry(1, 1, 1);
const boxMaterial = new THREE.MeshStandardMaterial({
color: 0x00ff88,
metalness: 0.3,
roughness: 0.4
});
const box = new THREE.Mesh(boxGeometry, boxMaterial);
box.position.set(-2, 0.5, 0);
box.castShadow = true;
scene.add(box);
const sphereGeometry = new THREE.SphereGeometry(0.7, 32, 32);
const sphereMaterial = new THREE.MeshStandardMaterial({
color: 0xff6b6b,
metalness: 0.7,
roughness: 0.2
});
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.set(0, 0.7, 0);
sphere.castShadow = true;
scene.add(sphere);
const torusGeometry = new THREE.TorusGeometry(0.5, 0.2, 16, 32);
const torusMaterial = new THREE.MeshStandardMaterial({ color: 0x4ecdc4 });
const torus = new THREE.Mesh(torusGeometry, torusMaterial);
torus.position.set(2, 0.7, 0);
torus.castShadow = true;
scene.add(torus);
const planeGeometry = new THREE.PlaneGeometry(10, 10);
const planeMaterial = new THREE.MeshStandardMaterial({
color: 0x333333,
side: THREE.DoubleSide
});
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -Math.PI / 2;
plane.receiveShadow = true;
scene.add(plane);
조명 설정
const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(5, 10, 5);
directionalLight.castShadow = true;
directionalLight.shadow.mapSize.width = 2048;
directionalLight.shadow.mapSize.height = 2048;
scene.add(directionalLight);
const pointLight = new THREE.PointLight(0xff9900, 1, 10);
pointLight.position.set(0, 3, 0);
scene.add(pointLight);
애니메이션 루프
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const elapsed = clock.getElapsedTime();
box.rotation.y = elapsed * 0.5;
box.rotation.x = elapsed * 0.3;
sphere.position.y = 0.7 + Math.sin(elapsed * 2) * 0.3;
torus.rotation.x = elapsed;
torus.rotation.z = elapsed * 0.5;
renderer.render(scene, camera);
}
animate();
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
카메라 제어 (OrbitControls)
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.minDistance = 2;
controls.maxDistance = 20;
controls.maxPolarAngle = Math.PI / 2;
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
성능 최적화 팁
| 기법 | 설명 |
|---|---|
| 지오메트리 병합 | BufferGeometryUtils.mergeGeometries로 드로우콜 감소 |
| LOD | 거리에 따라 디테일 수준 변경 |
| Frustum Culling | 카메라 밖 객체 자동 제외 (기본 활성) |
| 텍스처 압축 | KTX2 / Basis 텍스처 포맷 사용 |
| 인스턴싱 | InstancedMesh로 동일 객체 대량 렌더링 |
- Three.js는 초보자도 쉽게 3D를 시작할 수 있는 최고의 라이브러리
- React에서는 React Three Fiber(@react-three/fiber)로 선언적 사용 가능
- GLTF/GLB 포맷으로 Blender 등에서 만든 3D 모델 임포트 가능
- WebGPU 지원이 추가되어 차세대 그래픽 API 활용 가능
- drei(@react-three/drei) 라이브러리로 유용한 헬퍼 컴포넌트 활용
댓글 0