three.js에서 HDR 데이터를 이용한 배경 및 광원으로 사용하기

HDR은 High Dynamic Range의 약자로 밝은 부분과 어두운 부분의 차이를 효과적으로 보정하여 전반적으로 균형있게 출력할 수 있는 기술이라고 합니다. 다르게 설명하면 보다 더 사실적인 명암(밝기와 어두움)를 표현하기 위해 사용되는 기술이라고도 합니다. 아래의 연속된 3개의 이미지 중 가장 오른쪽이 HDR 기술이 적용된 이미지입니다. 왼쪽 이미지는땅 부분이 소실되었고 가운데 이미지는 하늘 부분이 소실되었습니다. 오른쪽 이미지는 HDR 기술을 적용해 만든 것으로 전반적으로 군형있게 표현되고 있습니다.

원래 일반적인 이미지 데이터는 가장 어두운 색의 값을 0, 가장 밝은 색의 값을 1이라는 범위로 정하고 모든 색상을 0~1사이로 맞춥니다. 하지만 HDR이 적용되어 만들어진 이미지 데이터는 0~1 사이의 한정된 범위가 아닌 훨씬 더 넓은 범위를 갖습니다. 즉 사용하는 데이터 크기가 더 큽니다. HDR 데이터의 크기만 봐도 수십에서 수백 MB가 되는 것을 보면 쉽게 이해할 수 있습니다.

three.js에서도 HDR 데이터를 사용할 수 있는데, 그 용도는 크게 두 가지입니다. 첫번째는 3차원 배경으로써의 사용과 두번째는 HDR 데이터 자체를 광원으로써 사용하는 것입니다. HDR 데이터는 인터넷에서 검색을 통해 쉽게 다운로드 받을 수 있습니다. 저 같은 경우 polyhaven이라는 사이트에서 데이터를 받았습니다.

three.js에서 HDR 데이터를 사용하는 주요 코드만을 정리하면 다음과 같습니다. 먼저 필요한 모듈과 HDR 데이터를 로딩하는 함수는 다음과 같습니다.

import { RGBELoader } from "../examples/jsm/loaders/RGBELoader.js"

class App {
    ...

    _setupBackground() {
        new RGBELoader()
            .load("./data/brown_photostudio_03_8k.hdr", (texture) => {
                texture.mapping = THREE.EquirectangularReflectionMapping;
                this._scene.background = texture; // 3차원 배경으로 사용
                this._scene.environment = texture; // 광원으로 사용

                //texture.dispose();
            }
        );
    }

    _setupModel() {
        const geometry = new THREE.TorusKnotGeometry(1, 0.3, 256, 64, 2, 3);
        // HDR을 광원으로 사용하기 위해서는 재질을 MeshStandardMaterial 또는 파생 객체를 사용해야 가능함
        const material = new THREE.MeshStandardMaterial({color: 0xffffff}); 

        const cube = new THREE.Mesh(geometry, material);
        this._scene.add(cube);
    }

    ...
}

위 코드에 대한 결과는 다음과 같습니다.

위의 이미지는 three.js에 어떠한 광원(Light) 객체도 장면에 추가하지 않은 결과입니다. 보시면 TorusKnot 모델이 너무 밝게 표현되어 백색으로 뭉게져 보입니다. 이는 톤맵핑 설정이 바르지 않기 때문입니다. 톤맵핑(Tone Mapping)은 HDR 영역의 색상 표현을 모니터의 색상 표현(SDR)으로 맵핑시켜준다는 개념입니다. 이를 위해 다음 코드가 필요합니다.

renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1;

결과는 다음과 같습니다.

toneMappingExposure 값을 적절하게 조정하면 밝기값이 조정됩니다.

HDR은 3차원 배경으로써 사용될 수도 있지만 광원에 대한 매우 효과적인 해결책입니다. 3차원 배경으로는 사용하지 않고 광원으로써 HDR를 사용하고자 한다면 this._scene.background = texture 코드를 제거하기만 하면 됩니다.

답글 남기기

이메일 주소는 공개되지 않습니다.