SeemsPyo 5 years ago
parent
commit
de3432855e

+ 4 - 6
threejs/lessons/kr/langinfo.hanson

@@ -1,17 +1,15 @@
 {
 {
   language: '한국어',
   language: '한국어',
   langCode: 'ko',
   langCode: 'ko',
-  defaultExampleCaption: "새 에서 보기",
+  defaultExampleCaption: "새 에서 보기",
   title: 'Three.js 튜토리얼',
   title: 'Three.js 튜토리얼',
   description: 'Three.js 입문자를 위한 튜토리얼',
   description: 'Three.js 입문자를 위한 튜토리얼',
   link: 'http://threejsfundamentals.org/',
   link: 'http://threejsfundamentals.org/',
   commentSectionHeader: `
   commentSectionHeader: `
     <div>
     <div>
-      <a href="http://stackoverflow.com/questions/tagged/three.js">스택오버플로우 바로가기</a>
-    </div>
-
-    <div>
-      <a href="http://github.com/greggman/threefundamentals/issues">깃허브에 이슈 남기기</a>
+      <a href="http://stackoverflow.com/questions/tagged/three.js">Stackoverflow</a>
+      /
+      <a href="http://github.com/greggman/threefundamentals/issues">Github</a>
     </div>
     </div>
   `,
   `,
   missing: `
   missing: `

+ 118 - 132
threejs/lessons/kr/threejs-fundamentals.md

@@ -38,44 +38,44 @@ Three.js는 3차원 세계를 다루므로, 우리는 정육면체(cube)를 3차
   `Scene`과 `Camera` 객체를 넘겨 받아 카메라의 [*절두체(frustum)*](https://ko.wikipedia.org/wiki/%EC%A0%88%EB%91%90%EC%B2%B4)
   `Scene`과 `Camera` 객체를 넘겨 받아 카메라의 [*절두체(frustum)*](https://ko.wikipedia.org/wiki/%EC%A0%88%EB%91%90%EC%B2%B4)
   안 3D 장면의 일부를 평면(2차원) 이미지로 렌더링합니다.
   안 3D 장면의 일부를 평면(2차원) 이미지로 렌더링합니다.
 
 
-* [씬 그래프(Scene graph)](threejs-scenegraph.html)는 `Scene` 객체 또는
-  다수의 `Mesh`, `Light`, `Group`, `Object3D`, `Camera` 객체로 이루어진
-  트리 구조와 유사합니다. `Scene` 객체는 씬 그래프의 최상위 노드로서 배경색(background color),
-  안개(fog) 등의 요소를 포함합니다. `Scene` 객체에 포함된 객체들 또한 부모/자식의
+* [씬 그래프(Scene graph)](threejs-scenegraph.html)는 `Scene` 또는
+  다수의 `Mesh`, `Light`, `Group`, `Object3D`, `Camera`로 이루어진
+  트리 구조와 유사합니다. `Scene` 씬 그래프의 최상위 노드로서 배경색(background color),
+  안개(fog) 등의 요소를 포함합니다. `Scene`에 포함된 객체들 또한 부모/자식의
   트리 구조로 이루어지며, 이는 각 객체의 유래와 방향성을 나타냅니다. 쉽게 말해 자식 객체의
   트리 구조로 이루어지며, 이는 각 객체의 유래와 방향성을 나타냅니다. 쉽게 말해 자식 객체의
-  위치(position)와 방향(orientation)은 부모를 기준으로 한다는 거죠. 예를 들어 자동차의 바퀴가
+  위치(position)와 방향(orientation)이 부모 기준이라는 거죠. 예를 들어 자동차의 바퀴가
   자동차 객체의 자식 객체라면, 자동차 객체의 방향을 움직일 때, 바퀴 객체의 방향 또한 같이
   자동차 객체의 자식 객체라면, 자동차 객체의 방향을 움직일 때, 바퀴 객체의 방향 또한 같이
   움직입니다(더 자세한 내용은 [씬 그래프에 관한 글](threejs-scenegraph.html)에서 확인할 수 있습니다)
   움직입니다(더 자세한 내용은 [씬 그래프에 관한 글](threejs-scenegraph.html)에서 확인할 수 있습니다)
 
 
-  `Camera` 객체가 도표에서 반쯤 나간 것이 보이나요? 이는 의도된 것으로, 다른 객체와 달리
-  `Camera` 객체는 굳이 씬 그래프에 포함될 필요가 없음을 보여주기 위함입니다. 물론 다른
-  객체와 마찬가지로 `Camera` 객체 또한 다른 객체의 자식 객체가 될 수 있습니다. 이러면
-  부모 객체에 따라 `Camera` 객체 또한 움직이겠죠. [씬 그래프에 관한 글](threejs-scenegraph.html)
-  마지막에 여러개의 `Camera` 객체를 넣는 예제가 있으니 참고하시기 바랍니다.
-
-* `Mesh`는 어떤 `Material` 객체로 하나의 `Geometry` 객체를 그리는 객체입니다.
-  `Material`, `Geometry` 객체는 재사용이 가능하여 여러개의 `Mesh` 객체가 하나의
-  `Material` 또는 `Geometry` 객체를 동시에 참조할 수 있습니다. 파란색 정육면체 2개를
-  그린다고 해보죠. 일단 두 정육면체의 위치가 달라야 하니, 2개의 `Mesh` 객체
-  필요합니다. 그리고 정점(vertext, 꼭지점) 데이터를 가진 한 개의 `Geometry` 객체
-  채색을 위한 하나의 `Material` 객체가 필요하겠죠. 각 `Mesh` 객체는 객체를 복사할 필요
-  없이, 같은 `Geometry` 그리고 `Material`를 참조할 수 있습니다.
-
-* `Geometry` 객체는 기하학 객체의 정점 데이터입니다. 구(sphere), 정육면체(cube),
+  `Camera`가 도표에서 반쯤 나간 것이 보이나요? 이는 의도된 것으로, 다른 객체와 달리
+  `Camera`는 굳이 씬 그래프에 포함될 필요가 없음을 보여주기 위함입니다. 물론 다른
+  객체와 마찬가지로 `Camera` 또한 다른 객체의 자식 객체가 될 수 있습니다. 이러면
+  부모 객체에 따라 `Camera` 또한 움직이겠죠. [씬 그래프에 관한 글](threejs-scenegraph.html)
+  마지막에 여러개의 `Camera`를 넣는 예제가 있으니 참고하시기 바랍니다.
+
+* `Mesh`는 어떤 `Material`로 하나의 `Geometry`를 그리는 객체입니다.
+  `Material`, `Geometry`는 재사용이 가능하여 여러개의 `Mesh`가 하나의
+  `Material` 또는 `Geometry`를 동시에 참조할 수 있습니다. 파란색 정육면체 2개를
+  그린다고 해보죠. 일단 두 정육면체의 위치가 달라야 하니, 2개의 `Mesh`가
+  필요합니다. 그리고 정점(vertext, 꼭지점) 데이터를 가진 한 개의 `Geometry`와
+  채색을 위한 하나의 `Material`이 필요하겠죠. 이때 각 `Mesh`는 객체를 복사할
+  필요 없이, 같은 `Geometry` 그리고 `Material`을 참조할 수 있습니다.
+
+* `Geometry`는 기하학 객체의 정점 데이터입니다. 구(sphere), 정육면체(cube),
   면(plane), 개, 고양이, 사람, 나무, 건물 등 아주 다양한 것이 될 수 있죠. Three.js는
   면(plane), 개, 고양이, 사람, 나무, 건물 등 아주 다양한 것이 될 수 있죠. Three.js는
   기본적으로 몇 가지의 내장(built-in) [기하학 객체](threejs-primitives.html)를 제공합니다.
   기본적으로 몇 가지의 내장(built-in) [기하학 객체](threejs-primitives.html)를 제공합니다.
   물론 [직접 기하학 객체를 만들](threejs-custom-geometry.html) 수도 있고,
   물론 [직접 기하학 객체를 만들](threejs-custom-geometry.html) 수도 있고,
   [파일에서 기하학 객체를 불러올](threejs-load-obj.html) 수도 있죠.
   [파일에서 기하학 객체를 불러올](threejs-load-obj.html) 수도 있죠.
 
 
-* `Material` 객체는 기하학 객체를 그리는 데 사용하는 [표면 속성](threejs-materials.html)입니다.
-  색이나 밝기 등을 지정할 수 있죠. 하나의 `Material` 객체는 여러개의 `Texture` 객체를 사용할 수
+* `Material` 기하학 객체를 그리는 데 사용하는 [표면 속성](threejs-materials.html)입니다.
+  색이나 밝기 등을 지정할 수 있죠. 하나의 `Material`는 여러개의 `Texture`를 사용할 수
   있습니다. 기하학 객체의 표면을 이미지로 덮어씌울 때 주로 사용하죠.
   있습니다. 기하학 객체의 표면을 이미지로 덮어씌울 때 주로 사용하죠.
 
 
-* `Texture` 객체는 이미지나 [파일에서 로드한 이미지](threejs-textures.html),
+* `Texture`는 이미지나 [파일에서 로드한 이미지](threejs-textures.html),
   [canvas로 생성한 이미지](threejs-canvas-textures.html)
   [canvas로 생성한 이미지](threejs-canvas-textures.html)
   또는 [다른 `Scene` 객체에서 렌더링한 결과물](threejs-rendertargets.html)에 해당합니다.
   또는 [다른 `Scene` 객체에서 렌더링한 결과물](threejs-rendertargets.html)에 해당합니다.
 
 
-* `Light` 객체는 [여러 종류의 광원에 해당](threejs-lights.html)합니다.
+* `Light`는 [여러 종류의 광원에 해당](threejs-lights.html)합니다.
 
 
 이제 기본적인 구조에 대해 배웠으니 아래와 같은 구조의 *"Hello Cube"*를 만들어 봅시다.
 이제 기본적인 구조에 대해 배웠으니 아래와 같은 구조의 *"Hello Cube"*를 만들어 봅시다.
 
 
@@ -144,7 +144,7 @@ const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
 설정했습니다. 알아둬야 할 건 Three.js의 대부분이 각도 단위로 호도(radians)를
 설정했습니다. 알아둬야 할 건 Three.js의 대부분이 각도 단위로 호도(radians)를
 사용하는데, 원근 카메라만 특이하게 도(degrees)를 인자로 받는다는 점입니다.
 사용하는데, 원근 카메라만 특이하게 도(degrees)를 인자로 받는다는 점입니다.
 
 
-`aspect` canvas의 가로 세로 비율입니다. 이는 [다른 글](threejs-responsive.html)
+`aspect` canvas의 가로 세로 비율입니다. 이는 [다른 글](threejs-responsive.html)
 에서 자세히 다루겠지만, 기본 설정으로 canvas의 크기는 300x150이니 비율도
 에서 자세히 다루겠지만, 기본 설정으로 canvas의 크기는 300x150이니 비율도
 300/150, 2로 설정했습니다.
 300/150, 2로 설정했습니다.
 
 
@@ -170,28 +170,27 @@ const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
 camera.position.z = 2;
 camera.position.z = 2;
 ```
 ```
 
 
-우리가 원하는 결과물은 다음과 같습니다.
+우리가 원하는 결과물을 다음처럼 그려볼 수 있습니다.
 
 
 <img src="resources/scene-down.svg" width="500" class="threejs_center"/>
 <img src="resources/scene-down.svg" width="500" class="threejs_center"/>
 
 
-In the diagram above we can see our camera is at `z = 2`. It's looking
-down the -Z axis. Our frustum starts 0.1 units from the front of the camera
-and goes to 5 units in front of the camera. Because in this diagram we are looking down,
-the field of view is affected by the aspect. Our canvas is twice as wide
-as it is tall so across view the field of view will be much wider than
-our specified 75 degrees which is the vertical field of view.
+카메라는 `z = 2` 위치에서 -Z 방향을 바라봅니다. 절두체는 카메라 앞 0.1 칸에서
+5칸까지를 차지하죠. 또한 아래를 바라보는 형태이기 때문에, 시야각은 canvas
+크기의 영향을 받습니다. 앞서 만든 canvas는 두 배 더 크기 때문에 실제로는 시야각이
+위에서 정의한 75도 보다는 훨씬 넓을 것입니다.
 
 
-Next we make a `Scene`. A `Scene` in three.js is the root of a form of scene graph.
-Anything you want three.js to draw needs to be added to the scene. We'll
-cover more details of [how scenes work in a future article](threejs-scenegraph.html).
+이제 `Scene`을 만듭니다. Three.js에서 `Scene`이란 씬 그래프에서 가장 상단에
+위치한 요소입니다. 뭔가를 화면에 렌더링하고 싶다면 먼저 `Scene`에 추가해야 하죠.
+여기서는 간단하게 다룰 것이므로 자세한 내용은 [이 글](threejs-scenegraph.html)을
+참고하세요.
 
 
 ```js
 ```js
 const scene = new THREE.Scene();
 const scene = new THREE.Scene();
 ```
 ```
 
 
-Next up we create a `BoxGeometry` which contains the data for a box.
-Almost anything we want to display in Three.js needs geometry which defines
-the vertices that make up our 3D object.
+다음으로 간단한 정육면체를 만들어보죠. Three.js에서 렌더링되는 대부분의 3D 요소는
+정점 데이터가 정의된 기하학 객체를 필요로 합니다. 지금은 정육면체를 만들어야 하니
+`BoxGeometry` 생성자를 호출하겠습니다.
 
 
 ```js
 ```js
 const boxWidth = 1;
 const boxWidth = 1;
@@ -200,49 +199,44 @@ const boxDepth = 1;
 const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
 const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
 ```
 ```
 
 
-We then create a basic material and set its color. Colors can
-be specified using standard CSS style 6 digit hex color values.
+다음으로 `Material`을 만들고 색을 지정합니다. 색을 지정할 때는 CSS처럼
+숫자 형태의 hex 코드를 이용합니다(`#` 대신 `0x`. 역주).
 
 
 ```js
 ```js
 const material = new THREE.MeshBasicMaterial({color: 0x44aa88});
 const material = new THREE.MeshBasicMaterial({color: 0x44aa88});
 ```
 ```
 
 
-We then create a `Mesh`. A `Mesh` in three represents the combination
-of a `Geometry` (the shape of the object) and a `Material` (how to draw
-the object, shiny or flat, what color, what texture(s) to apply. Etc.)
-as well as the position, orientation, and scale of that
-object in the scene.
+그리고 앞서 만든 `Geometry`(물체의 형태)와 `Material`(물체의 색, 밝기, 질감 등)을
+이용해 `Mesh`를 만듭니다. `Mesh`는 `Geometry`, `Material` 외에도 물체의 위치, 방향,
+크기 등을 담은 객체입니다.
 
 
 ```js
 ```js
 const cube = new THREE.Mesh(geometry, material);
 const cube = new THREE.Mesh(geometry, material);
 ```
 ```
 
 
-And finally we add that mesh to the scene
+마지막으로 완성된 정육면체 `Mesh`를 `Scene`에 넣어줍니다.
 
 
 ```js
 ```js
 scene.add(cube);
 scene.add(cube);
 ```
 ```
 
 
-We can then render the scene by calling the renderer's render function
-and passing it the scene and the camera
+`renderer`의 `render` 메서드에 `Scene`과 `Camera`를 넘겨주면 화면을 렌더링할
+수 있습니다.
 
 
 ```js
 ```js
 renderer.render(scene, camera);
 renderer.render(scene, camera);
 ```
 ```
 
 
-Here's a working example
+아래는 전체 코드입니다.
 
 
 {{{example url="../threejs-fundamentals.html" }}}
 {{{example url="../threejs-fundamentals.html" }}}
 
 
-It's kind of hard to tell that is a 3D cube since we're viewing
-it directly down the -Z axis and the cube itself is axis aligned
-so we're only seeing a single face.
-
-Let's animate it spinning and hopefully that will make
-it clear it's being drawn in 3D. To animate it we'll render inside a render loop using
-[`requestAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame).
+물론 위 예제는 3D 정육면체라고 하긴 어렵습니다. 코드 상으로 Three.js는
+분명 3D 정육면체를 그렸지만, 카메라가 -Z 방향을 바라보고, 정육면체도
+Z 축에 맞추어 정렬되어 있기 때문에 한 면만 보입니다.
 
 
-Here's our loop
+한 번 이 물체에 애니메이션을 주고 3D처럼 보이는지 확인해보죠.
+애니메이션을 구현하기 위해 [`requestAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) 루프 안에서 렌더링 함수를 호출합니다.
 
 
 ```js
 ```js
 function render(time) {
 function render(time) {
@@ -258,31 +252,31 @@ function render(time) {
 requestAnimationFrame(render);
 requestAnimationFrame(render);
 ```
 ```
 
 
-`requestAnimationFrame` is a request to the browser that you want to animate something.
-You pass it a function to be called. In our case that function is `render`. The browser
-will call your function and if you update anything related to the display of the
-page the browser will re-render the page. In our case we are calling three's
-`renderer.render` function which will draw our scene.
+`requestAnimationFrame`은 브라우저에 애니메이션 프레임을 요청하는 함수입니다.
+인자로 실행할 함수를 전달하면 되죠(이 경우는 `render` 함수). 브라우저는 넘겨받은
+함수를 실행하고, 페이지에 변화가 있다면 페이지를 다시 렌더링합니다. 위 예제에서는
+Three.js의 `renderer.render` 메서드를 호출해 씬을 렌더링하도록 했죠.
 
 
-`requestAnimationFrame` passes the time since the page loaded to
-our function. That time is passed in milliseconds. I find it's much
-easier to work with seconds so here we're converting that to seconds.
+`requestAnimationFrame`은 매개변수로 넘겨받은 함수에 페이지가 로드된 이후의 시간값을
+밀리초 단위로 넘겨줍니다. 전 초 단위가 더 익숙하기 때문에, 밀리초 단위를 초 단위로
+변경하였습니다.
 
 
-We then set the cube's X and Y rotation to the current time. These rotations
-are in [radians](https://en.wikipedia.org/wiki/Radian). There are 2 pi radians
-in a circle so our cube should turn around once on each axis in about 6.28
-seconds.
+그리고 정육면체의 X, Y축 회전값을 현재 시간값으로 설정합니다(이 회전값은 [라디안(radians)](https://ko.wikipedia.org/wiki/%EB%9D%BC%EB%94%94%EC%95%88)
+단위를 사용합니다). 360˚도는 2π 라디안이니 큐브는 각 축마다
+약 6.28초에 한 바퀴를 돌게 됩니다.
 
 
-We then render the scene and request another animation frame to continue
-our loop.
+그리고 씬을 렌더링 한 후, 브라우저에 재귀적으로 애니메이션 프레임을 요청해 이
+애니메이션이 반복되도록 합니다.
 
 
-Outside the loop we call `requestAnimationFrame` one time to start the loop.
+마지막으로 루프 바깥에서 `requestAnimationFrame`을 한 번 호출해 루프를
+시작합니다.
 
 
 {{{example url="../threejs-fundamentals-with-animation.html" }}}
 {{{example url="../threejs-fundamentals-with-animation.html" }}}
 
 
-It's a little better but it's still hard to see the 3d. What would help is to
-add some lighting so let's add a light. There are many kinds of lights in
-three.js which we'll go over in [a future article](threejs-lights.html). For now let's create a directional light.
+아까보단 낫지만 아직 3D 물체라고 부르기엔 뭔가 부족합니다. 광원을 추가해 그림자가
+지도록 하면 어떨까요? 나중에 [이 글](threejs-lights.html)에서 자세히 다루겠지만,
+Three.js에는 다양한 종류의 광원이 있습니다. 다 살펴보기 힘드니 지금은 예시로
+`DirectionalLight`를 사용해보도록 하죠.
 
 
 ```js
 ```js
 {
 {
@@ -294,38 +288,37 @@ three.js which we'll go over in [a future article](threejs-lights.html). For now
 }
 }
 ```
 ```
 
 
-Directional lights have a position and a target. Both default to 0, 0, 0. In our
-case we're setting the light's position to -1, 2, 4 so it's slightly on the left,
-above, and behind our camera. The target is still 0, 0, 0 so it will shine
-toward the origin.
+`DirectionnalLight`에는 `위치(position)`와 `목표(target)` 속성이 있습니다.
+기본값은 `0, 0, 0` 이죠. 먼저 `position`을 `-1, 2, 4`로 설정해 카메라보다
+약간 동서쪽, Z축으로는 약간 위로 보냅니다. `target`은 기본값 `0, 0, 0` 그대로
+두어 공간의 중앙을 비추도록 합니다.
 
 
-We also need to change the material. The `MeshBasicMaterial` is not affected by
-lights. Let's change it to a `MeshPhongMaterial` which is affected by lights.
+그리고 `material`도 바꿔야 합니다. `MeshBasicMaterial`은 광원에 반응하지 않으니,
+광원에 반응하는 `MeshPhongMaterial`로 바꿉니다(`phong`은 광원 반사 모델을 처음 개발한 사람 이름. 역주).
 
 
 ```js
 ```js
 -const material = new THREE.MeshBasicMaterial({color: 0x44aa88});  // greenish blue
 -const material = new THREE.MeshBasicMaterial({color: 0x44aa88});  // greenish blue
 +const material = new THREE.MeshPhongMaterial({color: 0x44aa88});  // greenish blue
 +const material = new THREE.MeshPhongMaterial({color: 0x44aa88});  // greenish blue
 ```
 ```
 
 
-Here is our new program structure
+다음은 현재까지의 프로그램 구조를 도식화 한 것이고,
 
 
 <div class="threejs_center"><img src="resources/images/threejs-1cube-with-directionallight.svg" style="width: 500px;"></div>
 <div class="threejs_center"><img src="resources/images/threejs-1cube-with-directionallight.svg" style="width: 500px;"></div>
 
 
-And here it is working.
+아래는 결과물입니다.
 
 
 {{{example url="../threejs-fundamentals-with-light.html" }}}
 {{{example url="../threejs-fundamentals-with-light.html" }}}
 
 
-It should now be pretty clearly 3D.
+이제 3D라고 불러도 어색하지 않네요.
 
 
-Just for the fun of it let's add 2 more cubes.
+재미를 위해서 한 번 정육면체를 2개만 더 만들어 봅시다.
 
 
-We'll use the same geometry for each cube but make a different
-material so each cube can be a different color.
+미리 만들어 놨던 `Geometry`를 사용하고, `Material`만 바꿔 다른 색을
+가진 큐브 2개를 만들겠습니다.
 
 
-First we'll make a function that creates a new material
-with the specified color. Then it creates a mesh using
-the specified geometry and adds it to the scene and
-sets its X position.
+먼저 함수를 하나 만들어보겠습니다. 이 함수는 넘겨받은 색상값으로
+새로운 `Material`을 만들고, 넘겨받은 `Geometry`와 조합해 새로운
+`Mesh`를 만듭니다. 그리고 씬에 추가한 후 넘겨받은 X축 값을 통해 물체를 이동시키죠.
 
 
 ```js
 ```js
 function makeInstance(geometry, color, x) {
 function makeInstance(geometry, color, x) {
@@ -340,8 +333,8 @@ function makeInstance(geometry, color, x) {
 }
 }
 ```
 ```
 
 
-Then we'll call it 3 times with 3 different colors and X positions
-saving the `Mesh` instances in an array.
+다음으로 3가지 다른 색상과 X축 값으로 이 함수를 호출해 결과물을 배열로
+저장합니다.
 
 
 ```js
 ```js
 const cubes = [
 const cubes = [
@@ -351,8 +344,8 @@ const cubes = [
 ];
 ];
 ```
 ```
 
 
-Finally we'll spin all 3 cubes in our render function. We
-compute a slightly different rotation for each one.
+마지막으로 `render` 함수에서 3개의 정육면체를 회전시킵니다. 동적인
+효과를 위해 각 큐브마다 약간 다른 값을 주도록 해보죠.
 
 
 ```js
 ```js
 function render(time) {
 function render(time) {
@@ -368,34 +361,31 @@ function render(time) {
   ...
   ...
 ```
 ```
 
 
-and here's that.
+결과물은 다음과 같습니다.
 
 
 {{{example url="../threejs-fundamentals-3-cubes.html" }}}
 {{{example url="../threejs-fundamentals-3-cubes.html" }}}
 
 
-If you compare it to the top down diagram above you can see
-it matches our expectations. With cubes at X = -2 and X = +2
-they are partially outside our frustum. They are also
-somewhat exaggeratedly warped since the field of view
-across the canvas is so extreme.
+아까 위에서 좌표로 도식한 그림과 위 결과물을 비교해보면, 예상대로
+X축으로 -2, +2만큼 이동한 정육면체들의 일부가 절두체에서 약간 벗어났습니다.
+또한 가운데 정육면체에 비해 굉장히 굴절되어 보이는데, 이는 우리가 설정한 시야각이
+너무 좁은 탓입니다.
 
 
-Our program now has this structure
+위 프로그램은 구조는 다음과 같습니다.
 
 
 <div class="threejs_center"><img src="resources/images/threejs-3cubes-scene.svg" style="width: 610px;"></div>
 <div class="threejs_center"><img src="resources/images/threejs-3cubes-scene.svg" style="width: 610px;"></div>
 
 
-As you can see we have 3 `Mesh` objects each referencing the same `BoxGeometry`.
-Each `Mesh` references a unique `MeshPhongMaterial` so that each cube can have
-a different color.
+그림을 보면 각 `Mesh` 객체는 같은 `BoxGeometry`를 참조합니다. 그러나
+각 `Mesh`는 다른 `MeshPhongMaterial`을 참조하므로 다른 색을 띄죠.
 
 
-I hope this short intro helps to get things started. [Next up we'll cover
-making our code responsive so it is adaptable to multiple situations](threejs-responsive.html).
+이 인트로가 Three.js를 시작하는 데 도움이 되었으면 합니다.
+[다음 장에서는 코드를 반응형으로 만들어 다양한 상황에 적용할 수 있도록 해 볼 것입니다](threejs-responsive.html).
 
 
 <div id="es6" class="threejs_bottombar">
 <div id="es6" class="threejs_bottombar">
-<h3>es6 modules, three.js, and folder structure</h3>
-<p>As of version r106 the preferred way to use three.js is via <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import">es6 modules</a>.</p>
+<h3>es6 모듈, Three.js, 프로젝트 구조</h3>
+<p>Three.js r106 릴리즈 이후에서는 three.js를 <a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/import">es6 모듈</a>로 사용하길 권장합니다.</p>
 <p>
 <p>
-es6 modules can be loaded via the <code>import</code> keyword in a script
-or inline via a <code>&lt;script type="module"&gt;</code> tag. Here's an example of
-both
+es6 모듈은 js 파일이나 인라인 <code>&lt;script type="module"&gt;</code> 태그 안에서
+<code>import</code> 키워드를 사용해 로드할 수 있습니다.
 </p>
 </p>
 <pre class=prettyprint>
 <pre class=prettyprint>
 &lt;script type="module"&gt;
 &lt;script type="module"&gt;
@@ -406,13 +396,12 @@ import * as THREE from './resources/threejs/r115/build/three.module.js';
 &lt;/script&gt;
 &lt;/script&gt;
 </pre>
 </pre>
 <p>
 <p>
-Paths must be absolute or relative. Relative paths always start with <code>./</code> or <code>../</code>
-which is different than other tags like <code>&lt;img&gt;</code> and <code>&lt;a&gt;</code>.
+경로는 절대경로나 상대경로를 사용해야 하며, 상대경로는 <code>&lt;img&gt;</code>, <code>&lt;a&gt;</code> 태그와
+달리 <code>./</code> 또는 <code>../</code>로 시작해야 합니다.
 </p>
 </p>
 <p>
 <p>
-References to the same script will only be loaded once as long as their absolute paths
-are exactly the same. For three.js this means it's required that you put all the examples
-libraries in the correct folder structure
+만약 절대경로가 같다면 같은 script는 한 번만 로드됩니다. Three.js 기반 프로젝트의 폴더 구조를
+잘 구성해야 하는 가장 큰 이유이죠.
 </p>
 </p>
 <pre class="dos">
 <pre class="dos">
 someFolder
 someFolder
@@ -439,33 +428,30 @@ someFolder
      ...
      ...
 </pre>
 </pre>
 <p>
 <p>
-The reason this folder structure is required is because the scripts in the
-examples like <a href="https://github.com/mrdoob/three.js/blob/master/examples/jsm/controls/OrbitControls.js"><code>OrbitControls.js</code></a>
-have hard coded relative paths like
+이유인 즉 <a href="https://github.com/mrdoob/three.js/blob/master/examples/jsm/controls/OrbitControls.js"><code>OrbitControls.js</code></a>
+같은 코드는 다음처럼 상대경로로 모듈을 로드하기 때문에
 </p>
 </p>
 <pre class="prettyprint">
 <pre class="prettyprint">
 import * as THREE from '../../../build/three.module.js';
 import * as THREE from '../../../build/three.module.js';
 </pre>
 </pre>
 <p>
 <p>
-Using the same structure assures then when you import both three and one of the example
-libraries they'll both reference the same three.module.js file.
+같은 폴더 구조를 사용함으로써 모든 예제 스크립트가 같은 three.module.js 파일을
+참조하도록 할 수 있죠.
 </p>
 </p>
 <pre class="prettyprint">
 <pre class="prettyprint">
 import * as THREE from './someFolder/build/three.module.js';
 import * as THREE from './someFolder/build/three.module.js';
 import {OrbitControls} from './someFolder/examples/jsm/controls/OrbitControls.js';
 import {OrbitControls} from './someFolder/examples/jsm/controls/OrbitControls.js';
 </pre>
 </pre>
-<p>This includes when using a CDN. Be sure your path to <code>three.modules.js</code> ends with
-<code>/build/three.modules.js</code>. For example</p>
+<p>아래는 CDN을 사용하는 예시입니다. <code>three.modules.js</code>의 경로가 <code>/build/three.modules.js</code>
+로 끝나야 한다는 것을 명심하세요.</p>
 <pre class="prettyprint">
 <pre class="prettyprint">
 import * as THREE from 'https://unpkg.com/[email protected]/<b>build/three.module.js</b>';
 import * as THREE from 'https://unpkg.com/[email protected]/<b>build/three.module.js</b>';
 import {OrbitControls} from 'https://unpkg.com/[email protected]/examples/jsm/controls/OrbitControls.js';
 import {OrbitControls} from 'https://unpkg.com/[email protected]/examples/jsm/controls/OrbitControls.js';
 </pre>
 </pre>
-<p>If you'd prefer the old <code>&lt;script src="path/to/three.js"&gt;&lt;/script&gt;</code> style
-you can check out <a href="https://r105.threejsfundamentals.org">an older version of this site</a>.
-Three.js has a policy of not worrying about backward compatibility. They expect you to use a specific
-version, as in you're expected to download the code and put it in your project. When upgrading to a newer version
-you can read the <a href="https://github.com/mrdoob/three.js/wiki/Migration-Guide">migration guide</a> to
-see what you need to change. It would be too much work to maintain both an es6 module and a class script
-version of this site so going forward this site will only show es6 module style. As stated elsewhere,
-to support legacy browsers look into a <a href="https://babeljs.io">transpiler</a>.</p>
+<p>만약 여러분이 <code>&lt;script src="path/to/three.js"&gt;&lt;/script&gt;</code> 같은 스타일을 선호한다면,
+<a href="https://r105.threejsfundamentals.org">이 사이트의 이전 버젼을 확인해보시기 바랍니다</a>.
+Three.js에는 하위 호환성을 보장하는 정책이 있습니다. Three.js의 개발자들은 여러분이 특정 버젼을 골라서 쓸
+거라고 가정 하에 라이브러리를 개발하죠. 새 버젼으로 업그레이드할 때는 <a href="https://github.com/mrdoob/three.js/wiki/Migration-Guide">마이그레이션 가이드</a>를 참조해 바뀐 사항을 업데이트 하면 됩니다. es6 모듈과 스크립트
+버젼을 모두 다루기는 너무 버거우니 이 사이트에서는 es6 모듈 스타일만 사용할 것입니다. 개발자들이 늘상 추천하듯
+구형 브라우저를 지원하려면 바벨 등의 <a href="https://babeljs.io">트랜스파일러</a>를 찾아보기 바랍니다.</p>
 </div>
 </div>

+ 271 - 0
threejs/lessons/kr/threejs-responsive.md

@@ -0,0 +1,271 @@
+Title: Three.js 반응형 디자인
+Description: Three.js 프로젝트를 반응형으로 만들기
+TOC: 반응형 디자인
+
+Three.js 두 번째 튜토리얼에 오신 것을 환영합니다!
+첫 번째 튜토리얼은 [Three.js의 기초](threejs-fundamentals.html)에 관한 내용이었죠.
+아직 이전 장을 보지 않았다면 이전 글을 먼저 읽어보길 추천합니다.
+
+이 장에서는 Three.js 앱을 어떤 환경에서든 구동할 수 있도록
+반응형으로 만드는 법에 대해 알아볼 것입니다. 웹에서 반응형이란
+웹 페이지를 PC, 타블렛, 스마트폰 등 다양한 환경에서 이용하기
+용이하도록 사이즈에 맞춰 콘텐츠를 최적화하는 것을 의미하죠.
+
+Three.js의 경우 일반 웹보다 고려해야할 요소가 많습니다.
+예를 들어 상하좌우에 컨트롤 패널이 있는 3D 에디터라든가,
+문서 사이에 들어가는 동적 그래프를 상상해볼 수 있죠.
+
+이전 글에서는 사이즈나 CSS 스타일을 정의하지 않은 canvas를 썼었죠.
+
+```html
+<canvas id="c"></canvas>
+```
+
+canvas 요소는 기본적으로 300x150 픽셀입니다.
+
+웹에서 어떤 요소의 크기를 지정할 때는 보통 CSS를 권장하죠.
+
+canvas가 페이지 전체를 차지하도록 CSS를 작성해봅시다.
+
+```html
+<style>
+html, body {
+   margin: 0;
+   height: 100%;
+}
+#c {
+   width: 100%;
+   height: 100%;
+   display: block;
+}
+</style>
+```
+
+body 요소는 기본적으로 5픽셀의 margin이 지정되어 있으니 `margin: 0`으로
+설정해 여백을 모두 없애줍니다. html과 body 요소의 높이를 지정하지 않으면
+컨텐츠의 높이만큼만 커지니, 높이를 100%로 맞춰 창 전체를 채우도록 합니다.
+
+그리고 `id=c`인 요소의 크기를 100%로 지정해 컨테이너, 이 예제에서는 body
+요소의 크기와 동일하게 맞춥니다.
+
+canvas 요소의 기본 `display` 속성은 `inline`입니다. `inline` 속성은 글자
+처럼 취급되어 흰 공백을 남길 수 있으니 `display` 속성을 `block`으로 지정합니다.
+
+아래는 이전 장에서 만든 예제에 방금 작성한 CSS 스타일을 덧붙인 것입니다.
+
+{{{example url="../threejs-responsive-no-resize.html" }}}
+
+canvas가 창 전체를 채우긴 했지만 문제가 좀 있네요. 정육면체가 창 크기에
+따라 늘어나 정육면체라기보다 너무 길거나 넓은 육면체처럼 보입니다. 예제를
+새 창에서 열어 창 크기를 조절해보세요. 정육면체가 어떻게 변하는지 확인할
+수 있을 겁니다.
+
+<img src="resources/images/resize-incorrect-aspect.png" width="407" class="threejs_center nobg">
+
+또 다른 문제는 저화질, 그러니까 깨지고 흐릿하게 보인다는 점입니다.
+창을 아주 크게 조절하면 문제를 바로 알 수 있을 거에요.
+
+<img src="resources/images/resize-low-res.png" class="threejs_center nobg">
+
+창 크기에 따라 늘어나는 문제부터 해결해봅시다. 먼저 카메라의 aspect(비율)
+속성을 canvas의 화면 크기에 맞춰야 합니다. 이는 canvas의 `clientWidth`와
+`clientHeight` 속성을 이용해 간단히 해결할 수 있죠.
+
+그리고 렌더링 함수를 다음처럼 수정합니다.
+
+```js
+function render(time) {
+  time *= 0.001;
+
++  const canvas = renderer.domElement;
++  camera.aspect = canvas.clientWidth / canvas.clientHeight;
++  camera.updateProjectionMatrix();
+
+  ...
+```
+
+이제 정육면체는 더이상 늘어나거나 찌그러들지 않을 겁니다.
+
+{{{example url="../threejs-responsive-update-camera.html" }}}
+
+예제를 새 창에서 열어 창 크기를 조절해보면, 정육면체의 비율이
+창 크기와 상관없이 그대로 유지되는 것을 확인할 수 있을 겁니다.
+
+<img src="resources/images/resize-correct-aspect.png" width="407" class="threejs_center nobg">
+
+이제 계단현상을 없애 봅시다.
+
+canvas 요소에는 두 종류의 크기값이 있습니다. 하나는 아까 CSS로
+설정한 canvas 요소의 크기이고, 다른 하나는 canvas 원본 픽셀 수에
+대한 값입니다. 예를 들어 128x64 픽셀인 이미지가 있다고 합시다.
+우리는 CSS를 이용해 이 이미지 요소를 400x200 픽셀로 보이도록 할 수
+있죠. canvas도 마찬가지입니다. 편의상 CSS로 지정한 크기를 디스플레이
+크기라고 부르겠습니다.
+
+```html
+<img src="128x64이미지.jpg" style="width:400px; height:200px">
+```
+
+canvas의 원본 크기, 해상도는 드로잉버퍼(drawingbuffer)라고 불립니다.
+Three.js에서는 `renderer.setSize` 메서드를 호출해 canvas의 드로잉버퍼
+크기를 지정할 수 있죠. 어떤 크기를 골라야 하냐구요? 당연히 "canvas의
+디스플레이 크기"죠! 다시 canvas의 `clientWidth`와 `clientHeight`를
+이용합시다.
+
+canvas의 원본 크기와 디스플레이 크기를 비교해 원본 크기를 변경할지 결정하는
+함수를 하나 만들어줍니다.
+
+```js
+function resizeRendererToDisplaySize(renderer) {
+  const canvas = renderer.domElement;
+  const width = canvas.clientWidth;
+  const height = canvas.clientHeight;
+  const needResize = canvas.width !== width || canvas.height !== height;
+  if (needResize) {
+    renderer.setSize(width, height, false);
+  }
+  return needResize;
+}
+```
+
+canvas를 리사이징할 필요가 있는지 검사했다는 점에 주의하세요.
+canvas 스펙상 리사이징은 화면을 다시 렌더링해야만 하므로, 같은
+사이즈일 때는 리사이징을 하지 않으므로써 불필요한 자원 낭비를
+막는 것이 좋습니다.
+
+canvas의 크기가 다르다면, `renderer.setSize` 메서드를 호출해
+새로운 width와 height를 넘겨줍니다. `renderer.setSize` 메서드는
+기본적으로 CSS의 크기를 설정하니 마지막 인자로 `false`를 넘겨주는
+것을 잊지 마세요. canvas가 다른 요소와 어울리려면 Three.js에서
+CSS를 제어하는 것 보다 다른 요소들처럼 CSS로 제어하는 것이 일관성
+있는 프로그래밍일 테니까요.
+
+위 함수는 canvas를 리사이징했으면 `true`를 반환합니다. 이 값을
+이용해 다른 요소들이 업데이트 해야 할지도 결정할 수 있겠네요.
+새로 만든 함수를 이용해 `render` 함수를 수정합시다.
+
+```js
+function render(time) {
+  time *= 0.001;
+
++  if (resizeRendererToDisplaySize(renderer)) {
++    const canvas = renderer.domElement;
++    camera.aspect = canvas.clientWidth / canvas.clientHeight;
++    camera.updateProjectionMatrix();
++  }
+
+  ...
+```
+
+canvas의 비율이 변하려면 canvas의 사이즈가 변해야 하므로,
+`resizeRendererToDisplaySize` 함수가 `true`를 반환했을 때만
+카메라의 비율을 변경합니다.
+
+{{{example url="../threejs-responsive.html" }}}
+
+이제 디스플레이 크기에 맞는 해상도로 렌더링될 겁니다.
+
+CSS가 디스플레이 크기를 제어하도록 해야 한다는 주장을 보충해보겠습니다.
+일단 이 코드를 [별도의 js 파일](../threejs-responsive.js)로 저장해주세요.
+아래의 예시들은 CSS가 디스플레이 크기를 제어하도록 한 예시입니다.
+잘 살펴보면 추가로 다른 코드를 써야할 필요가 없다는 걸 알 수 있죠.
+
+먼저 canvas를 텍스트 사이에 끼워 넣어보죠.
+
+{{{example url="../threejs-responsive-paragraph.html" startPane="html" }}}
+
+다음은 우측 컨트롤 패널 크기를 조정할 수 있는 에디터 형태의
+레이아웃에서 활용한 예시입니다.
+
+{{{example url="../threejs-responsive-editor.html" startPane="html" }}}
+
+HTML, CSS만 바뀌고 자바스크립트 코드는 한 줄도 바뀌지 않았습니다.
+
+## HD-DPI 디스플레이 다루기
+
+HD-DPI는 고해상도(high-density dot per inch)의 줄임말입니다.
+많은 Windows 기기나 맥, 스마트폰이 이 디스플레이를 사용하죠(스마트폰의
+실제 화면 크기가 데스크탑에 비해 훨씬 작지만, 해상도는 비슷한 경우를
+생각하면 됩니다. 한 픽셀을 선명하게 표현하기 위해 다수의 작은 픽셀을
+넣는 것. 역주).
+
+브라우저에서는 이에 대응하기 위해 픽셀의 집적도에 상관 없이
+CSS 픽셀을 이용해 요소의 크기를 지정합니다. 스마트폰이든,
+데스크탑이든 브라우저는 요소를 같은 크기로 좀 더 촘촘하게
+할 뿐이죠.
+
+Three.js로 HD-DPI를 다루는 방법은 아주 다양합니다.
+
+첫째는 아무것도 하지 않는 것입니다. 3D 렌더링은 많은 GPU 자원을
+소모하기 때문에 아마 가장 흔한 경우일 겁니다. 2018년의 이야기이긴
+하지만, 모바일 기기는 데스크탑에 비해 GPU 성능이 부족함에도 더 높은
+해상도를 가진 경우가 대부분입니다. 현재 플래그쉽 스마트폰은 HD-DPI
+약 3배의 해상도를 지녔습니다. 쉽게 말해 HD-DPI가 아닌 기기와 비교했을
+때 한 픽셀 당 픽셀 수가 1:9라는 것이고 이는 9배나 더 많은 렌더링
+작업을 처리해야 한다는 것을 의미하죠.
+
+9배 많은 픽셀을 처리하는 건 굉장히 까다로운 작업이지만, 만약 코드를
+저대로 내버려 둔다면 우리의 코드가 1픽셀을 계산할 때마다 브라우저는
+해당 픽셀보다 3배 큰 픽셀을 렌더링해야 합니다(3배 곱하기 3배 = 9배 많은 픽셀).
+
+이는 낮은 FPS, 즉 화면이 버벅거리게 만들 것이므로 무거운 Three.js
+앱을 만들 때는 지양해야 하는 요소이죠.
+
+물론 지양해야 한다는 건 기기의 해상도에 따라 화면을 렌더링할
+다른 방법들이 더 있다는 의미입니다.
+
+하나는 `rederer.setPixelRatio` 메서드를 이용해 해상도 배율을 알려주는
+것입니다. 브라우저로부터 CSS 픽셀과 실제 기기 픽셀의 배율을 받아
+Three.js에게 넘겨주는 것이죠.
+
+```js
+    renderer.setPixelRatio(window.devicePixelRatio);
+```
+
+그러면 `renderer.setSize`는 이제 알아서 사이즈에 배율을 곱해
+리사이징할 것입니다....만 **이 방법은 추천하지 않습니다**.
+
+다른 방법은 canvas를 리사이징할 때 직접 계산하는 것입니다.
+
+```js
+    function resizeRendererToDisplaySize(renderer) {
+      const canvas = renderer.domElement;
+      const pixelRatio = window.devicePixelRatio;
+      const width  = canvas.clientWidth  * pixelRatio | 0;
+      const height = canvas.clientHeight * pixelRatio | 0;
+      const needResize = canvas.width !== width || canvas.height !== height;
+      if (needResize) {
+        renderer.setSize(width, height, false);
+      }
+      return needResize;
+    }
+```
+
+객관적으로 따져봐도 이 방법이 훨씬 낫습니다. 이 방법으로는 개발자가
+원하는 결과가 나오니까요. Three.js로 앱을 만들 때 언제 canvas의
+드로잉버퍼 사이즈를 알아야 할지 특정하기란 어렵습니다. 예를 들어 전처리
+필터를 만든다거나, `gl_FragCoord`에 접근하는 쉐이더를 만든다거나,
+스크린샷을 찍는다거나, GPU가 관여하는 픽셀 수를 가져 온다거나, 
+
+
+This second way is objectively better. Why? Because it means I get what I ask for.
+There are many cases when using three.js where we need to know the actual
+size of the canvas's drawingBuffer. For example when making a post processing filter,
+or if we are making a shader that accesses `gl_FragCoord`, if we are making
+a screenshot, or reading pixels for GPU picking, for drawing into a 2D canvas,
+etc... There many many cases where if we use `setPixelRatio` then our actual size will be different
+than the size we requested and we'll have to guess when to use the size
+we asked for and when to use the size three.js is actually using.
+By doing it ourselves we always know the size being used is the size we requested.
+There is no special case where magic is happening behind the scenes.
+
+Here's an example using the code above.
+
+{{{example url="../threejs-responsive-hd-dpi.html" }}}
+
+It might be hard to see the difference but if you have an HD-DPI
+display and you compare this sample to those above you should
+notice the edges are more crisp.
+
+This article covered a very basic but fundamental topic. Next up lets quickly
+[go over the basic primitives that three.js provides](threejs-primitives.html).