November 09, 2024
three.js스터디에 참가하며 공부하고 있다. 이번엔 Three.js의 3가지 기본 요소 중 하나인 카메라에 대해 공부해보았다.
3D 환경에서 카메라는 사용자가 보는 시점과 전체적인 시각적 경험을 결정하는 중요한 요소이다.
3D 세계를 어떻게 관찰하고 탐험할지를 정의하기에 카메라는 3D렌더링에 있어서 핵심적인 역할을 한다.
카메라의 위치와 방향을 조정하여 3D 공간에서의 특정 객체에 포커스를 맞추거나 특정 장면을 강조할 수 있다.
Three.js에서는 대표적으로 PerspectiveCamera
와 OrthographicCamera
를 사용한다.
PerspectiveCamera
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
(참고: https://www.youtube.com/watch?v=qe3mahuoYlw)
window.innerWidth / window.innerHeight
값을 사용해 설정한다.
camera.position.x = 0.4 // 카메라가 오른쪽으로 가기에 물체는 왼쪽으로 간다.
camera.position.x =0 //카메라가 가운데
camera.position.x = -0.4 //카메라가 왼쪽으로 가기에 물체는 오른쪽으로 간다.
camera.position.y=0.5 카메라가 위로 가기에 물체는 아래로 내려간다.
camera.position.y = -0.5 // 카메라가 아래로 내려가기에 물체는 위로 간다.
camera.position.z = 10 카메라가 뒤에 있어서 물체가 작아 보인다.
camera.position.z = -1 카메라가 물체 뒤에 있어서, 물체가 안보인다.
const fov = 75; // 시야각(Field of View)
const aspect = window.innerWidth / window.innerHeight; // 종횡비
const near = 0.1; // 카메라가 인식할 수 있는 가장 가까운 거리
const far = 1000; // 카메라가 인식할 수 있는 가장 먼 거리
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 0, 10); // 카메라의 위치 설정
Orthographic Camera
const camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far);
const aspect = window.innerWidth / window.innerHeight;
const cameraSize = 10;
const camera = new THREE.OrthographicCamera(-cameraSize * 5, cameraSize * 5, cameraSize , -cameraSize , 0.1, 1000);
camera.position.set(0, 0, 10); // 카메라 위치 설정
camera.lookAt(0, 0, 0); // 카메라가 바라보는 지점 설정
cameraSize
는 카메라의 줌에 해당하는 역할을 한다. 값을 작게 설정할수록 확대되고, 크게 설정할수록 시야 범위가 넓어진다.카메라의 위치와 방향을 조정하여 원하는 장면을 연출할 수 있다.
Three.js에서는 카메라의 position
, rotation
, lookAt
메서드를 사용해 카메라의 위치와 방향을 지정할 수 있다.
camera.position
camera.position.set(x, y, z)
를 통해 설정한다.camera.position.set(5, 5, 10); // 카메라를 오른쪽 위, 먼 곳으로 이동
camera.rotation
rotation.x
, rotation.y
, rotation.z
로 개별 설정이 가능하다.x축 회전 : 위아래로 바라보는 각도를 조절 (pitching)
y축 회전 : 좌우로 바라보는 각도를 조절 (yawing)
z축 회전 : 카메라가 뒤집어지는 각도를 조절 ( rolling)
(참고: 네이버 블로그 | Can’t you fill my Heart? Yaw Pitch Roll 정의)
camera.rotation.x = Math.PI / 4; // x축 기준 45도 회전
camera.rotation.y = Math.PI / 6; // y축 기준 30도 회전
camera.lookAt
const target = new THREE.Vector3(0, 0, 0); // 바라볼 지점 설정
camera.lookAt(target); // 카메라가 해당 위치를 바라보도록 설정
camera.lookAt(x, y, z)
를 사용하여 카메라의 시선 방향을 지정할 수 있다camera.lookAt(x, y, z)
형태로 좌표를 직접 입력x
, y
, z
값으로 직접 카메라가 바라볼 좌표를 지정하는 방식x, y, z
좌표로 향하게 된다.camera.lookAt(0, 0, 0);
camera.lookAt(vector3)
형태로 Vector3
객체를 입력Vector3
는 3D 공간의 좌표를 나타내는 객체이므로 이를 통해 보다 유연하게 좌표를 지정할 수 있다.const target = new THREE.Vector3(0, 0, 0); // 바라볼 지점 설정
camera.lookAt(target); // 카메라가 해당 위치를 바라보도록 설정
rotation
은 직접 조작하기보다는 lookAt
메서드를 사용해 특정 지점을 바라보도록 설정하는 경우가 많다.camera.rotation
은 카메라의 방향을 수동으로 조절할 때 쓰고, camera.lookAt()
은 카메라가 특정 지점을 바라보게 설정할 때 유용하다.
const axesHelper = new THREE.AxesHelper();
scene.add(axesHelper)
기본 카메라 이동 애니메이션
function animateCamera() {
requestAnimationFrame(animateCamera);
camera.position.x += 0.05; // 카메라를 오른쪽으로 이동
camera.lookAt(new THREE.Vector3(0, 0, 0)); // 특정 지점을 계속 바라보게 함
renderer.render(scene, camera); // 씬 렌더링
}
animateCamera();
camera.position.x
를 점진적으로 증가시키면서 카메라가 왼쪽에서 오른쪽으로 이동한다.
이때, 카메라가 씬의 특정 지점만을 바라보도록 lookAt
을 설정하여 객체가 고정된 상태로 보이는 효과를 준다.
GSAP을 사용한 부드러운 애니메이션
fromTo
, to
, timeline
등을 활용해 더 쉽게 부드러운 애니메이션을 추가할 수 있다.Three.js는 카메라와 상호작용할 수 있는 다양한 방법을 제공한다. 마우스나 키보드 이벤트를 통해 카메라의 움직임을 제어할 수 있으며, 이를 통해 유저가 직접 시점을 조작할 수 있도록 할 수 있다.
OrbitControls - 가장 기본적이고 있기 있는 카메라 컨트롤
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true; // 부드러운 움직임을 추가
enableZoom
, enablePan
, maxPolarAngle
과 같은 다양한 옵션을 제공하여 카메라 조작을 세부적으로 설정할 수 있다.enableDamping
을 활성화하면 움직임이 부드러워져 사용자가 조작할 때 더 자연스러운 효과를 준다.Fly Controls
ex) https://threejs.org/examples/?q=Fly#misc_controls_fly
DragContorls
ex) https://threejs.org/examples/?q=Drag#misc_controls_drag
마우스 이벤트
마우스 이동에 따라 카메라의 위치를 동적으로 조정할 수 있습니다.
window.addEventListener('mousemove', (event) => {
const x = (event.clientX / window.innerWidth) * 2 - 1;
const y = -(event.clientY / window.innerHeight) * 2 + 1;
camera.position.x = x * 10;
camera.position.y = y * 10;
camera.lookAt(scene.position);
});