[Three.js] Geometry, Materials, Mesh

🌐

Three.js에서 3D Object를 구성하는 세 가지 핵심 요소인 Geometry와 Materials, 그리고 Mesh에 대해 알아보자.

Geometry란?

Geometry는 3D 객체의 형태를 정의하는 꼭지점(vertices)과 면(faces), 선(line)의 집합이다. 쉽게 말해서 3D 물체의 '골격'이라고 생각하면 된다. 아래 예제 코드를 보자.

// 사용자 정의 삼각형 만들기
const geometry = new THREE.BufferGeometry();

// 삼각형의 꼭지점 좌표
const vertices = new Float32Array([
    -1.0, -1.0, 0.0,  // v0
     1.0, -1.0, 0.0,  // v1
     0.0,  1.0, 0.0   // v2
]);

// 버퍼 속성으로 지오메트리에 할당
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));

이런 식으로 Matrix 형태의 데이터를 전달하여 화면에 그릴 수 있다. 이와 관련된 더 많은 옵션은 공식 문서 링크에서 찾을 수 있다.

기본 Geometry 종류

Three.js에서는 다양한 기본 도형을 만들 수 있는 Geometry 클래스를 제공한다.

// 박스
const boxGeometry = new THREE.BoxGeometry(width, height, depth);

// 구
const sphereGeometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments);

// 평면
const planeGeometry = new THREE.PlaneGeometry(width, height);

// 원기둥
const cylinderGeometry = new THREE.CylinderGeometry(radiusTop, radiusBottom, height);

// 원뿔
const coneGeometry = new THREE.ConeGeometry(radius, height);

// 도넛 모양
const torusGeometry = new THREE.TorusGeometry(radius, tube, radialSegments);

Materials란?

Material은 3D 객체의 외관을 정의한다. 색상, 투명도, 텍스처 등 객체가 어떻게 보일지 결정하는 모든 시각적 속성을 포함한다. 아래와 같은 주요 속성들을 사용한다.

const material = new THREE.MeshStandardMaterial({
    // 기본 속성들
    transparent: true,     // 투명도 사용 여부
    opacity: 0.5,         // 불투명도 (0.0 ~ 1.0)
    side: THREE.DoubleSide, // 양면 렌더링
    visible: true,        // 가시성
    wireframe: false,     // 와이어프레임 모드

    // 색상 관련
    color: 0xff0000,      // 기본 색상
    emissive: 0x000000,   // 자체 발광 색상

    // 등등...
});

주요 Material 종류와 특징

1. MeshBasicMaterial

가장 단순한 Material로, 조명의 영향을 받지 않는다. 성능이 좋고 단순한 용도에 적합하다. 조명 계산이 없기 때문에 가장 빠르게 렌더링할 수 있다.

2. MeshStandardMaterial

물리 기반 렌더링(PBR, Physically based rendering)을 사용하는 Material이다. PBR은 실제 물리 법칙을 기반으로 빛의 상호작용을 시뮬레이션하여 매우 사실적인 결과물을 만들어낸다. 그렇기에 다른 Material들 보다 렌더링의 계산 비용이 더 많이 든다.

3. MeshPhongMaterial

MeshPhongMaterial은 광택 있는 표면을 표현하는데 적합한 Material이다. Phong 셰이딩 모델을 사용하여 하이라이트와 반사광을 계산하며, 플라스틱이나 도자기 같은 Material을 표현할 때 자주 사용된다.

new THREE.MeshBasicMaterial({
  color: color,
  side: THREE.DoubleSide,
});
new THREE.MeshStandardMaterial({
  color: color,
  roughness: 0.5,
  metalness: 0.5,
  side: THREE.DoubleSide,
}),
new THREE.MeshPhongMaterial({
  color: color,
  shininess: 60,
  specular: 0x444444,
  side: THREE.DoubleSide,
}),

MeshBasicMaterial

MeshStandardMaterial

MeshPhongMaterial

Map의 기본 개념 및 종류

Material에는 다양한 Map을 사용하여 객체의 외관을 더욱 사실적이고 풍부하게 표현할 수 있다. Map은 텍스처를 3D 객체의 표면에 매핑하는 방법을 제공하며, 각각의 Map은 서로 다른 시각적 특성을 제어하는데 사용된다.

1. map

기본적인 색상 텍스처를 적용하는 맵이다.

const textureLoader = new THREE.TextureLoader();
const colorTexture = textureLoader.load('hangyodon.avif');

const material = new THREE.MeshStandardMaterial({
    map: colorTexture
});

2. normalMap

표면의 디테일을 표현하는 맵이다.

const normalTexture = textureLoader.load('hangyodon.avif');

const material = new THREE.MeshStandardMaterial({
    normalMap: normalTexture,
    normalScale: new THREE.Vector2(1, 1)  // 노말맵의 강도 조절
});

3. roughnessMap

표면의 거칠기를 제어하는 맵이다. MeshStandardMaterial에서 사용된다.

const roughnessTexture = textureLoader.load('hangyodon.avif');

const material = new THREE.MeshStandardMaterial({
    roughnessMap: roughnessTexture,
    roughness: 1.0  // 기본 거칠기 값
});

Meshmap

MeshnormalMap

MeshroughnessMap

Mesh

이제 뼈대 역할을 하는 Geometry와, 외관을 정의하는 역할을 하는 Material을 합쳐주는 객체가 Mesh이다. Mesh는 Three.js에서 Object3D를 상속받은 클래스로, 3D 공간에 렌더링될 수 있는 객체를 생성한다.

const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

Mesh의 속성과 메서드

위치(Position)

// 위치 설정
mesh.position.set(x, y, z);
// 또는
mesh.position.x = 1;
mesh.position.y = 2;
mesh.position.z = 3;

회전(Rotation)

// 위치 설정
mesh.position.set(x, y, z);
// 또는
mesh.position.x = 1;
mesh.position.y = 2;
mesh.position.z = 3;

크기(Scale)

// 크기 설정
mesh.scale.set(x, y, z);
// 또는
mesh.scale.x = 2;  // X축으로 2배
mesh.scale.y = 0.5; // Y축으로 0.5배
mesh.scale.z = 1;   // Z축은 변화 없음

마무리

Three.js의 핵심 구성 요소들에 대해 살펴보았다. Geometry로 3D 객체의 형태를 정의하고, Material로 객체의 시각적 특성을 표현하며, 이 둘을 결합한 Mesh를 통해 실제 화면에 렌더링되는 3D 객체를 만들 수 있었다.

이번 글에서는 기본적인 예제들을 통해 핵심 개념을 살펴보았지만, Three.js는 이보다 훨씬 더 다양하고 강력한 기능들을 제공하고 있으니 나중에 더 자세히 알아보면 좋을 것 같다.

또한 3D 그래픽스의 특성상, 객체가 복잡해질수록 더 많은 컴퓨팅 자원이 필요하다. 따라서 실제 프로젝트에서는 아래와 같은 항목들을 신경쓰며 작업해야 한다! (그렇지 않으면 모바일에서는 터지는 경우가 잦다...)

  • 적절한 폴리곤 수 유지
  • 불필요한 객체의 메모리 해제

🔎 참조