햇빛이 빨간 벽에 닿으면 그 옆의 흰 바닥에도 붉은 기운이 번진다. 바닥이 빨간색으로 바뀐 것이 아니라, 벽에서 반사된 빛이 바닥을 비추는 것이다.
이런 현상을 계산하려면 지금 그리는 표면만 알아서는 부족하다. 다른 물체가 어떤 빛을 받고, 그중 얼마를 반사하며, 두 표면 사이에 무엇이 있는지도 알아야 한다. 전역 조명(Global Illumination, GI)의 비용은 이 연결 관계를 계산하는 데서 나온다.
그런데 비슷한 바닥 지점들이 비슷한 간접광(indirect lighting)을 받는다면, 각 픽셀에서 같은 계산을 반복할 필요가 있을까? 이 질문에서 빛 캐싱(light caching)이 시작된다.
이 시리즈는 특정 GI 기법의 성능 순위를 매기기보다, 계산한 빛을 어디에 저장하고 어떻게 재사용하는가를 살펴본다. 주로 불투명 표면의 확산 반사(diffuse reflection)에 의한 간접광을 다루고, 참여 매질(participating media)과 투과(transmission)는 필요한 경우에만 언급한다.
Phong 모델에서는 왜 라이팅을 간단히 계산할 수 있을까?
그래픽스 입문에서 자주 구현하는 Phong 반사 모델(Phong reflection model)은 조명을 세 항으로 나눈다. LearnOpenGL의 Basic Lighting에서도 이 구성으로 시작한다.
- 주변광(ambient lighting): 표면에 기본적인 밝기를 더하는 항
- 확산 반사(diffuse reflection): 광원 방향과 표면 법선에 따라 달라지는 항
- 정반사(specular reflection): 시선과 반사 방향에 따라 하이라이트를 만드는 항

왼쪽부터 ambient, diffuse, specular와 이를 합친 Phong 결과. Ambient 항은 광원 방향과 관계없이 기본 밝기를 더한다.
입문 구현에서는 주변광을 ambientStrength * lightColor * objectColor처럼 계산한다. 다른 표면에서 반사되어 들어오는 복잡한 간접광을, 상수 주변광(ambient light) 색과 세기 하나로 대신하는 것이다. 매 픽셀에서 방 안의 모든 빛 경로를 조사할 필요가 없다.
이 근사는 어두운 면이 완전히 검게 보이는 것을 쉽게 막아준다. 하지만 빨간 벽 근처의 흰 바닥에만 붉은빛이 번지거나, 문을 열었을 때 방 안의 간접광이 달라지는 현상을 공간에 따라 계산하지는 못한다. 그런 변화는 상수 하나에 담겨 있지 않기 때문이다.
확산 항도 이상적인 램버트 반사(Lambertian reflection)를 가정하면 단순해진다. 이 표면의 확산 반사율(diffuse reflectance) $\rho$는 받은 빛 중 반사하는 비율이며, 이 모델의 BRDF는 $f_r=\rho/\pi$로 입사·출사 방향에 무관하다. 같은 입사 조명 아래에서 표면의 출사 방사휘도는 관찰 방향에 따라 변하지 않는다.
여기에 램버트 코사인 법칙(Lambert’s cosine law)에 따른 입사각 효과를 적용한다. 같은 광선 다발이 표면에 비스듬히 닿으면 더 넓은 면적에 퍼지므로, 단위 면적이 받는 빛은 $\cos\theta$에 비례한다. $n$을 단위 표면 법선, $l$을 표면에서 광원을 향하는 단위 벡터라고 하면 $\cos\theta=n\cdot l$이다. 뒷면에서 오는 직접광을 제외하면 $\max(0,n\cdot l)$을 쓰며, 입문 코드의 max(dot(normal, lightDir), 0.0)이 이 부분에 해당한다. 이 코사인 항은 Lambert BRDF 자체의 방향 의존성이 아니라, 표면이 받는 빛의 투영 면적에서 나온다.
같은 광선 다발도 비스듬히 닿으면 더 넓은 면적 A₂에 퍼진다. 단위 면적이 받는 빛이 줄어드는 것이 코사인 항의 기하학적 의미다.
따라서 직접 조명은 지정한 광원마다 법선과 광원 방향의 내적을 계산하고 반사율을 곱하는 형태로 구현할 수 있다. Phong의 정반사 항은 반사 방향과 시선 방향의 내적을 거듭제곱하는 경험적 모델(empirical model)로 더한다. 여기서 Lambert 가정은 확산 항에 적용된다.
간단한 Phong 라이팅의 핵심은, 간접광을 ambient 상수로 근사하고 직접광의 표면 반응을 단순한 모델로 평가한다는 데 있다. Lambert 표면이라도 실제 주변 물체가 만드는 간접광까지 구하려면, 그 물체들에서 어떤 빛이 들어오는지 계산해야 한다. 이제 ambient 상수로 생략했던 부분을 따라가 보자.
직접광(direct lighting)에서 간접광(indirect lighting)으로
빛의 경로를 간단히 나누면 다음과 같다. 화살표는 빛이 이동하는 방향이다.
직접광: 광원 ------------------> 바닥 --> 카메라
간접광: 광원 --> 빨간 벽 -------> 바닥 --> 카메라
반사
직접광을 계산할 때도 광원과 표면 사이의 가시성(visibility)과 그림자(shadow)를 확인해야 한다. 간접광은 여기에 다른 표면에서의 반사가 더해진다. 흰 바닥으로 들어오는 빛을 구하려면 빨간 벽에서 나오는 빛을 알아야 하고, 그 벽의 빛도 또 다른 표면에 의존할 수 있다.

