구성요소설명
Scene | 3D 객체, 조명, 카메라 등을 포함하는 컨테이너. 3D 공간을 나타냄 |
Mesh | 3D 객체를 나타내며, Geometry(형상)와 Material(재질)로 구성됨 |
Geometry | 객체의 형태와 구조를 정의(예: 크기, 위치) |
Material | 객체의 외관을 결정하는 속성 정의(예: 색상, 텍스처) |
Camera | 사용자의 시점을 정의하며, 렌더링될 내용을 결정 |
Light | 장면에 조명을 추가하여 객체의 가시성과 음영을 조절 |
Renderer | Scene과 Camera를 기반으로 3D 그래픽을 2D 화면에 출력 |
화면을 그리는 역할
Renderer 작성방법1 - 동적으로 Canvas 조립하는 방법
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer);
Renderer 작성방법2 - html에서 Canvas를 가져오는 방법
- 직관적이고, 다른 요소들과 css 스타일을 하는데 더 편리함으로 이 방법 사용
// main.js
const canvas = document.querySelector('#three-canvas');
const renderer = new THREE.WebGLRenderer({
canvas,
// antialias: true,
});
renderer.setSize(window.innerWidth, window.innerHeight);
// index.html
<body>
<script type="module" src="/src/main.js"></script>
<canvas id="three-canvas"></canvas>
</body>
// style.css
body {
margin: 0;
}
#three-canvas {
position: absolute;
left: 0;
top: 0;
}
2. 카메라
PerspectiveCamera vs OrthographicCamera
PerspectiveCamera, 원근 카메라
- 가장 자주 쓰임
const scene = new THREE.Scene();
// 가장 자주 사용되는 원근 카메라, PerspectiveCamera
// THREE.PerspectiveCamera(fov=시야각, aspect=가로세로 비율= 너비/높이 , near=가까운정도, far=먼정도)
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// 카메라의 위치를 조정하지 않으면, default는 0,0,0임
camera.position.x = 1;
camera.position.y = 2;
camera.position.z = 5;
scene.add(camera);
OrthographicCamera, 거리에 따라 크기가 일정하게 보이는 카메라
- 게임 중 디아블로, 롤에 사용됨
const camera = new THREE.OrthographicCamera(
-(window.innerWidth / window.innerHeight),
window.innerWidth / window.innerHeight,
1,
-1,
0.1,
1000
);
// 카메라의 위치를 조정하지 않으면, default는 0,0,0임
camera.position.x = 1;
camera.position.y = 2;
camera.position.z = 5;
camera.lookAt(0, 0, 0); // 0,0,0을 바라보도록
// 줌아웃 하고 싶을 때
camera.zoom = 0.5; // default 1
camera.updateProjectionMatrix();
scene.add(camera);
3. Mesh
- MeshBasicMaterial
- 빛에 영향을 받지 않음 → 조명이 없어도 화면에 보여짐
// Mesh
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({
// color: 0xff000,
// color: '#0xff000',
color: 'red',
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
Mesh만 만든다고 화면에 보이지 않음
⇒ 렌더러를 통해 그려줘야 한다.
// 그리기
renderer.render(scene, camera);
4. Mesh의 울퉁불퉁하게 보이는거 완화하기
antialias를 true로 설정하면 매끄러워짐
const renderer = new THREE.WebGLRenderer({
canvas,
antialias: true, //
});
5. 브라우저 창 사이즈 대응하기
resize 이벤트 리스너를 통해서 창 크기가 변경될 때 마다 setSize 함수를 통해 camera를 다시 설정
// 그리기
renderer.render(scene, camera);
function setSize() {
camera.aspect = window.innerWidth / window.innerHeight;
// updateProjectionMatrix => 카메라 투영에 관련된 값에 변화가 있을 경우 실행해야 함
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.render(scene, camera);
}
// 이벤트
window.addEventListener('resize', setSize);
6. 캔버스 고해상도 이미지 표현하기
const renderer = new THREE.WebGLRenderer({
canvas,
antialias: true,
});
renderer.setSize(window.innerWidth, window.innerHeight);
// console.log(window.devicePixelRatio);
// 1 => 이 값이 2라면, 100픽셀짜리 이미지를 표 현할 때 200픽셀을 사용한다는 의미
renderer.setPixelRatio(window.devicePixelRatio > 1 ? 2 : 1);
7. 배경색&투명도 설정
renderer에 배경색 넣기
const renderer = new THREE.WebGLRenderer({
canvas,
alpha: true, // 배경을 투명하게
});
renderer.setClearColor('#0x00ff00'); // 배경색 설정
renderer.setClearAlpha(0.5); // 0-1 사이로 투명도 조절할 수 있는 메서드
Scene에 배경색 넣기
- Scene의 우선순위가 renderer보다 높기 때문에 Scene의 배경색만 적용됨
renderer.setClearColor('#0x00ff00'); // 적용x
renderer.setClearAlpha(0.2); // 적용x
const scene = new THREE.Scene();
scene.background = new THREE.Color('blue');
8. Light
- MeshStandardMaterial는 빛에 영향을 받는 mesh이다.
- 카메라의 위치, Light, Mesh 위치를 조정하면서 보이도록 설정할 수 있다.
// Light
const light = new THREE.DirectionalLight(0xffffff, 1);
scene.add(light);
// Mesh
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({
color: 'red',
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
9. 애니메이션 기본
Window: requestAnimationFrame() method
window.requestAnimationFrame()
메서드는 브라우저에게 수행하기를 원하는 애니메이션을 알리고 다음 리페인트 바로 전에 브라우저가 애니메이션을 업데이트할 지정된 함수를 호출하도록 요청합니다. 이 메서드는 리페인트 이전에 호출할 인수로 콜백을 받습니다.
requestAnimationFrame
OR setAnimationLoop
둘 다 사용 가능하지만,
vr 같은걸 만들 때는 꼭 setAnimationLoop를 사용해야함
아래 코드는 성능 문제가 있다.
// 그리기
function draw() {
// 각도는 Radian을 사용
// 360도는 2파이
// mesh.rotation.y += 0.1;
mesh.rotation.y += THREE.MathUtils.degToRad(1); // 1도씩 회전
renderer.render(scene, camera);
// requestAnimationFrame(draw);
renderer.setAnimationLoop(draw); // vr 같은걸 만들 때는 꼭 이걸로 사용해야함
}
10. 애니메이션 성능 보정
방법 1 - getElapsedTime()
clock.getElapsedTime()
을 통해 기기에 상관없이 동일한 시간경과를 나타낼 수 있도록 성능을 보정해주자
console.log(clock.getElapsedTime());
로그를 찍어보면 0부터 증가되는 값을 확인할 수 있다.
따라서 값을 더해주는 것이 아니라 할당하는 방식으로 사용한다.
const clock = new THREE.Clock();
clock.getElapsedTime()
// 그리기
const clock = new THREE.Clock();
function draw() {
console.log(clock.getElapsedTime()); // 기기 성능에 상관없이 동일한 시간경과를 나타냄
const time = clock.getElapsedTime();
// mesh.rotation.y += THREE.MathUtils.degToRad(1); // 1도씩 회전
// mesh.rotation.y += 0.1
mesh.rotation.y = time; // 바로 위 코드와는 달리 더해주는게 아니라 바로 할당함.
renderer.render(scene, camera);
// requestAnimationFrame(draw);
renderer.setAnimationLoop(draw); // vr 같은걸 만들 때는 꼭 이걸로 사용해야함
}
방법 2 - getDelta()
이전 draw 함수 시작과 다음 draw 함수 실행의 시간 차를 나타냄
const clock = new THREE.Clock();
const delta = clock.getDelta();
// 그리기
const clock = new THREE.Clock();
function draw() {
const delta = clock.getDelta();
console.log(delta);
mesh.rotation.y += delta;
renderer.render(scene, camera);
// requestAnimationFrame(draw);
renderer.setAnimationLoop(draw);
}
그러나 둘을 동시에 사용하면 안된다.
11. gsap 애니메이션 라이브러리 사용하기
// gsap
gsap.to(
mesh.position, // 변화시키고 싶은 object,
{
duration: 1,
y: 2,
}
);
참고
https://www.inflearn.com/course/3d-%EC%9D%B8%ED%84%B0%EB%9E%99%ED%8B%B0%EB%B8%8C-%EC%9B%B9/dashboard
'Three.js' 카테고리의 다른 글
Three.js 파티클2 - 이미지 사용해서 랜덤으로 파티클 생성하기 (0) | 2025.02.02 |
---|---|
Three.js 파티클 1 - 기본 지오메트리 파티클&랜덤 파티클로 별 표현하기 (0) | 2025.02.02 |