전역 조명
고친 사람 github-actions[bot]
전역 조명은 물체에 부딪혀 튕겨 나온 빛까지 넣어서 화면의 밝기를 정하는 일입니다. 햇빛이 바닥만 비추는 방에서도 천장이 보이는 까닭이 이 튕긴 빛입니다. 해나 전등에서 곧장 온 빛만 따지면 그늘진 곳이 새까맣게 나옵니다. 계산이 많아서 게임 화면에서는 대개 어림으로 대신합니다.
쉽고 빠른 이해
전역 조명은 빛이 이 물체 저 물체에 튕기며 퍼지는 모습까지 그리는 일입니다. 빨간 벽 옆의 흰 바닥이 살짝 붉게 물드는 것이 그 결과입니다.
이게 없으면 빛이 곧장 닿는 곳만 밝습니다. 나머지는 깜깜하게 나옵니다. 그래서 모든 곳에 같은 밝기를 조금씩 얹어 감추는 꼼수를 오래 써 왔습니다.
어떻게 도는가:
- 화면의 한 점에서 선을 그어 처음 닿는 표면을 찾습니다
- 그 표면에서 빛이 들어올 방향을 하나 고릅니다. 그 방향으로 다시 선을 그어 무엇에 닿는지 찾습니다
- 닿은 곳에서 같은 계산을 되풀이합니다. 몇 번 튕긴 뒤 멈춥니다
- 방향을 바꿔 여러 번 해 봅니다. 그 평균이 그 점의 밝기입니다
대가는 계산량입니다. 한 점마다 많은 길을 따라가야 화면이 매끈해집니다. 덜 따라가면 자글자글한 알갱이가 남습니다. 그래서 게임은 미리 계산해 두거나 화면에 보이는 것만으로 어림합니다.
상세
해 질 녘 방에 커튼을 반쯤 치면 햇빛은 바닥 한 귀퉁이에만 떨어집니다. 그래도 의자도 천장도 다 보입니다. 바닥에 떨어진 햇빛이 튕겨 나와 방 안을 한 번 더 비추기 때문입니다.
컴퓨터로 이런 장면을 그림으로 만드는 일이 렌더링입니다. 렌더링은 화면의 점마다 무슨 색으로 얼마나 밝게 칠할지 정합니다.
전역 조명은 그 밝기를 정할 때 튕긴 빛까지 넣는 방식입니다. 이 절은 튕긴 빛이 무엇이고, 왜 계산하기 어렵고, 어떻게 어림하는지를 차례로 봅니다.
직접광과 간접광
빛을 내는 물체를 광원이라고 부릅니다. 해와 전등이 광원입니다. 광원에서 나와 물체에 곧장 닿은 빛을 직접광이라고 합니다.
다른 물체에 한 번 이상 튕긴 뒤에 닿은 빛은 간접광입니다. 앞의 방에서 천장을 비춘 빛이 간접광입니다. 전역 조명은 직접광과 간접광을 함께 계산하는 조명입니다.
flowchart TD
S["해"] -->|직접광| F["바닥"]
F -->|한 번 튕김| C["천장"]
F -->|한 번 튕김| E["눈"]
C -->|두 번 튕김| E
화살표 이름은 빛이 거기 닿기까지 몇 번 튕겼는지를 적은 것입니다. 바닥은 해에게서 곧장 빛을 받으니 직접광으로 밝습니다. 천장은 바닥에서 튕긴 빛을 받으니 간접광으로 밝습니다. 눈에는 바닥에서 튕긴 빛과 천장에서 튕긴 빛이 다 들어옵니다.
지역 조명과의 차이
간접광을 빼고 직접광만 계산하는 방식은 지역 조명이라고 부릅니다. 한 점의 밝기를 그 점과 광원만 보고 정합니다. 주변에 무엇이 있는지는 따지지 않습니다.
전역 조명은 한 점의 밝기를 정하려고 장면 전체를 봅니다. 천장의 밝기가 바닥에 달려 있습니다. 바닥의 밝기도 다시 천장과 벽에 달려 있습니다. 「전역」이라는 이름이 이 성질에서 왔습니다.
| 지역 조명 | 전역 조명 | |
|---|---|---|
| 한 점을 정할 때 보는 것 | 그 점과 광원 | 장면 전체 |
| 빛이 튕기는 횟수 | 0 | 여러 번 |
| 광원이 안 보이는 곳 | 새까맣다 | 튕긴 빛으로 밝아진다 |
| 계산량 | 적다 | 많다 |
지역 조명은 점마다 따로 계산하면 되니 빠릅니다. 대신 표의 셋째 줄처럼 그늘이 새까맣게 나옵니다. 이걸 감추려고 흔히 주변광을 더합니다. 모든 점에 같은 밝기를 조금씩 얹는 상수입니다.
주변광은 간접광을 숫자 하나로 갈음한 것입니다. 그 탓에 방구석과 방 한가운데가 똑같이 밝아집니다. 전역 조명은 이 숫자 하나를 장면에서 계산한 값으로 바꿉니다.
튕긴 빛이 남기는 흔적
간접광은 눈으로 알아볼 수 있는 흔적을 몇 가지 남깁니다. 지역 조명만으로는 이 흔적이 안 나옵니다. 이 흔적이 빠지면 그림이 어딘가 납작해 보입니다.
| 흔적 | 무엇이 일어나나 | 주변에서 보는 예 |
|---|---|---|
| 색 번짐 | 색 있는 표면에 튕긴 빛이 그 색을 묻혀 옆 표면에 닿는다 | 빨간 벽 옆 흰 바닥이 붉어진다 |
| 옅은 그림자 | 여러 방향에서 간접광이 들어와 그림자 속이 밝아진다 | 탁자 밑이 새까맣지 않다 |
| 구석의 어둠 | 좁은 틈은 빛이 들어올 방향이 적어 덜 밝다 | 벽과 바닥이 만나는 모서리 |
| 코스틱 | 유리나 물이 빛을 꺾어 한곳에 모은다 | 물컵 그림자 속의 밝은 무늬 |
셋째 줄 구석의 어둠만 따로 흉내 내는 기법이 앰비언트 오클루전입니다. 간접광 전체를 계산하지 않고 틈이 얼마나 좁은지만 보고 어둡게 칠합니다.
한 점의 밝기를 적는 식
전역 조명의 계산이 왜 많은지는 한 점의 밝기를 적는 식을 보면 드러납니다. 이 식을 렌더링 방정식이라고 부릅니다. 기호 대신 말로 적으면 이렇습니다.
나가는 빛 = 스스로 내는 빛
+ 사방에서 들어오는 빛 중 눈 쪽으로 되튕기는 몫
한 점에서 눈 쪽으로 나가는 빛은 이 둘을 더한 것입니다. 전등처럼 스스로 빛나지 않는 표면이면 첫째 항은 0 입니다. 남는 것은 둘째 항입니다.
둘째 항의 「되튕기는 몫」은 재질마다 다릅니다. 거울은 한 방향으로만 되튕깁니다. 종이는 사방으로 고르게 흩뿌립니다. 이 차이를 들어온 방향과 나가는 방향의 함수로 적은 것이 BRDF(Bidirectional Reflectance Distribution Function, 양방향 반사 분포 함수)입니다.
걸리는 것은 「들어오는 빛」입니다. 들어오는 빛은 다른 표면에서 나간 빛입니다. 그 표면의 나가는 빛을 알려면 같은 식을 또 풀어야 합니다.
답이 식의 양쪽에 다 들어 있는 꼴입니다. 그래서 한 번에 풀리지 않습니다. 빛이 튕기는 길은 몇 번까지 따라갈지 정해 끊습니다. 그 안에서 어림합니다.
튕김 횟수와 알베도
표면은 받은 빛을 다 되튕기지 않습니다. 일부는 표면이 삼킵니다. 표면이 되튕기는 비율이 알베도입니다.
빛은 튕길 때마다 알베도만큼 약해집니다. 알베도가 절반이라고 치고, 세 번 튕기는 동안 남는 빛을 계산하면 이렇습니다.
light = 1.0 # 바닥에 처음 닿은 빛
light *= 0.5 # 0.5 한 번 튕긴 뒤
light *= 0.5 # 0.25 두 번 튕긴 뒤
light *= 0.5 # 0.125 세 번 튕긴 뒤
튕길 때마다 남은 빛은 다른 표면을 비춰 장면의 밝기에 보태집니다. 처음 1.0 은 직접광이니 빼고 간접광의 몫만 더해 봅니다. 세 번까지 더하면 0.875 입니다. 끝없이 따라가서 더한 값은 1.0 입니다.
세 번만으로 간접광의 대부분을 잡은 셈입니다. 그래서 렌더링 프로그램(렌더러)은 대개 튕김 횟수에 상한을 두고 그 뒤는 버립니다. 눈밭처럼 알베도가 큰 장면은 빛이 덜 줄어듭니다. 그런 장면은 더 많이 튕겨야 밝기가 맞습니다.
어림하는 방법
식을 그대로 풀 수 없으니 어림하는 방법이 여럿 나왔습니다. 방법마다 무엇을 포기하는지가 다릅니다. 이 소절은 대표 방법의 이름과 하는 일만 짚습니다.
먼저 알아 둘 낱말이 광선입니다. 광선은 한 점에서 한 방향으로 곧게 그은 선입니다. 빛이 가는 길을 이 선으로 흉내 냅니다.
레이 트레이싱(광선추적)은 광선이 처음 닿는 물체를 찾아 그림을 그리는 방식입니다. 기본형은 거울 반사와 굴절, 그림자를 따라갑니다. 종이처럼 사방으로 흩뿌리는 표면의 빛은 따라가지 않습니다.
패스 트레이싱은 흩어지는 빛까지 따라가도록 레이 트레이싱을 넓힌 방식입니다. 사방에서 들어오는 빛을 다 따라갈 수는 없습니다. 들어올 수 있는 방향이 끝없이 많기 때문입니다.
패스 트레이싱은 대신 몬테카를로 방법을 씁니다. 무작위로 여러 번 뽑아 본 값의 평균으로 답을 어림하는 방법입니다. 방향을 몇 개만 골라 따라갑니다. 그 값들의 평균을 냅니다.
flowchart TD
E["눈"] --> P["화면의 한 점"]
P --> A["처음 닿은 표면에서 방향을 무작위로 고른다"]
A --> B["다음 표면에서 또 고른다"]
B --> L["광원에 닿으면 그 빛을 길 따라 되돌려 더한다"]
길은 눈에서 출발해 광원 쪽으로 거꾸로 갑니다. 광원에서 나간 빛은 대부분 눈에 안 들어옵니다. 눈에서 출발하면 화면에 보일 빛만 따라가게 됩니다.
방법마다 하는 일과 포기하는 것을 견주면 이렇습니다.
| 방법 | 하는 일 | 포기하는 것 |
|---|---|---|
| 패스 트레이싱 | 눈에서 쏜 광선을 무작위 방향으로 튕기며 따라간다 | 시간. 광선이 적으면 화면이 자글자글하다 |
| 라디오시티 | 표면을 작은 조각으로 나누고 조각끼리 주고받는 빛을 한꺼번에 푼다 | 반짝이는 반사. 흩뿌리는 표면만 다룬다 |
| 포톤 매핑 | 광원에서 빛 알갱이를 뿌려 닿은 곳에 쌓아 둔다. 그릴 때는 그 둘레에 쌓인 알갱이를 세어 밝기를 정한다 | 메모리. 알갱이를 저장해 둬야 한다 |
| 라이트맵 베이킹 | 미리 계산한 밝기를 그림 파일에 구워 두고 그릴 때 읽기만 한다 | 움직임. 광원이나 물체가 움직이면 다시 구워야 한다 |
| 화면 공간 전역 조명 | 이미 그린 화면 속 표면끼리 빛을 주고받게 한다 | 화면 밖. 안 보이는 물체에서 튕긴 빛은 빠진다 |
표의 넷째 줄은 두 낱말을 묶었습니다. 라이트맵은 표면마다 밝기를 담아 둔 그림 파일입니다. 베이킹은 그 밝기를 미리 계산해 라이트맵에 담는 일입니다.
화면 공간 전역 조명은 방금 그린 화면 한 장만 재료로 씁니다. 화면에 보이는 표면끼리만 빛을 주고받는 것으로 칩니다. 그 탓에 화면 밖 물체가 튕긴 빛은 빠집니다.
패스 트레이싱이 남기는 자글자글한 알갱이를 노이즈라고 부릅니다. 광선을 적게 쏘고 남은 노이즈를 따로 지우는 단계가 디노이징입니다.
실시간과 오프라인
영화는 화면 한 장, 곧 프레임 하나를 그리는 데 몇 분이 걸려도 됩니다. 이렇게 시간을 넉넉히 쓰는 렌더링이 오프라인 렌더링입니다. 광선을 넉넉히 쏘는 패스 트레이싱을 주로 씁니다.
게임은 1초에 프레임 수십 장을 그려야 합니다. 한 장에 쓸 수 있는 시간이 아주 짧습니다. 이 시간 안에 그리는 렌더링을 실시간 렌더링이라고 합니다. 이 시간 안에 패스 트레이싱을 넉넉히 돌리기는 어렵습니다.
게임은 방법을 섞어 씁니다. 움직이지 않는 건물과 지형의 간접광은 미리 구워 둡니다. 움직이는 캐릭터는 라이트 프로브에서 주변 밝기를 읽어 씁니다.
라이트 프로브는 장면 곳곳에 심어 둔 표본입니다. 그 지점에 사방에서 들어오는 빛을 미리 재어 담아 둡니다.
근래 그래픽 카드는 광선이 무엇에 닿는지 찾는 계산을 하드웨어로 돕습니다. 광선을 쏘고, 닿은 곳을 찾고, 닿은 곳의 색을 정하는 단계를 차례로 묶은 처리 순서가 레이 트레이싱 파이프라인입니다. 이 파이프라인으로 광선을 조금만 쏘고 디노이징으로 메우는 방식도 씁니다.
쓸 때와 안 쓸 때
백엔드 개발자가 전역 조명 식을 직접 풀 일은 드뭅니다. 만나는 곳은 그 계산을 돌리는 바깥쪽입니다.
오프라인 렌더링은 프레임 한 장 한 장을 따로 계산할 수 있습니다. 그래서 여러 대의 서버에 프레임을 나눠 맡깁니다. 이런 서버 묶음을 렌더 팜이라고 부릅니다. 작업을 나눠 주고 결과를 모으는 일이 배치 처리와 같은 모양입니다.
라이트맵 베이킹은 비싼 계산을 미리 해 두고 읽기만 하는 일입니다. 캐싱과 같은 모양입니다. 약점도 같습니다. 원본인 광원이나 물체가 바뀌면 다시 구워야 합니다.
장면이 거의 안 움직이면 미리 굽는 쪽이 싸게 먹힙니다. 해가 지거나 벽이 무너지는 장면이면 구운 결과가 금세 낡습니다. 그때는 그릴 때마다 계산하는 방법으로 가야 합니다. 계산량을 그만큼 치릅니다.
관련 항목
전역 조명 계산에 드는 빛의 성분과 식
직접 조명 · 간접 조명 · 주변광 · 광원 · 알베도 · BRDF · 렌더링 방정식
전역 조명을 계산하는 알고리즘
레이 트레이싱 · 패스 트레이싱 · 양방향 패스 트레이싱 · 라디오시티 · 포톤 매핑 · 몬테카를로 방법 · 중요도 샘플링 · 디노이징
전역 조명을 미리 굽거나 어림하는 기법
라이트맵 · 베이킹 · 라이트 프로브 · 화면 공간 전역 조명 · 앰비언트 오클루전 · 화면 공간 앰비언트 오클루전 · 화면 공간 반사
전역 조명이 화면에 남기는 빛의 흔적
색 번짐 · 코스틱 · 그림자 · 반사 · 굴절 · 표면하 산란
전역 조명과 맞세워지는 조명 계산
지역 조명 · 퐁 반사 모델 · 셰이딩 · 물리 기반 셰이딩
전역 조명이 쓰이는 렌더링 방식
렌더링 · 실시간 렌더링 · 오프라인 렌더링 · 래스터화 · 레이 트레이싱 파이프라인 · 렌더 팜 · 그래픽스
다른 이름: global illumination · GI · 글로벌 일루미네이션