Perspective Camera

Perspective Camera는 가까운건 작게, 멀리있는건 길게 보이는 카메라이다. 보통 PerspectiveCamera, OrthographicCamera 두 가지 카메라를 많이 사용한다.

위 예시를 보면 lil-guiPerspectiveCamera의 인자인 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에서는 왼쪽 아래가 원점이다.

그리고 setScissorsetViewport로 잘라줄 사각형을 정한다음 renderer.render(scene, camera) 를 이용해 렌더링을 해주면 그 영역에만 렌더링이 된다.

Z-파이팅(Z-fighting, Stitching)

이 예시에서 near0.0001 로 가장 낮게 설정한다면

image.png

이런식으로 구들의 Mesh가 깨져서 렌더링되는 현상을 볼 수 있다.

어떤게 더 먼저 렌더링이 되어야 할지 floating point에서 오차가 나며 생기는 현상이며 이를 Z-fighting이라고 부른다.

renderer의 logarithmicDepthBuffer 옵션을 쓰면 해결이 되지만, 성능이 나쁘고 호환성이 좋지않아 쓰지않는다.

따라서 nearfar를 설정함에 있어 주의를 기울여야 한다.

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, bottomzoom 속성을 통해 조절한다.

cameraaspect속성이 없고, 처음에 lrtb 를 2 x 2 형체의 정사각형으로 만들어두었기 때문에 $\dfrac{w}{h}$인 aspect 값을 이용해서 left, right를 -aspect, +aspect 로 변경해주면 카메라의 aspect를 맞출 수 있고, 사각형의 크기는 zoom 으로 조절하면 된다.

Categories:

Updated:

Comments