Three.js 시작하기
Three.js 기본 요소와 주요 개념1. Three.js의 핵심 구성 요소1.1 렌더러(Renderer)1.2 카메라(Camera)Object3D 클래스주요 카메라 종류1.3 씬(Scene)2. PerspectiveCamera 상세 설명2.1 PerspectiveCamera 생성자2.2 매개변수2.3 사용 예시updateProjectionMatrix() 메서드3. WebGLRenderer 사용하기3.1 렌더러 크기 설정3.2 WebGLRenderer 주요 매개변수3.3 주요 메서드4. 3D 객체 생성 및 애니메이션4.1 Mesh 객체 생성4.2 Scene 렌더링 및 애니메이션 설정4.3 애니메이션 구현 방법requestAnimationFrame vs setAnimationLoop주요 차이점기타 웹 애니메이션 구현 방법
Three.js 기본 요소와 주요 개념
Three.js는 웹 브라우저에서 3D 그래픽을 구현하기 위한 강력한 JavaScript 라이브러리입니다. 이 글에서는 Three.js의 기본 개념과 사용 방법에 대해 알아보겠습니다.
1. Three.js의 핵심 구성 요소
Three.js로 3D 장면을 만들기 위해서는 다음과 같은 기본 요소들이 필요합니다.
- 씬(Scene): 3D 객체들이 배치되는 공간입니다.
- 카메라(Camera): 사용자의 시점을 나타냅니다.
- 렌더러(Renderer): 씬과 카메라를 기반으로 화면에 이미지를 그립니다.
1.1 렌더러(Renderer)
- Scene과 Camera의 객체 데이터를 제공받아 웹사이트에 그려주는 역할을 합니다.
- 주로 WebGLRenderer를 사용하며, 이는 WebGL 기술을 활용합니다.
[주요 기능]
- 렌더링 설정: 안티앨리어싱, 그림자, 포스트 프로세싱 등 다양한 렌더링 옵션을 제공합니다.
- 크기 조절: setSize() 메서드로 렌더링 영역의 크기를 조절할 수 있습니다.
- 렌더링 루프: requestAnimationFrame과 함께 사용하여 연속적인 렌더링을 수행합니다.
1.2 카메라(Camera)
장면을 화면에 담기 위한 카메라입니다. 시야각, 종횡비, 카메라 시작 끝 지점, 카메라 위치 등을 설정해야 합니다.
주로 PerspectiveCamera를 사용합니다. 일반 프로퍼티들은 Object3D 클래스를 참고하면 됩니다.
Object3D 클래스
Object3D는 3D 공간에 존재하는 대다수 객체의 기본 클래스이자 중요한 클래스입니다.
주요 특징
- 계층 구조: 부모-자식 관계를 가질 수 있어 계층 구조를 형성할 수 있습니다.
- 변환: position, rotation, scale 속성으로 객체의 위치, 회전, 크기를 조절할 수 있습니다.
- 가시성: visible 속성으로 객체의 렌더링 여부를 제어할 수 있습니다.
- 이름 지정: name 속성으로 객체에 이름을 부여할 수 있어 식별이 용이합니다.
- 사용자 데이터: userData 객체를 통해 사용자 정의 데이터를 저장할 수 있습니다.
- 이벤트: 다양한 이벤트(예: 클릭, 마우스오버 등)를 처리할 수 있습니다.
Object3D를 상속받는 주요 클래스들
- Camera (PerspectiveCamera, OrthographicCamera 등)
- Light (DirectionalLight, PointLight 등)
- Mesh (3D 모델을 표현)
- Group (여러 Object3D를 그룹화)
- Scene (3D 씬을 나타냄)
주요 카메라 종류
- PerspectiveCamera (원근법 카메라)
- 사람의 눈으로 보는 방식을 모방하여 설계되었습니다.
- 3D 렌더링하는데 가장 널리 쓰이는 카메라입니다.
- OrthographicCamera (정투상도 카메라)
- 렌더링된 이미지에서 객체의 크기는 카메라와의 거리에 관계없이 일정하게 유지됩니다.
- 2D 장면과 UI 요소를 렌더링하는 데 유용합니다.
1.3 씬(Scene)
Scene은 3D 공간에 배치될 모든 객체, 조명, 카메라 등을 포함하는 컨테이너 역할을 합니다.
2. PerspectiveCamera 상세 설명
2.1 PerspectiveCamera 생성자
new THREE.PerspectiveCamera(fov, aspect, near, far)
PerspectiveCamera는 원근법을 사용하는 카메라로, 카메라의 시야 절두체를 정의합니다.
2.2 매개변수
- fov (Field of View) Number
- 시야각을 나타내며, 일반적으로 45~75 사이의 값을 사용합니다.
- 값이 클수록 더 넓은 시야를 보여줍니다.
- aspect Number
- 카메라 프레임의 가로 세로 비율입니다.
- 보통 렌더러의 너비를 높이로 나눈 값을 사용합니다.
- 기본값은 1(정사각형 화면)입니다.
- near Number
- 카메라가 렌더링을 시작하는 가장 가까운 지점입니다.
- 기본값은 0.1입니다.
- 유효 범위는 0보다 크고 현재 far(원평면) 값보다 작습니다.
- far Number
- 카메라가 렌더링을 멈추는 가장 먼 지점입니다.(카메라 절두체 원평면입니다.)
- 기본값은 2000입니다.
2.3 사용 예시
this.camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 100);
여기서 75는 시야각, width / height는 종횡비, 0.1은 near 평면, 100은 far 평면을 나타냅니다.
PerspectiveCamera를 사용하면 3D 공간에서 현실적인 깊이감과 원근감을 구현할 수 있습니다.
*참고: 프로퍼티 수정 후 변경 효과 적용을 위해 updateProjectionMatrix()를 호출해야 합니다.
updateProjectionMatrix() 메서드
- 카메라의 투영 행렬을 업데이트합니다.
- 투영 행렬은 3D 공간의 객체를 2D 화면에 어떻게 투영할지 결정합니다.
호출이 필요한 경우
- 카메라 속성 변경 후
- 화면 크기 변경 시
*주의: 올바른 렌더링 보장 및 필요할 때만 호출함으로써 불필요한 계산으로 인한 성능 저하를 방지해야 합니다.
3. WebGLRenderer 사용하기
3.1 렌더러 크기 설정
private resize() { const width = this.domApp.clientWidth; const height = this.domApp.clientHeight; const camera = this.camera; if (camera) { camera.aspect = width / height; camera.updateProjectionMatrix(); } this.renderer.setSize(width, height); }
3.2 WebGLRenderer 주요 매개변수
- stencil: 스텐실 버퍼 사용 여부
- anti-aliasing: 안티앨리어싱 적용 여부
- 픽셀로 인한 계단 현상 발생 시 주변에 비슷한 색을 칠해 현상을 최소화하는 기법
- 사용되는 알고리즘들: SSAA, MSAA, SMAA, MLAA, TAA, FXAA, DLAA, DLSS2 등
3.3 주요 메서드
- setSize(width: Integer, height: Integer, updateStyle: Boolean): undefined
- 캔버스 크기를 조정하여 장치 픽셀 비율을 고려하고, 뷰포트도 (0,0)에서 시작해 해당 크기에 맞게 설정합니다.
- updateStyle: false로 두면 캔버스 스타일이 변경되지 않습니다.
4. 3D 객체 생성 및 애니메이션
4.1 Mesh 객체 생성
Mesh는 3D를 구성하는 물체를 나타내며, 다음과 같이 생성합니다.
Mesh(geometry, material)
Mesh는 삼각형 폴리곤 메시 기반 객체를 나타내는 클래스입니다.
- geometry: 모양
- material: 재질
사용 예
private setupModel() { const geometry = new THREE.BoxGeometry(1, 1, 1); const material = new THREE.MeshBasicMaterial({ color: 0x44a88 }); this.cube = new THREE.Mesh(geometry, material); this.scene.add(this.cube); }
4.2 Scene 렌더링 및 애니메이션 설정
private render(time: number) { // time은 처음 렌더링 시작된 이후 시간값 (단위: ms) this.update(time); this.renderer.render(this.scene, this.camera!); }
4.3 애니메이션 구현 방법
requestAnimationFrame vs setAnimationLoop
- requestAnimationFrame
- 브라우저의 표준 API
- 일반적인 웹 애플리케이션에서 사용
- 수동으로 루프를 제어해야 함
- VR 콘텐츠에는 적합하지 않음
function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); } animate();
- setAnimationLoop
- Three.js에서 제공하는 메서드
- WebXR 콘텐츠에 최적화
- 자동으로 루프를 관리
- VR 환경에서 더 나은 성능 제공
renderer.setAnimationLoop(function () { renderer.render(scene, camera); });
주요 차이점
- 제어: requestAnimationFrame은 수동 제어, setAnimationLoop는 자동 제어
- 성능: VR 환경에서는 setAnimationLoop가 더 나은 성능 제공
- 구현: requestAnimationFrame은 표준 웹 API, setAnimationLoop는 Three.js 메서드
일반적인 3D 웹 애플리케이션에는 requestAnimationFrame을, VR/AR 콘텐츠에는 setAnimationLoop를 사용하는 것이 좋습니다.
기타 웹 애니메이션 구현 방법
- setInterval 방식
- 애니메이션을 위해 특별히 설계된 메서드가 아님
- 불필요한 콜스택이 많이 발생할 수 있어 애니메이션에 지연이 생길 수 있음
- 브라우저의 렌더링 주기와 동기화되지 않아 프레임 건너뛰기 현상이 발생할 수 있음
- requestAnimationFrame 방식
- 웹 브라우저의 표준 API로, 애니메이션을 위해 특별히 설계됨
- 브라우저의 렌더링 주기와 동기화되어 부드러운 애니메이션 구현 가능
- 일반적으로 1초에 약 60회(60fps) 실행되지만, 디스플레이의 주사율에 따라 달라질 수 있음
- 페이지가 비활성 상태일 때 자동으로 실행을 중지하여 CPU 리소스와 배터리 절약
- 성능 최적화에 도움이 됨
- Three.js의 setAnimationLoop 방식
- Three.js 라이브러리에서 제공하는 메서드
- WebXR (VR/AR) 콘텐츠에 최적화
- 자동으로 애니메이션 루프를 관리
- VR 환경에서 더 나은 성능 제공
예시 코드