|
@@ -8,16 +8,16 @@ TOC: 그림자(Shadows)
|
|
|
|
|
|
※ 이전 글인 [카메라에 관한 글](threejs-cameras.html)과
|
|
|
[조명에 관한 글](threejs-lights.html)에서 이 장을 읽는 꼭 필요한 내용을
|
|
|
-다루었으니 꼭 먼저 읽고 오기 바랍니다.
|
|
|
+다루었으니 꼭 먼저 읽고 오시기 바랍니다.
|
|
|
|
|
|
|
|
|
-컴퓨터에서 그림자란 그리 간단한 주제가 아닙니다. 그림자를 구현하는 방법은
|
|
|
+3D 그래픽에서 그림자란 그리 간단한 주제가 아닙니다. 그림자를 구현하는 방법은
|
|
|
아주 많지만 모두 단점이 있기에 어떤 것이 가장 효율적이라고 말하기 어렵습니다.
|
|
|
이는 Three.js에서 제공하는 방법도 마찬가지이죠.
|
|
|
|
|
|
-Three.js는 기본적으로 *그림자 맵(shadow maps)*을 사용합니다. 그림자 맵은
|
|
|
+Three.js는 기본적으로 *그림자 맵(shadow maps)*을 사용합니다. 그림자 맵이란
|
|
|
*그림자를 만드는 빛의 영향을 받는, 그림자를 드리우는 모든 물체를 빛의 시점에서
|
|
|
-렌더링*하는 방식을 말합니다. 중요하니 **다시 한 번 읽어보세요!**
|
|
|
+렌더링*하는 기법을 말합니다. 중요하니 **한 번 더 읽어보세요!**
|
|
|
|
|
|
다시 말해, 공간 안에 20개의 물체와 5개의 조명이 있고, 20개의 물체 모두
|
|
|
그림자를 드리우며 5개의 조명 모두 그림자를 지게 한다면, 한 장면을 만들기
|
|
@@ -114,27 +114,27 @@ const planeSize = 1;
|
|
|
const shadowGeo = new THREE.PlaneBufferGeometry(planeSize, planeSize);
|
|
|
```
|
|
|
|
|
|
-이제 구체를 아주 많이 만들겠습니다. 각각 구체마다 `기초` 역할을 할
|
|
|
+이제 구체를 아주 많이 만들겠습니다. 각각 구체마다 `컨테이너` 역할을 할
|
|
|
`THREE.Object3D`를 만들고, 그림자 평면 mesh, 구체 mesh를 이
|
|
|
-기초의 자식으로 만듭니다. 이러면 구체와 그림자를 동시에 움직일 수
|
|
|
+컨테이너의 자식으로 만듭니다. 이러면 구체와 그림자를 동시에 움직일 수
|
|
|
있죠. z-파이팅 현상을 막기 위해 그림자는 땅보다 약간 위에 둡니다.
|
|
|
또 `depthWrite` 속성을 false로 설정해 그림자끼리 충돌하는 현상을
|
|
|
막습니다. 이 충돌 현상은 [다른 글](threejs-transparency.html)에서
|
|
|
더 자세히 이야기할 거예요. 그림자는 빛을 반사하지 않으니 `MeshBasicMaterial`을
|
|
|
사용합니다.
|
|
|
|
|
|
-구체의 색상을 각각 다르게 지정하고, 기초, 구체 mesh, 그림자 mesh와
|
|
|
+구체의 색상을 각각 다르게 지정하고, 컨테이너, 구체 mesh, 그림자 mesh와
|
|
|
구체의 처음 y축 좌표를 배열에 기록합니다.
|
|
|
|
|
|
```js
|
|
|
const numSpheres = 15;
|
|
|
for (let i = 0; i < numSpheres; ++i) {
|
|
|
- // 구체와 그림자가 같이 움직이도록 기초(base)를 만듭니다
|
|
|
+ // 구체와 그림자가 같이 움직이도록 컨테이너(base)를 만듭니다
|
|
|
const base = new THREE.Object3D();
|
|
|
scene.add(base);
|
|
|
|
|
|
/**
|
|
|
- * 그림자를 기초에 추가합니다
|
|
|
+ * 그림자를 컨테이너에 추가합니다
|
|
|
* 주의: 여기서는 각 구체의 투명도를 따로 설정할 수 있도록
|
|
|
* 재질을 각각 따로 만듬
|
|
|
*/
|
|
@@ -150,7 +150,7 @@ for (let i = 0; i < numSpheres; ++i) {
|
|
|
shadowMesh.scale.set(shadowSize, shadowSize, shadowSize);
|
|
|
base.add(shadowMesh);
|
|
|
|
|
|
- // 구체를 기초에 추가
|
|
|
+ // 구체를 컨테이너에 추가
|
|
|
const u = i / numSpheres; // 반복문이 진행됨에 따라 0에서 1사이 값을 지정
|
|
|
const sphereMat = new THREE.MeshPhongMaterial();
|
|
|
sphereMat.color.setHSL(u, 1, .75);
|
|
@@ -163,8 +163,8 @@ for (let i = 0; i < numSpheres; ++i) {
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-조명은 2개를 만들겠습니다. 하나는 `HemisphereLight`, 강도를 2로 설정해 굉장히 밝은
|
|
|
-화면을 만들 겁니다.
|
|
|
+조명은 2개를 만들겠습니다. 하나는 `HemisphereLight`, 강도를 2로 설정해 화면을 아주
|
|
|
+밝게 설정할 겁니다.
|
|
|
|
|
|
```js
|
|
|
{
|
|
@@ -191,8 +191,8 @@ for (let i = 0; i < numSpheres; ++i) {
|
|
|
```
|
|
|
|
|
|
이대로도 렌더링해도 좋지만, 구체들에 애니메이션을 한 번 줘봅시다.
|
|
|
-기초를 움직여 구체, 그림자가 xz축 평면을 따라 움직이게 하고,
|
|
|
-`Math.abs(Math.sin(time))`를 사용해 구체에 위아래로 통통 튀는
|
|
|
+컨테이너를 움직여 구체, 그림자가 xz축 평면을 따라 움직이게 하고,
|
|
|
+`Math.abs(Math.sin(time))`를 사용해 구체에 공처럼 통통 튀는
|
|
|
애니메이션을 넣어줍니다. 또 그림자 재질의 투명도를 조절해 구체가
|
|
|
높을수록 그림자가 옅어지도록 합니다.
|
|
|
|
|
@@ -209,8 +209,8 @@ function render(time) {
|
|
|
const u = ndx / sphereShadowBases.length;
|
|
|
|
|
|
/**
|
|
|
- * 기초의 위치를 계산합니다. 구체와 그림자가
|
|
|
- * 기초에 종속적이므로 위치가 같이 변합니다
|
|
|
+ * 컨테이너의 위치를 계산합니다. 구체와 그림자가
|
|
|
+ * 컨테이너에 종속적이므로 위치가 같이 변합니다
|
|
|
*/
|
|
|
const speed = time * .2;
|
|
|
const angle = speed + u * Math.PI * 2 * (ndx % 1 ? 1 : -1);
|
|
@@ -232,45 +232,42 @@ function render(time) {
|
|
|
|
|
|
{{{example url="../threejs-shadows-fake.html" }}}
|
|
|
|
|
|
-In some apps it's common to use a round or oval shadow for everything but
|
|
|
-of course you could also use different shaped shadow textures. You might also
|
|
|
-give the shadow a harder edge. A good example of using this type
|
|
|
-of shadow is [Animal Crossing Pocket Camp](https://www.google.com/search?tbm=isch&q=animal+crossing+pocket+camp+screenshots)
|
|
|
-where you can see each character has a simple round shadow. It's effective and cheap.
|
|
|
-[Monument Valley](https://www.google.com/search?q=monument+valley+screenshots&tbm=isch)
|
|
|
-appears to also use this kind of shadow for the main character.
|
|
|
+물론 다른 모양의 그림자를 사용해야 하는 경우도 있습니다. 그림자의 경계를 분명하게
|
|
|
+하고 싶을 수도 있죠. 하지만 모든 물체의 그림자를 둥글게 표현하는 것이 좋은 경우도
|
|
|
+분명 있습니다. 모든 그림자를 둥글게 표현한 예 중 하나는 [동물의 숲 포켓 캠프](https://www.google.com/search?tbm=isch&q=animal+crossing+pocket+camp+screenshots)입니다.
|
|
|
+자연스럽고 성능면에서도 이득이죠. [Monument Valley](https://www.google.com/search?q=monument+valley+screenshots&tbm=isch)도
|
|
|
+메인 캐릭터에 이런 그림자를 사용한 것으로 보입니다.
|
|
|
|
|
|
-So, moving on to shadow maps, there are 3 lights which can cast shadows. The `DirectionalLight`,
|
|
|
-the `PointLight`, and the `SpotLight`.
|
|
|
+이제 그림자 맵을 살펴보겠습니다. 그림자를 드리울 수 있는 조명은 3가지, `DirectionalLight`,
|
|
|
+`PointLight`, `SpotLight`입니다.
|
|
|
|
|
|
-Let's start with the `DirectionalLight` with the helper example from [the lights article](threejs-lights.html).
|
|
|
+[조명에 관한 글](threejs-lights.html)에서 썼던 예제로 먼저 `DirectionalLight`부터
|
|
|
+살펴보죠.
|
|
|
|
|
|
-The first thing we need to do is turn on shadows in the renderer.
|
|
|
+먼저 renderer의 그림자 맵 옵션을 켜야 합니다.
|
|
|
|
|
|
```js
|
|
|
const renderer = new THREE.WebGLRenderer({canvas});
|
|
|
+renderer.shadowMap.enabled = true;
|
|
|
```
|
|
|
|
|
|
-Then we also need to tell the light to cast a shadow
|
|
|
+조명도 그림자를 드리우도록 옵션을 활성화합니다.
|
|
|
|
|
|
```js
|
|
|
const light = new THREE.DirectionalLight(color, intensity);
|
|
|
+light.castShadow = true;
|
|
|
```
|
|
|
|
|
|
-We also need to go to each mesh in the scene and decide if it should
|
|
|
-both cast shadows and/or receive shadows.
|
|
|
+또한 장면(scene) 안 각 mesh에 그림자를 드리울지, 그림자의 영향을 받을지 설정해줘야 합니다.
|
|
|
|
|
|
-Let's make the plane (the ground) only receive shadows since we don't
|
|
|
-really care what happens underneath.
|
|
|
+바닥 아래는 굳이 신경 쓸 필요가 없으니 평면(바닥)은 그림자의 영향만 받게 하겠습니다.
|
|
|
|
|
|
```js
|
|
|
const mesh = new THREE.Mesh(planeGeo, planeMat);
|
|
|
mesh.receiveShadow = true;
|
|
|
```
|
|
|
|
|
|
-For the cube and the sphere let's have them both receive and cast shadows
|
|
|
+정육면체와 구체는 그림자도 드리우고, 영향도 받도록 설정합니다.
|
|
|
|
|
|
```js
|
|
|
const mesh = new THREE.Mesh(cubeGeo, cubeMat);
|
|
@@ -284,48 +281,47 @@ mesh.castShadow = true;
|
|
|
mesh.receiveShadow = true;
|
|
|
```
|
|
|
|
|
|
-And then we run it.
|
|
|
+이제 실행해보죠.
|
|
|
|
|
|
{{{example url="../threejs-shadows-directional-light.html" }}}
|
|
|
|
|
|
-What happened? Why are parts of the shadows missing?
|
|
|
+이런, 그림자 일부가 잘려나간 것이 보이나요?
|
|
|
|
|
|
-The reason is shadow maps are created by rendering the scene from the point
|
|
|
-of view of the light. In this case there is a camera at the `DirectionalLight`
|
|
|
-that is looking at its target. Just like [the camera's we previously covered](threejs-cameras.html)
|
|
|
-the light's shadow camera defines an area inside of which
|
|
|
-the shadows get rendered. In the example above that area is too small.
|
|
|
+이는 빛의 시점에서 장면을 렌더링해 그림자 맵을 만들기 때문입니다. 위 예제를 예로 들면
|
|
|
+`DirectionalLight`의 위치에 카메라가 있고, 해당 조명의 목표를 바라보는 것이죠. 조명의
|
|
|
+그림자에는 별도의 카메라가 있고, 이전에 [카메라에 관한 글](threejs-cameras.html)에서
|
|
|
+설명한 것처럼 일정 공간 안의 그림자만 렌더링합니다. 위 예제에서는 그 공간이 너무 좁은
|
|
|
+것이죠.
|
|
|
|
|
|
-In order to visualize that area we can get the light's shadow camera and add
|
|
|
-a `CameraHelper` to the scene.
|
|
|
+그림자용 카메라를 시각화하기 위해 조명의 그림자 속성에서 카메라를 가져와 `CameraHelper`를
|
|
|
+생성한 뒤, 장면에 추가하겠습니다.
|
|
|
|
|
|
```js
|
|
|
const cameraHelper = new THREE.CameraHelper(light.shadow.camera);
|
|
|
scene.add(cameraHelper);
|
|
|
```
|
|
|
|
|
|
-And now you can see the area for which shadows are cast and received.
|
|
|
+이제 그림자가 렌더링되는 공간을 확인할 수 있을 겁니다.
|
|
|
|
|
|
{{{example url="../threejs-shadows-directional-light-with-camera-helper.html" }}}
|
|
|
|
|
|
-Adjust the target x value back and forth and it should be pretty clear that only
|
|
|
-what's inside the light's shadow camera box is where shadows are drawn.
|
|
|
+target의 x 값을 조정해보면 그림자용 카메라 범위 안에 있는 곳에만 그림자가 보이는
|
|
|
+것을 확인할 수 있을 겁니다.
|
|
|
|
|
|
-We can adjust the size of that box by adjusting the light's shadow camera.
|
|
|
+이 공간의 크기는 이 카메라의 속성을 수정해 바꿀 수 있습니다.
|
|
|
|
|
|
-Let's add some GUI setting to adjust the light's shadow camera box. Since a
|
|
|
-`DirectionalLight` represents light all going in a parallel direction, the
|
|
|
-`DirectionalLight` uses an `OrthographicCamera` for its shadow camera.
|
|
|
-We went over how an `OrthographicCamera` works in [the previous article about cameras](threejs-cameras.html).
|
|
|
+그림자용 카메라의 속성을 수정하는 GUI를 추가해보죠. `DirectionalLight`는 빛이 평행으로
|
|
|
+나아가므로, `DirectionalLight`는 그림자용 카메라로 `OrthographicCamera`(정사영 카메라)를
|
|
|
+사용합니다. `OrthographicCamera`가 뭔지 잘 기억나지 않는다면, [카메라에 관한 이전 글](threejs-cameras.html)을
|
|
|
+참고하세요.
|
|
|
|
|
|
-Recall an `OrthographicCamera` defines
|
|
|
-its box or *view frustum* by its `left`, `right`, `top`, `bottom`, `near`, `far`,
|
|
|
-and `zoom` properties.
|
|
|
+`OrthographicCamera`의 시야는 육면체나 *절두체(frustum)*로 정의한다고 했었죠. `left`,
|
|
|
+`right`, `top`, `bottom`, `near`, `far`, `zoom` 속성을 지정해서요.
|
|
|
|
|
|
-Again let's make a helper class for the dat.GUI. We'll make a `DimensionGUIHelper`
|
|
|
-that we'll pass an object and 2 properties. It will present one property that dat.GUI
|
|
|
-can adjust and in response will set the two properties one positive and one negative.
|
|
|
-We can use this to set `left` and `right` as `width` and `up` and `down` as `height`.
|
|
|
+dat.GUI가 쓸 간단한 헬퍼 클래스를 하나 더 만들겠습니다. 이 `DimensionGUIHelper`는
|
|
|
+객체와 속성 이름 2개를 인자로 받아, GUI가 하나의 값을 조정할 때 하나의 값은 양수로,
|
|
|
+다른 값은 음수로 지정합니다. 이렇게 하면 `left`와 `right`값을 `width`로, `up`과
|
|
|
+`down`값을 `height`로 바꾸어 조작할 수 있죠.
|
|
|
|
|
|
```js
|
|
|
class DimensionGUIHelper {
|
|
@@ -344,8 +340,8 @@ class DimensionGUIHelper {
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-We'll also use the `MinMaxGUIHelper` we created in the [camera article](threejs-cameras.html)
|
|
|
-to adjust `near` and `far`.
|
|
|
+또한 [이전 글](threejs-cameras.html)에서 썼던 `MinMaxGUIHelper`를 가져와 `near`와
|
|
|
+`far` 속성을 조작하는 데 사용하겠습니다.
|
|
|
|
|
|
```js
|
|
|
const gui = new GUI();
|
|
@@ -367,98 +363,72 @@ gui.add(light, 'intensity', 0, 2, 0.01);
|
|
|
+}
|
|
|
```
|
|
|
|
|
|
-We tell the GUI to call our `updateCamera` function anytime anything changes.
|
|
|
-Let's write that function to update the light, the helper for the light, the
|
|
|
-light's shadow camera, and the helper showing the light's shadow camera.
|
|
|
+그리고 값이 바뀔 때마다 `updateCamera` 함수를 호출하도록 합니다. 이 함수 안에서는
|
|
|
+조명, 조명 헬퍼, 조명의 그림자용 카메라, 그림자용 카메라의 헬퍼를 업데이트할 거예요.
|
|
|
|
|
|
```js
|
|
|
function updateCamera() {
|
|
|
- // update the light target's matrixWorld because it's needed by the helper
|
|
|
+ // 헬퍼가 가이드라인을 그릴 때 필요한 조명 목표(target)의 matrixWorld를 업데이트 합니다
|
|
|
light.target.updateMatrixWorld();
|
|
|
helper.update();
|
|
|
- // update the light's shadow camera's projection matrix
|
|
|
+ // 그림자용 카메라의 투영 행렬(projection matrix)를 업데이트합니다
|
|
|
light.shadow.camera.updateProjectionMatrix();
|
|
|
- // and now update the camera helper we're using to show the light's shadow camera
|
|
|
+ // 그림자용 카메라를 보기 위해 설치한 카메라의 헬퍼를 업데이트합니다
|
|
|
cameraHelper.update();
|
|
|
}
|
|
|
updateCamera();
|
|
|
```
|
|
|
|
|
|
-And now that we've given the light's shadow camera a GUI we can play with the values.
|
|
|
+이제 그림자용 카메라에 GUI가 생겼으니, 값들을 조정하며 놀아봅시다.
|
|
|
|
|
|
{{{example url="../threejs-shadows-directional-light-with-camera-gui.html" }}}
|
|
|
|
|
|
-Set the `width` and `height` to about 30 and you can see the shadows are correct
|
|
|
-and the areas that need to be in shadow for this scene are entirely covered.
|
|
|
+`width`와 `height` 속성을 30 정도로 조정하면 그림자가 있어야 할만한 공간은
|
|
|
+대부분 그림자용 카메라 안에 속할 겁니다.
|
|
|
|
|
|
-But this brings up the question, why not just set `width` and `height` to some
|
|
|
-giant numbers to just cover everything? Set the `width` and `height` to 100
|
|
|
-and you might see something like this
|
|
|
+하지만 여기서 의문이 하나 생깁니다. 어째서 `width`와 `height`를 완전 큰 값으로
|
|
|
+설정해 모든 요소를 다 포함하도록 하지 않는 걸까요? `width`와 `height`를 100 정도로
|
|
|
+설정해보세요. 아래와 같은 현상이 나타날 겁니다.
|
|
|
|
|
|
<div class="threejs_center"><img src="resources/images/low-res-shadow-map.png" style="width: 369px"></div>
|
|
|
|
|
|
-What's going on with these low-res shadows?!
|
|
|
+왜 그림자의 해상도가 낮아졌을까요?
|
|
|
|
|
|
-This issue is yet another shadow related setting to be aware of.
|
|
|
-Shadow maps are textures the shadows get drawn into.
|
|
|
-Those textures have a size. The shadow camera's area we set above is stretched
|
|
|
-across that size. That means the larger area you set, the more blocky your shadows will
|
|
|
-be.
|
|
|
+이는 그림자 관련 설정을 할 때 항상 주의해야하는 부분입니다. 사실 그림자 맵은 그림자가
|
|
|
+포함된 하나의 텍스처입니다. 이 텍스처는 크기가 정해져 있죠. 위 예제에서 카메라의 공간을
|
|
|
+늘리면, 이 텍스처 또한 늘어납니다. 다시 말해 공간을 크게 설정할수록 그림자가 더 각져
|
|
|
+보일 거라는 얘기죠.
|
|
|
|
|
|
-You can set the resolution of the shadow map's texture by setting `light.shadow.mapSize.width`
|
|
|
-and `light.shadow.mapSize.height`. They default to 512x512.
|
|
|
-The larger you make them the more memory they take and the slower they are to compute so you want
|
|
|
-to set them as small as you can and still make your scene work. The same is true with the
|
|
|
-light's shadow camera area. Smaller means better looking shadows so make the area as small as you
|
|
|
-can and still cover your scene. Be aware that each user's machine has a maximum texture size
|
|
|
-allowed which is available on the renderer as [`renderer.capabilities.maxTextureSize`](WebGLRenderer.capabilities).
|
|
|
+그림자 맵의 해상도는 `light.shadow.mapSize` 속성의 `width`와 `height` 속성으로 설정합니다(기본값은
|
|
|
+512x512). 그림자 맵은 크게 설정할수록 메모리를 많이 차지하고, 연산이 더 복잡해지므로
|
|
|
+가능한 작게 설정하는 것이 좋습니다. 이는 그림자용 카메라의 공간도 마찬가지죠. 작을 수록
|
|
|
+그림자의 퀄리티가 좋아질 테니 가능한 공간을 작게 설정하는 것이 좋습니다. 또한 기기마다
|
|
|
+렌더링할 수 있는 텍스처의 용량이 정해져 있으니 주의해야 합니다. Three.js에서 이 용량은
|
|
|
+[`renderer.capabilities.maxTextureSize`](WebGLRenderer.capabilities)로 확인할 수 있습니다.
|
|
|
|
|
|
-<!--
|
|
|
-Ok but what about `near` and `far` I hear you thinking. Can we set `near` to 0.00001 and far to `100000000`
|
|
|
--->
|
|
|
-
|
|
|
-Switching to the `SpotLight` the light's shadow camera becomes a `PerspectiveCamera`. Unlike the `DirectionalLight`'s shadow camera
|
|
|
-where we could manually set most its settings, `SpotLight`'s shadow camera is controlled by the `SpotLight` itself. The `fov` for the shadow
|
|
|
-camera is directly connected to the `SpotLight`'s `angle` setting.
|
|
|
-The `aspect` is set automatically based on the size of the shadow map.
|
|
|
+`SpotLight`는 그림자용 카메라로 `PerspectiveCamera`(원근 카메라)를 사용합니다. `DirectionalLight`의
|
|
|
+그림자용 카메라는 거의 모든 속성을 직접 변경할 수 있었지만, `SpotLight`의 그림자용 카메라는
|
|
|
+조명 속성의 영향을 받습니다. 카메라의 `fov` 속성은 `SpotLight`의 `angle` 속성과 직접 연결되어
|
|
|
+있죠. `aspect`는 그림자 맵의 크기에 따라 자동으로 정해집니다.
|
|
|
|
|
|
```js
|
|
|
-const light = new THREE.DirectionalLight(color, intensity);
|
|
|
+const light = new THREE.SpotLight(color, intensity);
|
|
|
```
|
|
|
|
|
|
-and we added back in the `penumbra` and `angle` settings
|
|
|
-from our [article about lights](threejs-lights.html).
|
|
|
+추가로 [이전 글](threejs-lights.html)에서 썼던 `penumbra(반음영)`, `angle` 설정을 가져오겠습니다.
|
|
|
|
|
|
{{{example url="../threejs-shadows-spot-light-with-camera-gui.html" }}}
|
|
|
|
|
|
-<!--
|
|
|
-You can notice, just like the last example if we set the angle high
|
|
|
-then the shadow map, the texture is spread over a very large area and
|
|
|
-the resolution of our shadows gets really low.
|
|
|
-
|
|
|
-div class="threejs_center"><img src="resources/images/low-res-shadow-map-spotlight.png" style="width: 344px"></div>
|
|
|
-
|
|
|
-You can increase the size of the shadow map as mentioned above. You can
|
|
|
-also blur the result
|
|
|
-
|
|
|
-{{{example url="../threejs-shadows-spot-light-with-shadow-radius" }}}
|
|
|
--->
|
|
|
+마지막으로 `PointLight`를 살펴보죠. `PointLight`는 모든 방향으로 빛을 발산하기에
|
|
|
+관련 설정은 `near`와 `far` 정도입니다. 그리고 사실 `PointLight`의 그림자는 정육면체의
|
|
|
+각 면에 `SpotLight`를 하나씩, 총 6개의 그림자를 놓은 것과 같습니다. 한 방향에 한
|
|
|
+번씩, 총 6번을 렌더링해야 하니 렌더링 속도가 훨씬 느리겠죠.
|
|
|
|
|
|
-
|
|
|
-And finally there's shadows with a `PointLight`. Since a `PointLight`
|
|
|
-shines in all directions the only relevant settings are `near` and `far`.
|
|
|
-Otherwise the `PointLight` shadow is effectively 6 `SpotLight` shadows
|
|
|
-each one pointing to the face of a cube around the light. This means
|
|
|
-`PointLight` shadows are much slower since the entire scene must be
|
|
|
-drawn 6 times, one for each direction.
|
|
|
-
|
|
|
-Let's put a box around our scene so we can see shadows on the walls
|
|
|
-and ceiling. We'll set the material's `side` property to `THREE.BackSide`
|
|
|
-so we render the inside of the box instead of the outside. Like the floor
|
|
|
-we'll set it only to receive shadows. Also we'll set the position of the
|
|
|
-box so its bottom is slightly below the floor so the floor and the bottom
|
|
|
-of the box don't z-fight.
|
|
|
+이번에는 장면 주위에 상자를 두어 벽과 천장에도 그림자가 생길 수 있도록 해보겠습니다.
|
|
|
+먼저 재질의 `side` 속성을 `THREE.BackSide`로 설정해 외부 상자의 밖이 아닌 안을 렌더링
|
|
|
+하도록 합니다. 바닥과 마찬가지로 그림자를 드리우지 않도록 설정하고, z-파이팅 현상을
|
|
|
+피하기 위해 외부 상자를 바닥보다 살짝 아래에 둡니다.
|
|
|
|
|
|
```js
|
|
|
{
|
|
@@ -475,7 +445,7 @@ of the box don't z-fight.
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-And of course we need to switch the light to a `PointLight`.
|
|
|
+물론 조명도 `PointLight`로 바꿔야죠.
|
|
|
|
|
|
```js
|
|
|
-const light = new THREE.SpotLight(color, intensity);
|
|
@@ -483,21 +453,13 @@ And of course we need to switch the light to a `PointLight`.
|
|
|
|
|
|
....
|
|
|
|
|
|
-// so we can easily see where the point light is
|
|
|
+// 조명이 위치를 확인하기 쉽도록 헬퍼 추가
|
|
|
+const helper = new THREE.PointLightHelper(light);
|
|
|
+scene.add(helper);
|
|
|
```
|
|
|
|
|
|
{{{example url="../threejs-shadows-point-light.html" }}}
|
|
|
|
|
|
-Use the `position` GUI settings to move the light around
|
|
|
-and you'll see the shadows fall on all the walls. You can
|
|
|
-also adjust `near` and `far` settings and see just like
|
|
|
-the other shadows when things are closer than `near` they
|
|
|
-no longer receive a shadow and they are further than `far`
|
|
|
-they are always in shadow.
|
|
|
-
|
|
|
-<!--
|
|
|
-self shadow, shadow acne
|
|
|
--->
|
|
|
-
|
|
|
+GUI의 `position` 속성을 조정해 조명을 움직이면 벽에 그림자가 지는 걸
|
|
|
+확인할 수 있을 겁니다. 다른 그림자와 마찬가지로 `near` 값보다 가까운
|
|
|
+곳은 그림자가 지지 않고, `far` 값보다 먼 곳은 항상 그림자가 지죠.
|