Three.js 는 조명이 없으면 검은 화면만 보이게 됩니다.
이번 포스팅에서는 조명의 종류와 특징, 설정 방법에 대해 정리하고자 합니다.
조명의 종류는 다음과 같습니다.
그리고 개발환경에서 조명의 광원 위치를 파악하기 쉽게 도와주는 Helper class 가 있습니다.
자세한 사항은 각 조명과 함께 정리하겠습니다.
이번 포스팅에서 사용할 예시 코드는 다음과 같습니다.
import {
WebGLRenderer,
Scene,
PerspectiveCamera,
SphereGeometry,
MeshStandardMaterial,
Mesh,
Color,
DirectionalLight,
DirectionalLightHelper,
} from 'three';
import './style.css';
import {
OrbitControls,
} from 'three/examples/jsm/controls/OrbitControls';
/** @type { WebGLRenderer } */
let renderer;
/** @type { Scene } */
let scene;
/** @type { PerspectiveCamera } */
let camera;
/** @type { OrbitControls } */
let controls;
function initCanvas() {
const $canvas = document.createElement('canvas');
$canvas.width = window.innerWidth;
$canvas.height = window.innerHeight;
const $app = document.querySelector('#app');
$app.appendChild($canvas);
return $canvas;
}
function initRenderer($canvas) {
renderer = new WebGLRenderer({
canvas: $canvas,
antialias: true,
});
}
function initScene() {
scene = new Scene();
}
function initCamera() {
camera = new PerspectiveCamera();
camera.fov = 35;
camera.aspect = window.innerWidth / window.innerHeight;
camera.position.set(0, 0, 10);
camera.updateProjectionMatrix();
}
function initControls($canvas) {
controls = new OrbitControls(camera, $canvas);
controls.enableDamping = true;
}
function createSphere() {
const geometry = new SphereGeometry();
const material = new MeshStandardMaterial();
const sphere = new Mesh(geometry, material);
return sphere;
}
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
controls.update();
}
function init() {
const $canvas = initCanvas();
initRenderer($canvas);
initScene();
initCamera();
initControls($canvas);
const sphere = createSphere();
scene.add(sphere);
// 여기에서 `조명 설정` 함수를 호출하며 실습할 예정입니다.
render();
}
init();
DirectionalLight 는 광원 에서 특정 지점(lookAt(좌표)) 로 비추는 단방향 조명 입니다.
물체에 비추는 빛의 양은 광원과의 거리와 무관한 빛의 세기(intensity) 설정값이 적용됩니다.
import {
DirectionalLight,
} from 'three';
function init() {
initRenderer(initCanvas());
initCamera();
initScene();
const sphere = createSphere();
scene.add(sphere);
initDirectionalLight();
render();
}
function initDirectionalLight() {
const light = new DirectionalLight();
light.position.set(1, 1, 1);
scene.add(light);
}
init();
DirectionalLight 생성자에 인자로 Color 객체 를 넘겨주어 빛의 색상을 변경할 수 있습니다.
Color 는 Three.js 에서 제공하는 class 이며, Three.js 의 색상관련 설정은 Color 인스턴스 를 받습니다.
import {
Color,
} from 'three';
function init() {
initRenderer(initCanvas());
initCamera();
initScene();
const sphere = createSphere();
scene.add(sphere);
initDirectionalLight();
render();
}
function initDirectionalLight() {
const color = new Color('#f0f400');
const light = new DirectionalLight(color);
light.position.set(1, 1, 1);
scene.add(light);
}
init();
DirectionalLight 의 광원을 표기해주는 기능을 사용해 보겠습니다.
DirectionalLightHelper 인스턴스를 생성한 후, scene.add()
를 사용하여 등록해 줍니다.
import {
DirectionalLight,
DirectionalLightHelper,
} from 'three';
function init() {
initRenderer(initCanvas());
initCamera();
initScene();
const sphere = createSphere();
scene.add(sphere);
initDirectionalLight();
render();
}
function initDirectionalLight() {
const color = new Color('#f0f400');
const light = new DirectionalLight(color);
light.position.set(1, 1, 1);
scene.add(light);
const helper = new DirectionalLightHelper(light);
scene.add(helper);
}
init();
조명은 빛의 세기(intensity) 가 있습니다.
Three.js 의 모든 조명에도 빛의 세기(intensity) 를 설정할 수 있습니다.
빛의 세기 값은 0 ~ 1 값으로 설정합니다.
아래 코드는 DirectionalLight 에 빛의 세기(intensity) 를 0.75 로 설정하고 있습니다.
function init() {
initRenderer(initCanvas());
initCamera();
initScene();
const sphere = createSphere();
scene.add(sphere);
initDirectionalLight();
render();
}
function initDirectionalLight() {
const color = new Color('#f0f400');
const light = new DirectionalLight(
color,
0.75
);
light.position.set(1, 1, 1);
scene.add(light);
const helper = new DirectionalLightHelper(light);
scene.add(helper);
}
init();
전등처럼 한 점에서 빛을 방사하는 조명 입니다.
사용방법은 다음과 같습니다.
import {
PointLight,
PointLightHelper,
} from 'three';
function init() {
initRenderer(initCanvas());
initCamera();
initScene();
const sphere = createSphere();
scene.add(sphere);
initPointLight();
render();
}
function initPointLight() {
const color = new Color('#f0f400');
const light = new PointLight(
color,
0.75 // 빛의 세기(intensity)
);
light.position.set(1, 1, 1);
scene.add(light);
const helper = new PointLightHelper(light);
scene.add(helper);
}
init();
Ambient 는 주변
이라는 뜻을 가지고 있습니다.
AmbientLight 는 특정한 광원이 없고, 모든 영역에 동일하게 비추는 조명입니다.
즉 (x, y, z)
에 관계없이 동일한 빛을 비춥니다.
AmbientLight 가 적용된 결과를 확인하기 위해, PointLight 와 함께 사용해 보겠습니다.
import {
PointLight,
PointLightHelper,
AmbientLight,
} from 'three';
function init() {
initRenderer(initCanvas());
initCamera();
initScene();
const sphere = createSphere();
scene.add(sphere);
initPointLight();
initAmbientLight();
render();
}
function initPointLight() {
const color = new Color('#f0f400');
const light = new PointLight(
color,
0.75 // 빛의 세기(intensity)
);
light.position.set(1, 1, 1);
scene.add(light);
const helper = new PointLightHelper(light);
scene.add(helper);
}
function initAmbientLight() {
const color = new Color('#fff');
const light = new AmbientLight(
color,
0.25, // 빛의 세기(intensity)
);
scene.add(light);
}
init();
그리고 AmbientLight 는 모든 영역에 비추는 조명이므로, Helper class 가 없다는 특징 이 있습니다.
HemisphereLight 는 위쪽(skyColor) 와 아래쪽(groundColor) 를 인자로 받고, 그라데이션으로 비추는 조명입니다.
일반적으로 기본 조명으로 사용하는데, 이는 Three.js 특성 때문입니다.
아래 코드는 HemisphereLight 와 DirectionalLight 를 조합한 예시 입니다.
import {
DirectionalLight,
DirectionalLightHelper,
HemisphereLight,
HemisphereLightHelper,
} from 'three';
function init() {
initRenderer(initCanvas());
initCamera();
initScene();
const sphere = createSphere();
scene.add(sphere);
initDirectionalLight();
initHemisphereLight();
render();
}
function initDirectionalLight() {
const color = new Color('#fff');
const light = new DirectionalLight(
color,
0.75 // 빛의 세기(intensity)
);
light.position.set(1, 1, 1);
scene.add(light);
const helper = new PointLightHelper(light);
scene.add(helper);
}
function initHemisphereLight() {
const skyColor = new Color('#fff');
const groundColor = new Color('#000');
const light = new HemisphereLight(
skyColor,
groundColor,
0.25, // 빛의 세기(intensity)
);
scene.add(light);
const helper = new HemisphereLightHelper(light);
scene.add(helper);
}
init();
일반적으로 DirectionalLight 와 HemisphereLight 를 조합하여 기본 조명을 구성합니다.
각 설정은 다음과 같습니다.
function initDirectionalLight() {
const color = new Color('#fff');
const light = new DirectionalLight(
color,
0.75 // HemispherLight 보다 0.5 강하게 설정합니다.
);
scene.add(light);
}
function initHemisphereLight() {
const skyColor = new Color('#fff');
const groundColor = new Color('#000');
const light = new HemisphereLight(
skyColor,
groundColor,
0.25 // DirectionalLight 보다 0.5 약하게 설정합니다.
);
scene.add(light);
}
HemisphereLight 를 사용하므로써 그림자 부분이 검은색으로 보이지 않도록 해주며, 좀 더 자연스러운 조명을 연출할 수 있습니다.
그리고 PointLight 는 특정 물체를 강조하거나 효과를 주기위해 주로 사용합니다.
Three.js 는 개발 능력뿐만 아니라 사물을 표현하는 예술 능력도 필요하겠다는 느낌이 듭니다. 😱