Cornell box의 흰 바닥과 상자에 벽의 색이 번진다. 이런 색 번짐(color bleeding)은 다른 표면에서 반사된 간접광을 계산해야 나타난다.
GI는 본래 직접광과 간접광을 포함하는 장면 전체의 빛 전달을 가리킨다. 엔진에서는 별도 간접광 시스템을 편의상 GI라고 부르는 경우가 많다. 이 글에서도 맥락이 분명한 곳에서는 그렇게 사용한다. 빛 전달(light transport)의 재귀적 관계는 PBRT의 Light Transport Equation에 정리되어 있다.
렌더링 방정식(Rendering Equation)이 비싼 이유
불투명한 반사 표면에서 나가는 빛을 단순화해 쓰면 다음과 같다.
- $x$: 빛을 계산할 표면 위치
- $n$: 그 표면의 단위 법선(unit normal)
- $\omega_i$, $\omega_o$: 표면에서 바깥쪽으로 정의한 입사 방향(incident direction)과 출사 방향(outgoing direction)
- $L_i$, $L_o$: 들어오는 빛과 나가는 빛의 방사휘도(radiance)
- $L_e$: 표면 자체의 발광(emission)
- $f_r$: 입사광을 출사 방향으로 얼마나 반사하는지 나타내는 양방향 반사 분포 함수(Bidirectional Reflectance Distribution Function, BRDF)
- $\Omega^+(n)$: 법선이 향하는 쪽의 반구(hemisphere)
수식의 요지는 모든 입사 방향에서 오는 빛을 재질의 반사 특성과 각도에 따라 합산한다는 것이다. 코사인 항은 빛이 비스듬히 들어올 때 같은 에너지가 더 넓은 표면에 퍼지는 효과를 나타낸다. 반사 적분의 정의는 PBRT의 Surface Reflection을 참고할 수 있다.
어려운 부분은 $L_i$다. 이 값은 단순히 광원 목록에서 읽는 숫자가 아니다. 어떤 방향으로 광선을 보냈을 때 만나는 표면의 출사광에 의존한다.
바닥 x의 입사광을 구한다
|
+--> 벽 y에서 나오는 빛이 필요하다
|
+--> 천장 z에서 나오는 빛이 필요하다
|
+--> ...
광선 추적(ray tracing)은 표면을 찾는 일을 맡고, 몬테카를로 샘플링(Monte Carlo sampling)은 적분을 일부 표본으로 추정하게 해준다. 하지만 적은 표본은 노이즈(noise)를 만들고, 표본을 늘리면 교차 검사(intersection test)와 셰이딩(shading) 비용이 커진다.
1920×1080 화면에는 2,073,600개의 픽셀이 있다. 설명을 위해 모든 픽셀에서 간접광 광선을 16개씩 보낸다고 가정하면, 시작 광선만 약 3,318만 개다. 여기에는 추가 bounce나 광원을 향한 shadow ray가 포함되지 않는다. 실제 엔진의 비용 측정이 아니라, 같은 종류의 적분을 수많은 위치에서 반복하는 규모를 보여주는 예다.
확산 반사(diffuse reflection)에서는 무엇을 캐싱할 수 있을까?
방사휘도(radiance)는 위치와 방향에 따른 빛을 나타낸다. 복사조도(irradiance)는 특정 방향을 향한 표면이 받는 빛을 입사 방향 전체에 걸쳐 합산한 양이다.
둘 다 RGB로 저장할 수 있지만 의미는 다르다. 방향을 따라 들어오는 radiance를 합산해 irradiance를 얻으며, irradiance에는 어느 방향에서 왔는지에 대한 세부 정보가 줄어든다.
이상적인 Lambert 확산 반사(Lambertian diffuse reflection) 재질에서는 $f_r=\rho/\pi$이므로, 간접광에 대한 출사 radiance는 다음처럼 쓸 수 있다.
$\rho$는 표면의 확산 반사율(diffuse reflectance), 즉 알베도(albedo)다. Lambertian BRDF와 $1/\pi$ 정규화는 PBRT의 Diffuse Reflection에 설명되어 있다.
이렇게 분리하면 바닥의 작은 무늬는 현재 픽셀의 알베도 텍스처(albedo texture)로 표현하고, 비교적 완만하게 변하는 간접 irradiance는 더 적은 수의 샘플에서 가져올 수 있다. 빛을 저장할 때 albedo를 이미 곱했는지 확인하는 것도 중요하다. 두 번 곱하면 재질이 잘못 어두워진다.
표면에 고정된 irradiance 값 하나는 그 위치와 법선을 대표한다. 임의의 법선에 대응하려면 방향 정보를 더 저장해야 한다. 뒤에서 light probe를 설명할 때 이 차이가 다시 등장한다.
공간적으로 공유하고(spatial reuse), 시간적으로 누적한다(temporal accumulation)
Light caching에는 두 가지 재사용이 있다.
Spatial reuse
표면: ---- x ---- x ---- x ---- x ----
\ | /
같은 조명 샘플을 참조
Temporal reuse
frame 0: 표본 계산 --> 캐시
frame 1: 새 표본 --> 기존 캐시와 결합
frame 2: 새 표본 --> 다시 결합
공간 재사용(spatial reuse)은 주변 지점의 조명이 충분히 비슷하다는 가정이다. 시간 재사용(temporal reuse)은 이전 프레임의 결과가 현재에도 유효하다는 가정이다. 따라서 저장 공간만 만들면 끝나는 최적화가 아니다. 두 가정을 언제 허용하고 언제 거부할지도 정해야 한다.
예를 들어 큰 벽 한가운데에서는 주변 샘플의 평균이 잘 맞을 수 있다. 하지만 밝은 창문 바로 옆이나 얇은 칸막이 양쪽에서는 작은 이동으로 가시성이 달라진다. Diffuse가 입사 방향을 부드럽게 합산한다고 해서, 공간의 모든 조명이 부드럽게 변하는 것은 아니다.
시간도 마찬가지다. 카메라만 움직였다면 정적 벽의 조명은 여전히 유효할 수 있다. 문이 열렸다면 벽이 움직이지 않았어도 그 벽이 받는 빛은 달라진다.
캐시는 계산을 줄이면서 새로운 문제를 만든다
표면점 $x$의 정확한 조명 대신 주변 캐시를 보간(interpolation)한 $\widetilde E(x,n)$을 사용한다고 생각해보자.
표본 수를 줄였으므로 계산 비용은 낮아질 수 있다. 대신 캐시 해상도, 보간, 오래된 데이터로 인한 오차가 생긴다. 벽 너머 빛이 섞이는 빛 누출(light leaking), 변화한 조명을 늦게 따라가는 반응 지연(lag), 새 영역에 데이터가 없는 초기 상태(cold start)가 대표적이다.
Ray tracing과 caching은 함께 사용할 수 있다. Ray tracing으로 캐시를 갱신하고, 많은 픽셀은 그 결과를 읽는다. 또 ray tracing으로 적은 픽셀 표본을 만든 뒤 화면에서 노이즈 제거(denoising)를 할 수도 있다. 모든 실시간 GI가 같은 캐시를 필요로 하는 것은 아니지만, 비싼 계산을 어디서 공유할지는 여러 시스템에 공통된 질문이다.
다음 글 「빛을 어디에 저장할 것인가: Texel, Voxel, Probe」에서는 이 조명 샘플을 표면의 UV에 둘지, 3차원 셀에 둘지, 공간의 대표 지점에 둘지 비교한다.
References
- Joey de Vries, Basic Lighting, LearnOpenGL. Phong 모델의 ambient·diffuse·specular 구성과 입문 구현.
- Matt Pharr, Wenzel Jakob, Greg Humphreys, The Light Transport Equation, Physically Based Rendering, 4th ed. 빛 전달과 GI의 재귀적 관계.
- 같은 책의 Surface Reflection, Diffuse Reflection. 반사 적분과 Lambertian 모델.
- Phong 이미지: © Joey de Vries, LearnOpenGL, @JoeyDeVriez, CC BY 4.0.
- 코사인 법칙 도식: © Matt Pharr, Wenzel Jakob, Greg Humphreys, PBRT 4판, Radiometry, Figure 4.2, CC BY-NC-ND 4.0.