Three.js로 웹에서 3D 구현하기
전부터 배우고 싶었는데 미루다 미루다 드디어 입문했습니다 😎
지금 하는 일에 도움은 안되지만 순전히 재미만을 위한 학습 너무 좋아요 푸하항
사실 저는 6년 전 쯤, 3D 모델링을 잠깐 배워본 적이 있었고, 한 때는 관련 일을 꿈꾸기도 해서 그런지 이번 강의가 너무 재밌었어요. 그리고 PerspectiveCamera 라든가 ... AmbientLight, texture 등 한 때는 자주 봤던(?) 단어들을 다시 보니 반갑기도 했어요.
아무튼 도전하기 어려운 Three.js를 이 강의를 통해 쉽게 훑어볼 수 있었네요.강의에 대한 내용은 맨 아래에 적어놨습니다!
Three.js 의 특징
- 자바스크립트 기반의 3D 라이브러리
- WebGL기반으로 동작
- 3D모델링, 렌더링, 애니메이션 구현
- 이벤트를 통한 인터렉션 표현 가능
- 블렌더, Cindema4D 등으로 모델링한 오브젝트를 import할 수 있음
Three.js 의 기본 구조
이 셋만 알면 된다.
Scene, Camera, Renderer
Scene
- 모든 3D 오브젝트가 배치되는 가장 기본의 객체, 공간
- 화면에 보여질 오브젝트는 Scene에 추가되어야 한다.
- add() 메서드를 통해 추가
Camera
- Scene를 보는 시점.
- PerspectiveCamera와 OrthographicCamera를 주로 사용
- PerspectiveCamera(fov, aspect, near, far)로 생성
fov는 시야각 (기본값: 50) / aspect는 종횡비 / near, far는 최소, 최대 거리로 이 사이에만 렌더링된다.
PerspectiveCamera | 객체에 원근감을 적용하여 3D 공간감을 표현 |
OrthographicCamera | 객체에 원근감 적용하지 않아서 평면적인 투영 |
Render
- Scene와 Camera를 받아서 실제 보여지는 이미지를 생성
- canvas 요소다.
- new THREE.WebGLRenderer()를 통해서 Render 객체 생성
- 해당 Render 객체의 메서드 render(scene, camera) 를 통해서 렌더링한다.
Three.js 의 3D 오브젝트
Mesh
- 3D 객체를 의미
- geometry와 material로 구성되어 있다.
Geometry
- 형태를 의미하며 다양한 형태를 생성할 수 있다.
육면체 |
new THREE.BoxGeometry(1, 1, 1);
|
|
원뿔 |
new THREE.ConeGeometry(0.5, 1, 30);
|
|
원기둥 |
new THREE.CylinderGeometry(0.5, 0.8, 1, 10);
|
|
구 |
new THREE.SphereGeometry(1, 20);
|
|
평면 |
new THREE.PlaneGeometry(1, 2);
|
|
평면(원) |
new THREE.CircleGeometry(1, 32);
|
|
튜브 |
new THREE.TorusGeometry(1, 0.5);
|
Material
- 재질을 의미
단색 (명암 표현 X, 출력 확인용) |
MeshBasicMaterial |
표준 | MeshStandardMaterial |
피지컬 (표준의 확장, 고급 물리기반 렌더 제공) |
MeshPhysicalMaterial |
퐁 : 광택 표현 | MeshPhongMaterial |
Material
1. AmbientLight (color, intensity)
- 전역으로 빛을 발산
- 그림자X
- 출력과 재질 확인용
2. DirectionalLight (color, intensity)
- 방향성 광원 마치 햇빛
- 거리와 상관없이 동일한 빛의 효과 적용
- 그림자O
- 타겟은 기본 0,0,0 이지만 조정가능
3. PointLight ((color, intensity, distance))
- 한 점에서 방출되는 빛 마치 전구
4. SpotLight (color, intensity, distance, angle, penumbra)
- 한 점에서 원뿔형으로 빛이 방출
- 스포트라이트
- 그림자O
- 기본 위치는 0,1,0
- (색, 강도, 거리, 각도, 흐림효과)
5. HemisphereLight (color, color)
- 위 아래로 빛이 방출
- 하늘면, 바닥면 색상 지정
- 그림자X
Shadow
1. 그림자 추가를 위한 설정1
렌더객체.shadowMap.enabled = true;
2. 그림자 추가를 위한 설정2 - 이 빛으로 그림자를 만들도록 설정
빛객체.castShadow = true;
3. 그림자 추가를 위한 설정3 - 설정한 빛에 의해 그림자를 만들도록 설정
Mesh객체.castShadow = true;
4. 그림자 추가를 위한 설정4 - 그림자를 받도록 설정
Mesh객체.receiveShadow = true;
Texture
1. normalMap
- 표면의 빛을 왜곡해서 입체감 표현
- 실제 형태가 변하지는 않음
2. roughnessMap
- 명암에 따라 거칠기, 광택이 표현
3. displacementMap
- 명암에 따라 표면의 높낮이를 조절
- 형태가 변함
Three.js 의 3D 오브젝트 조작
(1) 위치변경 : position 값으로 설정
(2) 회전변경 : rotation 값으로 설정
단, 라디안 값 기준(360° = 2π)이라서 degToRad() 를 통해 각도를 라디안으로 변환하여 사용해야한다.
(3) 크기변경 : scale 값으로 설정
// position
mesh.position.x = 2;
mesh.position.y = 1;
mesh.position.set(0, 2, 1);
// rotation
mesh.rotation.y = 360;
// 회전의 기준이 라디안 값이라 다르게 출력된다.
// 내가 아는 각도로 변경되도록 degToRad 메서드를 사용
mesh.rotation.y = THREE.MathUtils.degToRad(360);
// scale
mesh.scale.x = 1.2;
Three.js 의 유용한 기능
애니메이션
- 자바스크립트 requestAnimationFrame의 콜백 함수를 활용
- 오브젝트를 변경후 render를 하는 메서드의 호출을 반복하며 애니메이션을 표현
// 애니메이션을 화면에 출력
function animate() {
// 박스를 회전 + 렌더
cube.rotation.y += 0.01;
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
animate(); // ==> 박스를 회전 + 렌더를 계속 반복함
이벤트
- 오브젝트를 변경하고 업데이트를 하는 이벤트를 등록하여 사용
// // resize 이벤트 추가 (화면 사이즈 변경 이벤트)
window.addEventListener('resize', () => {
// 1. 카메라의 종횡비 변경
// updateProjectionMatrix로 속성 업데이트
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
// 2. 렌더러의 크기 변경 (현재 윈도우의 크기)
renderer.setSize(window.innerWidth, window.innerHeight);
}); // ==> 화면 크기를 변경하면 렌더러의 크기도 변경된다.
AxesHelper
- 좌표계를 표시함
- 오브젝트의 위치와 회전을 쉽게 파악할 수 있음 (Scene에도 가능)
const axesHelper = new THREE.AxesHelper(10);
scene.add(axesHelper);
OrbitControls
- 마우스로 3D 모델을 회전, 확대, 축소하여 확인할 수 있는 기능
- 줌, 회전, 마우스이동, 조작범위 등 설정 가능
- 자동회전, 스피드, 관성 설정 가능
import { OrbitControls } from "../../node_modules/three/examples/jsm/controls/OrbitControls.js";
// OrbitControls
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableZoom = true;
controls.enableRotate = true;
controls.enablePan = true;
controls.enableDamping = true;
function animate() {
// 업데이트
renderer.render(scene, camera);
controls.update();
requestAnimationFrame(animate);
}
animate();
Group
- 여러 Mesh들을 그룹으로 묶어서 한번에 관리할 수 있다.
const group = new THREE.Group();
group.add(mesh1);
scene.add(group);
외부 모델링 가져오기
- GLTFLoader를 활용하기 위해 .gltf, .glb 확장자의 3D 모델링을 가져올 수 있다.
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
// 외부모델링
const modelLoader = new GLTFLoader();
modelLoader.load('./src/models/외부모델링.glb',
(gltf) => {
const model = gltf.scene;
// 외부모델링의 속성은 여기서 변경
model.position.set(5, 0.5, 2);
model.rotation.y = Math.PI / -10;
scene.add(model);
// 외부모델링 그림자 적용하려면
// 내부 mesh에 그림자 속성 변경해야함
for (const mesh of model.children) {
mesh.castShadow = true;
}
})
재밌는 three.js
조만간 뭐 하나 만들어서 올려보겠습니다
'🧠 저장 > etc.' 카테고리의 다른 글
무료 모션그래픽 툴 Phase 사용후기 (0) | 2024.05.29 |
---|---|
SVG와 Canvas 간단 비교 (0) | 2024.03.30 |
Lottie.js 간단 정리 (0) | 2024.03.25 |
웹팩(모듈 번들러) 간단 정리 (0) | 2024.02.02 |
npm(노드 패키지 매니저) 간단 정리 (0) | 2023.11.03 |