이번 포스트에서는 이전 포스트에서 만들었던 내용을 가지고 materials 과 light 그리고 shadow를 추가해보겠습니다.
light관련 소스를 scene에 추가해보면서 시작해보겠습니다.
var spotLight = new THREE.SpotLight(0xFFFFFF);
spotLight.position.set(-40, 40, -15);
spotLight.castShadow = true;
spotLight.shadow.mapSize = new TREE.Vector2(1024, 1024);
spotLight.shadow.camera.far = 130;
spotLight.shadow.camera.near = 40;
THREE.SpotLight는 spotLight의 위치(spotLight.position.set(-40, 60, -10)
)에서부터 우리의 Scene에 빛을 쏘는 것입니다. 그림자를 설정하려면 간단히 castShadow
property를 true로 설정하면 됩니다. 그리고 위 코드에서는 물론 추가적인 properties이 있습니다.
shadow.mapSize, shadow.camera.far, shadow.camera.near
이것들에 대해 너무 상세히 다루지않고, 이 properties는 얼마나 얇게(sharp) 그리고 자세히 저희가 만든 그림자들을 렌더링해서 나타나게합니다. 다음 포스트에서 이건 자세히 알아보겠습니다.
여기까지설정한다고해서 이전 포스트에서의 결과와 차이가 생기지 않습니다. 그 이유는 material의 종류에 따라 light에 따라 다르게 반응하기 떄문입니다. 이전에 우리가 사용했던 Basic material(THREE.MeshBasicMaterial)는 여기 Scence에서는 light와 함께 아무것도 하지않습니다.
basic material은 단지 해당색으로 렌더링하기만합니다. 그래서 그림자를 만들기위해서는 plane, sphere, cube에서 materials를 바꿔야합니다.
var planeGeometry = new THREE.PlaneGeometry(60,20);
var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
...
var cubeGeometry = new THREE.BoxGeometry(4,4,4);
var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000});
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
...
var sphereGeometry = new THREE.SphereGeometry(4,20,20);
var sphereMaterial = new THREE.MeshLambertMaterial({color: 0x7777ff});
var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
위 코드를 보면 materials을 MeshBasicMaterial에서 MeshLambertMaterial로 변경했습니다.
MeshLambertMaterial, MeshPhysicalMaterial and MeshStandardMaterial 는 Three.js에서 제공하는 렌더링될 때 light source를 고려하는 materials입니다.
여기까지하고 결과를 보면 큐브와 구, 평명에는 음영이 생긴걸 확인할 수 있지만 그림자는 생기지 않았습니다. 그림자를 Rendering하는 것은 많은 Computing power를 소비합니다. 그러한 이유때문에 Three.js에서는 그림자를 rendering하는 설정을 default로 disable하게합니다.
하지만 그림자 렌더링을 허용하는 것은 간단히 renderer.shadowMap.Enabled
Property를 True로 바꿔주면됩니다.
renderer.setClearColor(new THREE.Color(0x000000));
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.Enabled = true;
그러고나서도 결과를 보면 아마도 아직 그림자가 생기지않았을 것입니다.
추가로 해줘야할 작업은 빛을 받는 즉, 어느 피사체 Shadow를 cast하는지 혹은 receive하는지를 설정해줘야합니다.(여기서 cast shadow는 그림자를 내뿜는(?) 것을 의미하고 receive는 그림자를 받는 역할(바닥)입니다.
cube.castShadow = true;
sphere.castShadow = true;
plane.receiveShadow = true;