Three.js는 개발자들이 쉽게 3D 도형을 만들 수 있도록 다양한 기본 도형들을 제공합니다. 이러한 미리 정의된 3D 도형들을 'Primitives'라고 부릅니다.
Geometry는 3D 공간에서 물체의 형태를 정의하는 정점(vertices)들의 집합입니다. Primitives보다 더 기본적인 개념으로, 3D 물체의 뼈대라고 할 수 있죠. 예를 들어, 하나의 박스를 만들 때 두 가지 방법으로 접근할 수 있습니다.
1. Primitives 사용 (간단한 방법)
const boxGeometry = new THREE.BoxGeometry(1, 1, 1);2. BufferGeometry로 직접 정의 (세밀한 제어 가능)
1const geometry = new THREE.BufferGeometry();
2
3// 정점 데이터를 더 읽기 쉽게 구조화
4const vertices = new Float32Array([
5 // Front face
6 -1.0, -1.0, 1.0, // v0: 좌하단
7 1.0, -1.0, 1.0, // v1: 우하단
8 1.0, 1.0, 1.0, // v2: 우상단
9 -1.0, 1.0, 1.0, // v3: 좌상단
10]);
11
12// 각 정점당 x, y, z 3개의 값을 사용
13geometry.setAttribute(
14 'position',
15 new THREE.BufferAttribute(vertices, 3)
16);BufferGeometry는 Three.js에서 3D 모델의 기하학적 데이터를 효율적으로 저장하고 처리하기 위한 컨테이너입니다. 여러 BufferAttribute들의 집합으로 구성되며, 각 속성은 정점(vertex)의 특정 특성을 정의합니다. *모든 기본 제공 Geometry들이 이를 기반으로 만들어집니다.
각 정점(vertex)은 다음과 같은 속성들을 가질 수 있습니다.
| 속성 | 설명 | 용도 |
|---|---|---|
| Position | 3차원 좌표 (x, y, z) | 정점의 위치 정의 |
| Normal | 법선 벡터 | 조명 계산, 표면 방향 정의 |
| Color | RGB 색상 값 | 정점별 색상 지정 |
| UV | 2차원 좌표 (u, v) | 텍스처 매핑 |
| Index | 정점 참조 번호 | 면(삼각형) 구성 |
데이터 구조의 이해
1// 정점 데이터 예시
2const positions = new Float32Array([
3 // x, y, z // 설명
4 -1.0, -1.0, 1.0, // 정점 0
5 1.0, -1.0, 1.0, // 정점 1
6 1.0, 1.0, 1.0 // 정점 2
7]);
8
9const normals = new Float32Array([
10 0, 0, 1, // 정점 0의 법선
11 0, 0, 1, // 정점 1의 법선
12 0, 0, 1 // 정점 2의 법선
13]);
14💡 정육면체 구성의 이해
정육면체를 만들 때 필요한 정점 수는 다음과 같이 계산됩니다.
총 정점 수 = 면 개수 × 삼각형/면 × 정점/삼각형
= 6 × 2 × 3
= 36개🔍 왜 36개나 필요할까?
기본 도형 - BoxGeometry (상자) - SphereGeometry (구) - CylinderGeometry (원통) - PlaneGeometry (평면) - TorusGeometry (도넛) 고급 도형 - ExtrudeGeometry (돌출) - TextGeometry (텍스트) - TubeGeometry (관)
다면체 - IcosahedronGeometry (20면체) - OctahedronGeometry (8면체)
*이보다 더 많은 Geometry와 예제 코드는 Three.js docs에서 살펴보실 수 있습니다.
실제 예제를 통해 Geometry의 활용법을 살펴보겠습니다.
const saturnGeometry = new THREE.SphereGeometry(1.5, 128, 128);*SphereGeometry는 구체를 만드는 기하학적 도형입니다.
매개변수
*세그먼트가 많을수록 더 부드러운 구체가 생성됩니다.
const ringGeometry = new THREE.RingGeometry(innerRad, outerRad, 256);*RingGeometry는 2D 원형 디스크 모양을 생성합니다.
매개변수
1const rings = [
2 createRing(2.0, 2.3, 0x3c3c3c, 0.9), // 가장 안쪽 고리
3 createRing(2.3, 2.8, 0xb0a89b, 0.8),
4 createRing(2.8, 3.2, 0x8b7355, 0.7),
5 createRing(3.2, 3.5, 0x6d6152, 0.6),
6 createRing(3.5, 3.7, 0x4a4a4a, 0.4) // 가장 바깥쪽 고리
7];5개의 서로 다른 고리를 생성하여 실제 토성의 고리와 비슷한 모양을 구현했습니다.
각 고리마다 반지름 범위, 색상, 투명도를 다르게 했습니다.
const tilt = (15 * Math.PI) / 180; // 15도 기울기
rings.forEach((ring) => {
ring.rotation.x = Math.PI / 2; // 90도 회전 (수평 배치)
ring.rotation.z = tilt; // 15도 기울기 적용
});실제 토성의 고리와 유사한 모습을 연출하기 위해서 고리들을 수평으로 배치하고 15도 기울어진 형태로 구현했습니다.
Three.js의 Geometry 시스템을 살펴보면서 실습까지 해보니 기본 제공되는 도형들에 감사함을 느낄 수 있었습니다. BufferGeometry를 직접 만져보려니 상당히 어지러웠거든요.
실습 예제 토성의 왕사탕… 무늬는 얼떨결에 작업해보다가 만들어 낸 것인데 귀여운 맛도 있고… 좀 두었다가 틈틈이 개선해보려고합니다. 이유는 귀여워서 입니다. 👻
글 작성 시 참고한 자료: https://threejs.org/manual/#ko/primitives