Three.js Camera 기본
Perspective Camera
Perspective Camera는 가까운건 작게, 멀리있는건 길게 보이는 카메라이다. 보통 PerspectiveCamera, OrthographicCamera 두 가지 카메라를 많이 사용한다.
위 예시를 보면 lil-gui로 PerspectiveCamera의 인자인 fov, near, far 를 수정할수 있고, CameraHelper를 통해 frustum가 어떻게 보이는지 직관적으로 볼 수 있다.
const cameraHelper = new THREE.CameraHelper(camera);
그리고 이 예제는 특이하게 두 개의 카메라를 이용해서 왼쪽 카메라는 일반적으로 만들던대로 만든 카메라, 오른쪽 카메라는 CameraHelper도 보이게 렌더링하고 더 멀리서 보는 카메라이다.
OrbitControls는 Three.js에서 카메라를 마우스로 쉽게 조작할 수 있게 해주는 컨트롤러이며 Rotate, Zoom, Pan, Damping을 지원한다.
const controls = new OrbitControls(camera, view1Elem as any); controls.target.set(0, 5, 0); controls.update(); Scissor
Scissor는 Three.js에서 화면을 분할해서 각기 다른 장면을 보여주기위한 API이다.
renderer.setScissorTest(true); 로 활성화하며 다음과 같은 함수를 사용할 수 있다.
function setScissorForElement(elem) { const canvasRect = canvas.getBoundingClientRect(); const elemRect = elem.getBoundingClientRect(); // canvas에 대응하는 사각형을 구하기 const right = Math.min(elemRect.right, canvasRect.right) - canvasRect.left; const left = Math.max(0, elemRect.left - canvasRect.left); const bottom = Math.min(elemRect.bottom, canvasRect.bottom) - canvasRect.top; const top = Math.max(0, elemRect.top - canvasRect.top); const width = Math.min(canvasRect.width, right - left); const height = Math.min(canvasRect.height, bottom - top); // canvas의 일부분만 렌더링하도록 scissor 적용 const positiveYUpBottom = canvasRect.height - bottom; renderer.setScissor(left, positiveYUpBottom, width, height); renderer.setViewport(left, positiveYUpBottom, width, height); // 비율 반환 return width / height; } 다른것들보다 중요한건
const positiveYUpBottom = canvasRect.height - bottom; renderer.setScissor(left, positiveYUpBottom, width, height); renderer.setViewport(left, positiveYUpBottom, width, height); 이 부분인데, positiveYUpBottom 이 있는 이유는 Three.js 에서 공간이 캔버스에서의 좌표와 다르기 때문이다. 캔버스의 좌표는 왼쪽 위가 $(0,~0)$이지만, Three.js에서는 왼쪽 아래가 원점이다.
그리고 setScissor와 setViewport로 잘라줄 사각형을 정한다음 renderer.render(scene, camera) 를 이용해 렌더링을 해주면 그 영역에만 렌더링이 된다.
Z-파이팅(Z-fighting, Stitching)
이 예시에서 near 를 0.0001 로 가장 낮게 설정한다면

이런식으로 구들의 Mesh가 깨져서 렌더링되는 현상을 볼 수 있다.
어떤게 더 먼저 렌더링이 되어야 할지 floating point에서 오차가 나며 생기는 현상이며 이를 Z-fighting이라고 부른다.
renderer의 logarithmicDepthBuffer 옵션을 쓰면 해결이 되지만, 성능이 나쁘고 호환성이 좋지않아 쓰지않는다.
따라서 near와 far를 설정함에 있어 주의를 기울여야 한다.
OrthographicCamera
PerspectiveCamera와 다르게 사각형을 그대로 보여주는 카메라이다.
const left = -1; const right = 1; const top = 1; const bottom = -1; const near = 5; const far = 50; const camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far); camera.zoom = 0.2; 처럼 만들수 있고, fov, aspect 속성들 대신 직접 사각형이 어떻게 정의되는지 left, right, top, bottom과 zoom 속성을 통해 조절한다.
camera의 aspect속성이 없고, 처음에 lrtb 를 2 x 2 형체의 정사각형으로 만들어두었기 때문에 $\dfrac{w}{h}$인 aspect 값을 이용해서 left, right를 -aspect, +aspect 로 변경해주면 카메라의 aspect를 맞출 수 있고, 사각형의 크기는 zoom 으로 조절하면 된다.
Comments