객체들의 그림자가 보이기 위해서 그림자가 표현될 바닥이 필요합니다.
그래서 평면 객체를 사용하여 바닥을 만들겠습니다.
Scence(씬, 장면)에 추가할 바닥으로 PlaneGeometry(플레인 지오메트리, 평면)을 생성합니다.
PlaneGeometry(width : Float, height : Float, widthSegments : Integer, heightSegments : Integer)
- width(가로, 너비, 폭) : 평면의 가로길이입니다. 기본값 1 (입력하지 않으면 기본값으로 설정됩니다.)
- height(세로, 높이) : 평면의 세로길이입니다. 기본값 1 (입력하지 않으면 기본값으로 설정됩니다.)
- widthSegments(수평 세그먼트, 가로 분절 수) : 가로를 분할 면의 수입니다. 기본값 1(입력하지 않으면 기본값으로 설정됩니다.)
- heightSegments(수직 세그먼트, 세로 분절 수) : 세로를 분할 면의 수입니다. 기본값 1(입력하지 않으면 기본값으로 설정됩니다.)
가로, 세로가 10인 PlaneGeometry(플레인 지오메트리, 평면)를 생성하고 색상이 흰색인 Material(머티리얼)을 생성하여 평면 객체를 생성하고 Scence(씬, 장면)에 추가합니다.
MeshLambertMaterial(메쉬 램버트 머티리얼)은 반사 하이라이트가 없는 재질로 렌더링 합니다.
// 평면 지오메트리 생성
const plane1Geometry = new THREE.PlaneGeometry(10, 10);
// 반사 하이라이트가 없는 재질
const plane1Material = new THREE.MeshLambertMaterial({color:0xffffff});
// 평면 지오메트리와 메쉬 램버트 머티리얼을 결합하여 평면 객체 생성
const plane1 = new THREE.Mesh(plane1Geometry, plane1Material);
// 장면에 평면 객체 추가
scene.add(plane1);
웹 브라우저에 평면 객체가 녹색의 육면체와 겹쳐 나오게 됩니다.
그래서 평면 객체의 X축을 -90도 회전시켜 눕힙니다. 그리고 평면 객체의 위치(position)를 아래로 이동시킵니다.
// 평면 객체를 바닥처럼 눕히기 위해 X축을 90도 회전 시킵니다.
plane1.rotation.x = Math.PI * -0.5; // (Math.PI/180) * -90;
// 평면 객체를 중앙에서 아래로 위치 설정
plane1.position.set(0, -1, 0);
그러면 평면 객체가 눕혀 저 바닥처럼 보이게 됩니다.
그림자(Shadow) 기능 활성화 하기
그림자를 만들기 위해서는 렌더러(Renderer)와 조명, 생선 된 객체에 그림자 생성 기능이 활성화되어야 합니다. 그리고 그림자가 표현될 객체에 그림자 받기 기능이 활성화되어야 합니다.
렌더러(Renderer)에서 그림자를 만들기 위해서는 shadowMap 속성이 활성화(shadowMap.enabled = true) 되어야 합니다. 기본적으로 비활성화되어 있습니다. (shadowMap.enabled = false)
// 렌더러에 그림자 맵 활성화
renderer.shadowMap.enabled = true;
렌더러(Renderer)는 기본적으로 PCFShadowMap를 사용하여 그림자를 랜더링 합니다.
렌더러(Renderer)의 그림자 타입
- BasicShadowMap : 필터링이 적용되지 않은 그림자 맵 (빠르지만 품질이 가장 낮습니다.)
- PCFShadowMap : Percentage-Closer Filtering(PCF, 퍼센티지-클로저 필터링)을 사용한 그림자 맵 (그림자 경계에서 보이는 에일리어싱(Aliasing, 일그러짐) 문제를 해결)
- PCFSoftShadowMap : PCF에서 발전된 기능을 사용한 그림자 맵 (반그림자(penumbra) 영역을 좀 더 부드럽게 처리, 그림자가 생성될 객체와 그림자가 표현될 객체의 거리에 따른 그림자 처리)
- VSMShadowMap : Variance Shadow Map(VSM)을 사용한 그림자 맵
필터의 크기가 커질수록에 계산 속도가 느려지기 단점이 있습니다.
부드러운 그림자를 만들기 위해 렌더러(Renderer)의 그림자 타입을 PCFSoftShadowMap으로 설정하겠습니다.
// 렌더러에 그림자 맵 활성화
renderer.shadowMap.enabled = true;
// 렌더러에 그림자 맵 타입 설정
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
그림자가 만들어지기 위해서는 조명과 객체에 그림자 생성 기능인 castShadow(캐스트 쉐도우)가 활성화되어야 합니다. 기본적으로 비활성화되어 있습니다.
// 조명에 그림자 생성 활성화
light1.castShadow = true;
// 육면체에 그림자 생성 활성화
box1.castShadow = true;
// 구에 그림자 생성 활성화
sphere1.castShadow = true;
그리고 그림자가 표현될 객체에는 그림자를 받기 위해서 receiveShadow(리시브 쉐도우)가 활성화되어야 합니다. 기본적으로 비활성화되어 있습니다.
// 평면에 그림자 받기 활성화
plane1.receiveShadow = true;
그림자 기은 설정은 Scence(씬, 장면)에 추가하기 전이나 렌더러(Renderer)가 랜더 하기 전에 추가되어야 합니다.
평면 객체에 그림자가 만들어진 것을 확인할 수 있습니다.
그림자가 다 보이게 평면 객체의 위치(position)를 조정합니다.
// 평면 객체를 중앙에서 아래로 위치 설정
plane1.position.set(1, -1, -3);
또는 평면 객체의 가로, 세로가 10에서 100으로 조정합니다.
// 평면 지오메트리 생성
const plane1Geometry = new THREE.PlaneGeometry(100, 100);
:
// 평면 객체를 중앙에서 아래로 위치 설정
plane1.position.set(0, -1, 0);
저는 평면 객체의 가로, 세로를 조정하였습니다.
DirectionalLight(디렉셔널 라이트)의 위치(position)가 멀어질 수 록 객체들의 그림자가 달라집니다.
DirectionalLight(디렉셔널 라이트)의 위치(position)를 왼쪽으로 더 이동(X축 -1에서 -5로 이동)시키면 그림자가 길어지게 됩니다.
// 방향성 조명
const light1 = new THREE.DirectionalLight(0xffffff, 1);
light1.position.set(-5, 1, 1);
scene.add(light1);