|
@@ -7,7 +7,7 @@ TOC: 카메라(Cameras)
|
|
읽고 오길 권장합니다.
|
|
읽고 오길 권장합니다.
|
|
|
|
|
|
|
|
|
|
-이번 장에서는 카메라(cemaras)에 대해 알아보겠습니다. [첫 번째 장](threejs-fundamentals.html)에서
|
|
|
|
|
|
+이번 장에서는 카메라(cameras)에 대해 알아보겠습니다. [첫 번째 장](threejs-fundamentals.html)에서
|
|
일부 다루긴 했지만, 중요 요소인 만큼 더 자세히 살펴볼 필요가 있습니다.
|
|
일부 다루긴 했지만, 중요 요소인 만큼 더 자세히 살펴볼 필요가 있습니다.
|
|
|
|
|
|
Three.js에서 가장 자주 사용하는 카메라는 여태까지 썼던 `PerspectiveCamera`(원근 카메라)입니다.
|
|
Three.js에서 가장 자주 사용하는 카메라는 여태까지 썼던 `PerspectiveCamera`(원근 카메라)입니다.
|
|
@@ -30,7 +30,7 @@ Three.js에서 가장 자주 사용하는 카메라는 여태까지 썼던 `Pers
|
|
쉽죠 😅.
|
|
쉽죠 😅.
|
|
|
|
|
|
`PerspectiveCamera`는 4가지 속성을 바탕으로 절두체를 만듭니다. `near`는 절두체가 어디서 시작할지
|
|
`PerspectiveCamera`는 4가지 속성을 바탕으로 절두체를 만듭니다. `near`는 절두체가 어디서 시작할지
|
|
-결정하는 속성이고, `far`는 절두체의 끝입니다. `fov`는 시아갹(field of view)으로, `near`과 카메라의
|
|
|
|
|
|
+결정하는 속성이고, `far`는 절두체의 끝입니다. `fov`는 시아갹(field of view)으로, `near`와 카메라의
|
|
거리에 따라 절두체의 높이를 계산해 적용합니다. `aspect`는 절두체의 너비에 관여하는 비율으로, 절두체의
|
|
거리에 따라 절두체의 높이를 계산해 적용합니다. `aspect`는 절두체의 너비에 관여하는 비율으로, 절두체의
|
|
너비는 절두체의 높이에 이 비율을 곱한 값입니다.
|
|
너비는 절두체의 높이에 이 비율을 곱한 값입니다.
|
|
|
|
|
|
@@ -152,9 +152,8 @@ const view2Elem = document.querySelector('#view2');
|
|
+const controls = new OrbitControls(camera, view1Elem);
|
|
+const controls = new OrbitControls(camera, view1Elem);
|
|
```
|
|
```
|
|
|
|
|
|
-다음으로 `PerspectiveCamera`와 두 번째 `OrbitControls`를 추가합니다. 두 번째
|
|
|
|
-`OrbitControls`는 두 번째 카메라에 종속적이며, 오른쪽 div 요소의 이벤트에
|
|
|
|
-반응합니다.
|
|
|
|
|
|
+다음으로 `PerspectiveCamera`와 두 번째 `OrbitControls`를 추가합니다. 이 `OrbitControls`를
|
|
|
|
+두 번째 카메라에 종속시키고, 오른쪽 div 요소의 이벤트에만 반응하도록 합니다.
|
|
|
|
|
|
```js
|
|
```js
|
|
const camera2 = new THREE.PerspectiveCamera(
|
|
const camera2 = new THREE.PerspectiveCamera(
|
|
@@ -171,19 +170,19 @@ controls2.target.set(0, 5, 0);
|
|
controls2.update();
|
|
controls2.update();
|
|
```
|
|
```
|
|
|
|
|
|
-Finally we need to render the scene from the point of view of each
|
|
|
|
-camera using the scissor function to only render to part of the canvas.
|
|
|
|
|
|
+끝으로 가위 함수를 사용해 화면을 분할하겠습니다. 카메라 각각의 시점에 따라
|
|
|
|
+장면을 canvas의 양쪽에 나눠 렌더링하게끔 할 것입니다.
|
|
|
|
|
|
-Here is a function that given an element will compute the rectangle
|
|
|
|
-of that element that overlaps the canvas. It will then set the scissor
|
|
|
|
-and viewport to that rectangle and return the aspect for that size.
|
|
|
|
|
|
+아래의 함수는 canvas 위에 덮어 씌운 요소의 사각 좌표(rectangle)를 구합니다.
|
|
|
|
+그리고 해당 사각 좌표로 `renderer`의 화면(viewport)과 가위(scissor)의 값을
|
|
|
|
+정의한 뒤, 사각 좌표의 가로세로 비율을 반환합니다.
|
|
|
|
|
|
```js
|
|
```js
|
|
function setScissorForElement(elem) {
|
|
function setScissorForElement(elem) {
|
|
const canvasRect = canvas.getBoundingClientRect();
|
|
const canvasRect = canvas.getBoundingClientRect();
|
|
const elemRect = elem.getBoundingClientRect();
|
|
const elemRect = elem.getBoundingClientRect();
|
|
|
|
|
|
- // compute a canvas relative rectangle
|
|
|
|
|
|
+ // canvas에 대응하는 사각형을 구하기
|
|
const right = Math.min(elemRect.right, canvasRect.right) - canvasRect.left;
|
|
const right = Math.min(elemRect.right, canvasRect.right) - canvasRect.left;
|
|
const left = Math.max(0, elemRect.left - canvasRect.left);
|
|
const left = Math.max(0, elemRect.left - canvasRect.left);
|
|
const bottom = Math.min(elemRect.bottom, canvasRect.bottom) - canvasRect.top;
|
|
const bottom = Math.min(elemRect.bottom, canvasRect.bottom) - canvasRect.top;
|
|
@@ -192,17 +191,17 @@ function setScissorForElement(elem) {
|
|
const width = Math.min(canvasRect.width, right - left);
|
|
const width = Math.min(canvasRect.width, right - left);
|
|
const height = Math.min(canvasRect.height, bottom - top);
|
|
const height = Math.min(canvasRect.height, bottom - top);
|
|
|
|
|
|
- // setup the scissor to only render to that part of the canvas
|
|
|
|
|
|
+ // canvas의 일부분만 렌더링하도록 scissor 적용
|
|
const positiveYUpBottom = canvasRect.height - bottom;
|
|
const positiveYUpBottom = canvasRect.height - bottom;
|
|
renderer.setScissor(left, positiveYUpBottom, width, height);
|
|
renderer.setScissor(left, positiveYUpBottom, width, height);
|
|
renderer.setViewport(left, positiveYUpBottom, width, height);
|
|
renderer.setViewport(left, positiveYUpBottom, width, height);
|
|
|
|
|
|
- // return the aspect
|
|
|
|
|
|
+ // 비율 반환
|
|
return width / height;
|
|
return width / height;
|
|
}
|
|
}
|
|
```
|
|
```
|
|
|
|
|
|
-And now we can use that function to draw the scene twice in our `render` function
|
|
|
|
|
|
+이제 이 함수를 사용해 `render` 함수에서 장면을 두 번 렌더링할 수 있습니다.
|
|
|
|
|
|
```js
|
|
```js
|
|
function render() {
|
|
function render() {
|
|
@@ -215,36 +214,36 @@ And now we can use that function to draw the scene twice in our `render` functio
|
|
|
|
|
|
+ resizeRendererToDisplaySize(renderer);
|
|
+ resizeRendererToDisplaySize(renderer);
|
|
+
|
|
+
|
|
-+ // turn on the scissor
|
|
|
|
|
|
++ // 가위 활성화
|
|
+ renderer.setScissorTest(true);
|
|
+ renderer.setScissorTest(true);
|
|
+
|
|
+
|
|
-+ // render the original view
|
|
|
|
|
|
++ // 기존 화면 렌더링
|
|
+ {
|
|
+ {
|
|
+ const aspect = setScissorForElement(view1Elem);
|
|
+ const aspect = setScissorForElement(view1Elem);
|
|
+
|
|
+
|
|
-+ // adjust the camera for this aspect
|
|
|
|
|
|
++ // 비율에 따라 카메라 조정
|
|
+ camera.aspect = aspect;
|
|
+ camera.aspect = aspect;
|
|
+ camera.updateProjectionMatrix();
|
|
+ camera.updateProjectionMatrix();
|
|
+ cameraHelper.update();
|
|
+ cameraHelper.update();
|
|
+
|
|
+
|
|
-+ // don't draw the camera helper in the original view
|
|
|
|
|
|
++ // 기존 화면에서 가이드라인(CameraHelper)이 노출되지 않도록 설정
|
|
+ cameraHelper.visible = false;
|
|
+ cameraHelper.visible = false;
|
|
+
|
|
+
|
|
+ scene.background.set(0x000000);
|
|
+ scene.background.set(0x000000);
|
|
+
|
|
+
|
|
-+ // render
|
|
|
|
|
|
++ // 렌더링
|
|
+ renderer.render(scene, camera);
|
|
+ renderer.render(scene, camera);
|
|
+ }
|
|
+ }
|
|
+
|
|
+
|
|
-+ // render from the 2nd camera
|
|
|
|
|
|
++ // 두 번째 카메라 렌더링
|
|
+ {
|
|
+ {
|
|
+ const aspect = setScissorForElement(view2Elem);
|
|
+ const aspect = setScissorForElement(view2Elem);
|
|
+
|
|
+
|
|
-+ // adjust the camera for this aspect
|
|
|
|
|
|
++ // 비율에 따라 카메라 조정
|
|
+ camera2.aspect = aspect;
|
|
+ camera2.aspect = aspect;
|
|
+ camera2.updateProjectionMatrix();
|
|
+ camera2.updateProjectionMatrix();
|
|
+
|
|
+
|
|
-+ // draw the camera helper in the 2nd view
|
|
|
|
|
|
++ // 가이드라인 활성화
|
|
+ cameraHelper.visible = true;
|
|
+ cameraHelper.visible = true;
|
|
+
|
|
+
|
|
+ scene.background.set(0x000040);
|
|
+ scene.background.set(0x000040);
|
|
@@ -261,11 +260,11 @@ And now we can use that function to draw the scene twice in our `render` functio
|
|
}
|
|
}
|
|
```
|
|
```
|
|
|
|
|
|
-The code above sets the background color of the scene when rendering the
|
|
|
|
-second view to dark blue just to make it easier to distinguish the two views.
|
|
|
|
|
|
+위 예제에서는 분할된 두 화면을 구별하기 쉽두록 두 번째 화면의 배경을 진한
|
|
|
|
+파란색으로 칠했습니다.
|
|
|
|
|
|
-We can also remove our `updateCamera` code since we're updating everything
|
|
|
|
-in the `render` function.
|
|
|
|
|
|
+또한 `render` 함수 안에서 모든 것을 처리하기에, `updateCamera` 함수도
|
|
|
|
+제거하였습니다.
|
|
|
|
|
|
```js
|
|
```js
|
|
-function updateCamera() {
|
|
-function updateCamera() {
|
|
@@ -282,31 +281,22 @@ const minMaxGUIHelper = new MinMaxGUIHelper(camera, 'near', 'far', 0.1);
|
|
+gui.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('far');
|
|
+gui.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('far');
|
|
```
|
|
```
|
|
|
|
|
|
-And now you can use one view to see the frustum of the other.
|
|
|
|
|
|
+이제 두 번째 화면에서 첫 번째 카메라의 절두체를 확인할 수 있습니다.
|
|
|
|
|
|
{{{example url="../threejs-cameras-perspective-2-scenes.html" }}}
|
|
{{{example url="../threejs-cameras-perspective-2-scenes.html" }}}
|
|
|
|
|
|
-On the left you can see the original view and on the right you can
|
|
|
|
-see a view showing the frustum of the camera on the left. As you adjust
|
|
|
|
-`near`, `far`, `fov` and move the camera with mouse you can see that
|
|
|
|
-only what's inside the frustum shown on the right appears in the scene on
|
|
|
|
-the left.
|
|
|
|
|
|
+왼쪽은 기존의 화면과 같고 오른쪽에 왼쪽 카메라의 절두체가 보입니다.
|
|
|
|
+패널에서 `near`, `far`, `fov` 값을 조정하거나 마우스로 화면을 움직여보면,
|
|
|
|
+오른쪽 화면의 절두체 안에 있는 물체만 왼쪽 화면에 노출됨을 확인할 수
|
|
|
|
+있을 겁니다.
|
|
|
|
|
|
-Adjust `near` up to around 20 and you'll easily see the front of objects
|
|
|
|
-disappear as they are no longer in the frustum. Adjust `far` below about 35
|
|
|
|
-and you'll start to see the ground plane disappear as it's no longer in
|
|
|
|
-the frustum.
|
|
|
|
|
|
+누군가 이렇게 물을지도 모르겠네요. 그냥 `near`를 0.0000000001로 설정하고 `far`를
|
|
|
|
+10000000000000로 설정해버리면요? 이러면 모든 게 항상 다 보이지 않나요? 이유를
|
|
|
|
+설명하자면, GPU는 어떤 물체가 앞에 있거나 다른 물체의 뒤에 있을 때만 정밀도가
|
|
|
|
+높기 때문입니다. 정밀도는 일정량이 `near`와 `far` 사이에 퍼져 있는데, 기본적으로
|
|
|
|
+카메라에 가까울 수록 정밀도가 높고 멀수록 정밀도가 낮아집니다.
|
|
|
|
|
|
-This brings up the question, why not just set `near` to 0.0000000001 and `far`
|
|
|
|
-to 10000000000000 or something like that so you can just see everything?
|
|
|
|
-The reason is your GPU only has so much precision to decide if something
|
|
|
|
-is in front or behind something else. That precision is spread out between
|
|
|
|
-`near` and `far`. Worse, by default the precision close the camera is detailed
|
|
|
|
-and the precision far from the camera is coarse. The units start with `near`
|
|
|
|
-and slowly expand as they approach `far`.
|
|
|
|
-
|
|
|
|
-Starting with the top example, let's change the code to insert 20 spheres in a
|
|
|
|
-row.
|
|
|
|
|
|
+현상을 직접 확인해보죠. 위의 예제를 수정해 20개의 구체를 한 줄로 세우겠습니다.
|
|
|
|
|
|
```js
|
|
```js
|
|
{
|
|
{
|
|
@@ -325,38 +315,38 @@ row.
|
|
}
|
|
}
|
|
```
|
|
```
|
|
|
|
|
|
-and let's set `near` to 0.00001
|
|
|
|
|
|
+`near` 속성을 0.00001로 설정합니다.
|
|
|
|
|
|
```js
|
|
```js
|
|
const fov = 45;
|
|
const fov = 45;
|
|
-const aspect = 2; // the canvas default
|
|
|
|
|
|
+const aspect = 2; // canvas 기본값
|
|
-const near = 0.1;
|
|
-const near = 0.1;
|
|
+const near = 0.00001;
|
|
+const near = 0.00001;
|
|
const far = 100;
|
|
const far = 100;
|
|
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
|
|
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
|
|
```
|
|
```
|
|
|
|
|
|
-We also need to tweak the GUI code a little to allow 0.00001 if the value is edited
|
|
|
|
|
|
+그리고 기존의 GUI 코드를 수정해 0.00001의 작은 단위도 설정할 수 있도록 합니다.
|
|
|
|
|
|
```js
|
|
```js
|
|
-gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near').onChange(updateCamera);
|
|
-gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near').onChange(updateCamera);
|
|
+gui.add(minMaxGUIHelper, 'min', 0.00001, 50, 0.00001).name('near').onChange(updateCamera);
|
|
+gui.add(minMaxGUIHelper, 'min', 0.00001, 50, 0.00001).name('near').onChange(updateCamera);
|
|
```
|
|
```
|
|
|
|
|
|
-What do you think will happen?
|
|
|
|
|
|
+어떤 결과가 나올 것 같나요?
|
|
|
|
|
|
{{{example url="../threejs-cameras-z-fighting.html" }}}
|
|
{{{example url="../threejs-cameras-z-fighting.html" }}}
|
|
|
|
|
|
-This is an example of *z fighting* where the GPU on your computer does not have
|
|
|
|
-enough precision to decide which pixels are in front and which pixels are behind.
|
|
|
|
|
|
+이는 *z-파이팅(z-fighting, Stitching)*의 한 예입니다. 컴퓨터의 GPU가 어떤 픽셀이
|
|
|
|
+앞이고 어떤 픽셀을 뒤로 보내야할지 결정할 정밀도가 모자를 때 발생하는 현상이죠.
|
|
|
|
|
|
-Just in case the issue doesn't show on your machine here's what I see on mine
|
|
|
|
|
|
+위 예제가 어떻게 해도 정상적으로 보인다면, 아래 이미지를 보기 바랍니다.
|
|
|
|
|
|
<div class="threejs_center"><img src="resources/images/z-fighting.png" style="width: 570px;"></div>
|
|
<div class="threejs_center"><img src="resources/images/z-fighting.png" style="width: 570px;"></div>
|
|
|
|
|
|
-One solution is to tell three.js use to a different method to compute which
|
|
|
|
-pixels are in front and which are behind. We can do that by enabling
|
|
|
|
-`logarithmicDepthBuffer` when we create the `WebGLRenderer`
|
|
|
|
|
|
+한 가지 해결책은 Three.js에게 픽셀의 앞 뒤를 결정할 때 다른 방법을 쓰도록 설정하는
|
|
|
|
+것입니다. `WebGLRenderer`를 생성할 때 `logarithmicDepthBuffer` 속성을 활성화해주면
|
|
|
|
+되죠.
|
|
|
|
|
|
```js
|
|
```js
|
|
-const renderer = new THREE.WebGLRenderer({canvas});
|
|
-const renderer = new THREE.WebGLRenderer({canvas});
|
|
@@ -366,40 +356,35 @@ pixels are in front and which are behind. We can do that by enabling
|
|
+});
|
|
+});
|
|
```
|
|
```
|
|
|
|
|
|
-and with that it might work
|
|
|
|
|
|
+대게의 경우 정상적으로 보일 겁니다.
|
|
|
|
|
|
{{{example url="../threejs-cameras-logarithmic-depth-buffer.html" }}}
|
|
{{{example url="../threejs-cameras-logarithmic-depth-buffer.html" }}}
|
|
|
|
|
|
-If this didn't fix the issue for you then you've run into one reason why
|
|
|
|
-you can't always use this solution. That reason is because only certain GPUs
|
|
|
|
-support it. As of September 2018 almost no mobile devices support this
|
|
|
|
-solution whereas most desktops do.
|
|
|
|
|
|
+문제가 그대로라면 *이 해결책을 쓸 수 없는 건가?*라는 의문에 빠질 수 있습니다.
|
|
|
|
+이 해결책이 먹히지 않은 이유는 일부 GPU만 이 기능을 지원하기 때문이죠. 2018년
|
|
|
|
+9월 기준으로 거의 모든 데스크탑 GPU가 이 기능을 지원하나, 모바일 기기는 대부분
|
|
|
|
+이 기능을 지원하지 않습니다.
|
|
|
|
|
|
-Another reason not to choose this solution is it can be significantly slower
|
|
|
|
-than the standard solution.
|
|
|
|
|
|
+이 기능을 쓰지 말아야 하는 또 다른 이유는, 이 기능이 일반적인 해결책보다 훨씬
|
|
|
|
+성능이 나쁘기 때문입니다.
|
|
|
|
|
|
-Even with this solution there is still limited resolution. Make `near` even
|
|
|
|
-smaller or `far` even bigger and you'll eventually run into the same issues.
|
|
|
|
|
|
+게다가 이 기능을 활성화해도, `near`를 더 작게, `far`를 더 멀게 설정하다보면
|
|
|
|
+결국 같은 현상을 만나게 될 겁니다.
|
|
|
|
|
|
-What that means is that you should always make an effort to choose a `near`
|
|
|
|
-and `far` setting that fits your use case. Set `near` as far away from the camera
|
|
|
|
-as you can and not have things disappear. Set `far` as close to the camera
|
|
|
|
-as you can and not have things disappear. If you're trying to draw a giant
|
|
|
|
-scene and show a close up of someone's face so you can see their eyelashes
|
|
|
|
-while in the background you can see all the way to mountains 50 kilometers
|
|
|
|
-in the distance well then you'll need to find other creative solutions that
|
|
|
|
-maybe we'll go over later. For now, just be aware you should take care
|
|
|
|
-to choose appropriate `near` and `far` values for your needs.
|
|
|
|
|
|
+이는 항상 `near`와 `far`를 설정하는데 많은 공을 들여야 한다는 의미입니다.
|
|
|
|
+`near`는 대상이 보이는 한 가장 멀게, `far`도 대상이 보이는 한 카메라와 가장
|
|
|
|
+가깝게 설정하는 것이 좋죠. 만약 거대한 공간을 렌더링하는 경우, 예를 들어 사람의
|
|
|
|
+속눈썹과 50km 떨어진 산을 동시에 보이게 하려면 다른 해결책-나중에 다룰지도 모르는-을
|
|
|
|
+찾아야 합니다. 당장은 `near`와 `far`를 적절하게 설정하는 게 중요하다는 것만
|
|
|
|
+알아둡시다.
|
|
|
|
|
|
-The 2nd most common camera is the `OrthographicCamera`. Rather than
|
|
|
|
-specify a frustum it specifies a box with the settings `left`, `right`
|
|
|
|
-`top`, `bottom`, `near`, and `far`. Because it's projecting a box
|
|
|
|
-there is no perspective.
|
|
|
|
|
|
+두 번째로 자주 사용하는 카메라는 `OrthographicCamera`(정사영 카메라)입니다.
|
|
|
|
+절두체 대신 `left`, `right`, `top`, `bottom`, `near`, `far`로 육면체를
|
|
|
|
+정의해 사용하죠. 육면체로 화면을 투사하기에 원근 효과가 없습니다.
|
|
|
|
|
|
-Let's change the 2 view example above to use an `OrthographicCamera`
|
|
|
|
-in the first view.
|
|
|
|
|
|
+2분할 화면 예제를 수정해 첫 번째 화면을 `OrthographicCamera`로 바꾸겠습니다.
|
|
|
|
|
|
-First let's setup an `OrthographicCamera`.
|
|
|
|
|
|
+먼저 `OrthographicCamera`를 만들어보죠.
|
|
|
|
|
|
```js
|
|
```js
|
|
const left = -1;
|
|
const left = -1;
|
|
@@ -412,37 +397,35 @@ const camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far)
|
|
camera.zoom = 0.2;
|
|
camera.zoom = 0.2;
|
|
```
|
|
```
|
|
|
|
|
|
-We set `left` and `bottom` to -1 and `right` and `top` to 1. This would make
|
|
|
|
-a box 2 units wide and 2 units tall but we're going to adjust the `left` and `top`
|
|
|
|
-by the aspect of the rectangle we're drawing to. We'll use the `zoom` property
|
|
|
|
-to make it easy to adjust how many units are actually shown by the camera.
|
|
|
|
|
|
+먼저 `left`와 `bottom`을 -1로, `right`와 `top`을 1로 설정했습니다. 이러면 육면체는
|
|
|
|
+기본적으로 너비 2칸, 높이 2칸이 되겠죠. 그리고 육면체의 비율을 조정해 `left`와 `top`의
|
|
|
|
+값을 조정할 수 있도록, `zoom` 속성을 이용해 카메라에 보이는 범위를 조정할 수 있도록
|
|
|
|
+했습니다.
|
|
|
|
|
|
-Let's add a GUI setting for `zoom`
|
|
|
|
|
|
+다음으로 `zoom` 속성을 조정할 GUI를 추가합니다.
|
|
|
|
|
|
```js
|
|
```js
|
|
const gui = new GUI();
|
|
const gui = new GUI();
|
|
+gui.add(camera, 'zoom', 0.01, 1, 0.01).listen();
|
|
+gui.add(camera, 'zoom', 0.01, 1, 0.01).listen();
|
|
```
|
|
```
|
|
|
|
|
|
-The call to `listen` tells dat.GUI to watch for changes. This is here because
|
|
|
|
-the `OrbitControls` can also control zoom. For example the scroll wheel on
|
|
|
|
-a mouse will zoom via the `OrbitControls`.
|
|
|
|
|
|
+`listen` 메서드를 호출하면 dat.GUI가 변화를 감지합니다. 이렇게 한 이유는 `OrbitControls`이
|
|
|
|
+마우스 휠 스크롤을 감지해 `zoom` 속성을 변경하기 때문이죠.
|
|
|
|
|
|
-Last we just need to change the part that renders the left
|
|
|
|
-side to update the `OrthographicCamera`.
|
|
|
|
|
|
+끝으로 왼쪽 화면을 렌더링할 때 `OrthographicCamera`를 업데이트하도록 설정합니다.
|
|
|
|
|
|
```js
|
|
```js
|
|
{
|
|
{
|
|
const aspect = setScissorForElement(view1Elem);
|
|
const aspect = setScissorForElement(view1Elem);
|
|
|
|
|
|
- // update the camera for this aspect
|
|
|
|
|
|
+ // 요소의 비율에 맞춰 카메라 업데이트
|
|
- camera.aspect = aspect;
|
|
- camera.aspect = aspect;
|
|
+ camera.left = -aspect;
|
|
+ camera.left = -aspect;
|
|
+ camera.right = aspect;
|
|
+ camera.right = aspect;
|
|
camera.updateProjectionMatrix();
|
|
camera.updateProjectionMatrix();
|
|
cameraHelper.update();
|
|
cameraHelper.update();
|
|
|
|
|
|
- // don't draw the camera helper in the original view
|
|
|
|
|
|
+ // 기존 화면에서 가이드라인(CameraHelper)이 노출되지 않도록 설정
|
|
cameraHelper.visible = false;
|
|
cameraHelper.visible = false;
|
|
|
|
|
|
scene.background.set(0x000000);
|
|
scene.background.set(0x000000);
|
|
@@ -450,17 +433,15 @@ side to update the `OrthographicCamera`.
|
|
}
|
|
}
|
|
```
|
|
```
|
|
|
|
|
|
-and now you can see an `OrthographicCamera` at work.
|
|
|
|
|
|
+이제 `OrthographicCamera`가 어떻게 작동하는지 확인할 차례입니다.
|
|
|
|
|
|
{{{example url="../threejs-cameras-orthographic-2-scenes.html" }}}
|
|
{{{example url="../threejs-cameras-orthographic-2-scenes.html" }}}
|
|
|
|
|
|
-An `OrthographicCamera` is most often used if using three.js
|
|
|
|
-to draw 2D things. You'd decide how many units you want the camera
|
|
|
|
-to show. For example if you want one pixel of canvas to match
|
|
|
|
-one unit in the camera you could do something like
|
|
|
|
|
|
+Three.js에서 `OrthographicCamera`는 주로 2D 요소를 표현하기 위해 사용합니다.
|
|
|
|
+카메라에 얼마나 많은 요소를 보여줄지만 결정하면 되죠. 만약 canvas의 1픽셀을
|
|
|
|
+카메라의 한 칸과 같은 크기로 지정하고 싶다면...
|
|
|
|
|
|
-To put the origin at the center and have 1 pixel = 1 three.js unit
|
|
|
|
-something like
|
|
|
|
|
|
+중점을 장면의 중심에 두고 1 픽셀을 Three.js의 한 칸으로 만들 수 있습니다.
|
|
|
|
|
|
```js
|
|
```js
|
|
camera.left = -canvas.width / 2;
|
|
camera.left = -canvas.width / 2;
|
|
@@ -472,8 +453,7 @@ camera.far = 1;
|
|
camera.zoom = 1;
|
|
camera.zoom = 1;
|
|
```
|
|
```
|
|
|
|
|
|
-Or if we wanted the origin to be in the top left just like a
|
|
|
|
-2D canvas we could use this
|
|
|
|
|
|
+2D canvas처럼 중점을 상단 왼쪽에 두려면 다음과 같이 설정할 수 있죠.
|
|
|
|
|
|
```js
|
|
```js
|
|
camera.left = 0;
|
|
camera.left = 0;
|
|
@@ -485,24 +465,24 @@ camera.far = 1;
|
|
camera.zoom = 1;
|
|
camera.zoom = 1;
|
|
```
|
|
```
|
|
|
|
|
|
-In which case the top left corner would be 0,0 just like a 2D canvas
|
|
|
|
|
|
+중점이 상단 왼쪽에 있을 경우의 좌표는 2D canvas처럼 0, 0입니다.
|
|
|
|
|
|
-Let's try it! First let's set the camera up
|
|
|
|
|
|
+한 번 만들어보죠! 먼저 카메라를 설정합니다.
|
|
|
|
|
|
```js
|
|
```js
|
|
const left = 0;
|
|
const left = 0;
|
|
-const right = 300; // default canvas size
|
|
|
|
|
|
+const right = 300; // canvas 기본 크기
|
|
const top = 0;
|
|
const top = 0;
|
|
-const bottom = 150; // default canvas size
|
|
|
|
|
|
+const bottom = 150; // canvas 기본 크기
|
|
const near = -1;
|
|
const near = -1;
|
|
const far = 1;
|
|
const far = 1;
|
|
const camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far);
|
|
const camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far);
|
|
camera.zoom = 1;
|
|
camera.zoom = 1;
|
|
```
|
|
```
|
|
|
|
|
|
-Then let's load 6 textures and make 6 planes, one for each texture.
|
|
|
|
-We'll parent each plane to a `THREE.Object3D` to make it easy to offset
|
|
|
|
-the plane so it's center appears to be at it's top left corner.
|
|
|
|
|
|
+다음으로 평면(plane) 6개를 만들어 각각 다른 텍스처를 적용하겠습니다.
|
|
|
|
+각 평면마다 `THREE.Object3D` 인스턴스를 만들어 평면의 부모로 설정합니다.
|
|
|
|
+이러면 중점을 0, 0, 상단 좌측으로 지정해 좌표를 지정하기가 쉽습니다.
|
|
|
|
|
|
```js
|
|
```js
|
|
const loader = new THREE.TextureLoader();
|
|
const loader = new THREE.TextureLoader();
|
|
@@ -526,14 +506,14 @@ const planes = textures.map((texture) => {
|
|
});
|
|
});
|
|
const mesh = new THREE.Mesh(planeGeo, planeMat);
|
|
const mesh = new THREE.Mesh(planeGeo, planeMat);
|
|
planePivot.add(mesh);
|
|
planePivot.add(mesh);
|
|
- // move plane so top left corner is origin
|
|
|
|
|
|
+ // 평면을 움직여 상단 좌측이 중점이 되도록 설정
|
|
mesh.position.set(planeSize / 2, planeSize / 2, 0);
|
|
mesh.position.set(planeSize / 2, planeSize / 2, 0);
|
|
return planePivot;
|
|
return planePivot;
|
|
});
|
|
});
|
|
```
|
|
```
|
|
|
|
|
|
-and we need to update the camera if the size of the canvas
|
|
|
|
-changes.
|
|
|
|
|
|
+그리고 `render` 함수 안에 canvas의 사이즈가 변경되었을 때 카메라를 업데이트하는
|
|
|
|
+코드를 추가합니다.
|
|
|
|
|
|
```js
|
|
```js
|
|
function render() {
|
|
function render() {
|
|
@@ -547,12 +527,12 @@ function render() {
|
|
...
|
|
...
|
|
```
|
|
```
|
|
|
|
|
|
-`planes` is an array of `THREE.Mesh`, one for each plane.
|
|
|
|
-Let's move them around based on the time.
|
|
|
|
|
|
+`planes`는 `THREE.Mesh`, 평면의 배열입니다. 시간값을 기반으로 이 평면이 따로
|
|
|
|
+움직이도록 하겠습니다.
|
|
|
|
|
|
```js
|
|
```js
|
|
function render(time) {
|
|
function render(time) {
|
|
- time *= 0.001; // convert to seconds;
|
|
|
|
|
|
+ time *= 0.001; // 초 단위로 변경
|
|
|
|
|
|
...
|
|
...
|
|
|
|
|
|
@@ -574,22 +554,22 @@ function render(time) {
|
|
renderer.render(scene, camera);
|
|
renderer.render(scene, camera);
|
|
```
|
|
```
|
|
|
|
|
|
-And you can see the images bounce pixel perfect off the edges of the
|
|
|
|
-canvas using pixel math just like a 2D canvas
|
|
|
|
|
|
+이미지가 완벽하게 가장자리에서 튕기는 것을 확인할 수 있을 겁니다. 2D canvas에서
|
|
|
|
+픽셀값을 이용해 구현할 때와 같은 방식이죠.
|
|
|
|
|
|
{{{example url="../threejs-cameras-orthographic-canvas-top-left-origin.html" }}}
|
|
{{{example url="../threejs-cameras-orthographic-canvas-top-left-origin.html" }}}
|
|
|
|
|
|
-Another common use for an `OrthographicCamera` is to draw the
|
|
|
|
-up, down, left, right, front, back views of a 3D modeling
|
|
|
|
-program or a game engine's editor.
|
|
|
|
|
|
+`OrthographicCamera`는 게임 엔진 에디터 등에서처럼 3D 모델링 결과물의 상, 하, 좌, 우,
|
|
|
|
+앞, 뒤를 렌더링할 때도 사용합니다.
|
|
|
|
|
|
<div class="threejs_center"><img src="resources/images/quad-viewport.png" style="width: 574px;"></div>
|
|
<div class="threejs_center"><img src="resources/images/quad-viewport.png" style="width: 574px;"></div>
|
|
|
|
|
|
-In the screenshot above you can see 1 view is a perspective view and 3 views are
|
|
|
|
-orthographic views.
|
|
|
|
|
|
+위 스크린샷의 1개의 화면만 원근(perspective) 카메라이고 나머지 3개는 정사영(orthographic)
|
|
|
|
+카메라입니다.
|
|
|
|
|
|
-That's the fundamentals of cameras. We'll cover a few common ways to move cameras
|
|
|
|
-in other articles. For now let's move on to [shadows](threejs-shadows.html).
|
|
|
|
|
|
+여기까지 카메라의 기초에 대해 살펴보았습니다. 카메라를 움직이는 방법에 대해서는 다른
|
|
|
|
+글에서 좀 더 상세히 설명할 거예요. 다음은 장에서는 [그림자(shadows)](threejs-shadows.html)에
|
|
|
|
+대해 먼저 살펴보겠습니다.
|
|
|
|
|
|
<canvas id="c"></canvas>
|
|
<canvas id="c"></canvas>
|
|
<script type="module" src="../resources/threejs-cameras.js"></script>
|
|
<script type="module" src="../resources/threejs-cameras.js"></script>
|