조명 종류와 설정

Three.js 는 조명이 없으면 검은 화면만 보이게 됩니다.

이번 포스팅에서는 조명의 종류와 특징, 설정 방법에 대해 정리하고자 합니다.


조명 종류

조명의 종류는 다음과 같습니다.

  • DirectionalLight
  • PointLight
  • AmbientLight
  • HemisphereLight

그리고 개발환경에서 조명의 광원 위치를 파악하기 쉽게 도와주는 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

DirectionalLight 는 광원 에서 특정 지점(lookAt(좌표)) 로 비추는 단방향 조명 입니다.

물체에 비추는 빛의 양은 광원과의 거리와 무관한 빛의 세기(intensity) 설정값이 적용됩니다.


DirectionalLight import 하기
import {
    DirectionalLight,
} from 'three';
DirectionalLight
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 인스턴스 를 받습니다.

Color import 하기
import {
    Color,
} from 'three';
DirectionalLight 색상 설정하기
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

DirectionalLight 의 광원을 표기해주는 기능을 사용해 보겠습니다.

DirectionalLightHelper 인스턴스를 생성한 후, scene.add() 를 사용하여 등록해 줍니다.

DirectionalLightHelper import 하기
import {
    DirectionalLight,
    DirectionalLightHelper,
} from 'three';
DirectionalLight 색상 설정하기
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();
DirectionalLightHelper

빛의 세기(intensity) 설정하기

조명은 빛의 세기(intensity) 가 있습니다.

Three.js 의 모든 조명에도 빛의 세기(intensity) 를 설정할 수 있습니다.

빛의 세기 값은 0 ~ 1 값으로 설정합니다.

아래 코드는 DirectionalLight 에 빛의 세기(intensity) 를 0.75 로 설정하고 있습니다.

DirectionalLight 색상 설정하기
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();

PointLight

전등처럼 한 점에서 빛을 방사하는 조명 입니다.

사용방법은 다음과 같습니다.

PointLight import 하기
import {
    PointLight,
    PointLightHelper,
} from 'three';
PointLight 색상 설정하기
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();
PointLight

AmbientLight

Ambient 는 주변 이라는 뜻을 가지고 있습니다.

AmbientLight 는 특정한 광원이 없고, 모든 영역에 동일하게 비추는 조명입니다.

(x, y, z) 에 관계없이 동일한 빛을 비춥니다.


AmbientLight 가 적용된 결과를 확인하기 위해, PointLight 와 함께 사용해 보겠습니다.

PointLight import 하기
import {
    PointLight,
    PointLightHelper,
 
    AmbientLight,
} from 'three';
PointLight 색상 설정하기
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

그리고 AmbientLight 는 모든 영역에 비추는 조명이므로, Helper class 가 없다는 특징 이 있습니다.


HemisphereLight

HemisphereLight 는 위쪽(skyColor) 와 아래쪽(groundColor) 를 인자로 받고, 그라데이션으로 비추는 조명입니다.

일반적으로 기본 조명으로 사용하는데, 이는 Three.js 특성 때문입니다.

  • 조명이 없으면, 물체(Mesh) 는 보이지 않는 검은 화면만 렌더링 됩니다.
  • 다른 조명에 의해 생기는 그림자를 좀 더 자연스럽고 부드럽게 만들어줍니다.

아래 코드는 HemisphereLight 와 DirectionalLight 를 조합한 예시 입니다.

PointLight import 하기
import {
    DirectionalLight,
    DirectionalLightHelper,
 
    HemisphereLight,
    HemisphereLightHelper,
} from 'three';
PointLight 색상 설정하기
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();
Hemisphere

마치며

일반적으로 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 는 개발 능력뿐만 아니라 사물을 표현하는 예술 능력도 필요하겠다는 느낌이 듭니다. 😱