서비스
교육 철학

10.1 렌더링의 원리·BRDF·색과 빛·렌더링 방정식 (Rendering)

10장: 3D 그래픽스의 수학적 주제

예쁜 그래픽이 나쁠 건 없다고 생각합니다. — 미야모토 시게루(1952~)
이 장에서는 컴퓨터로 3차원 그래픽스를 만들 때 나타나는 여러 수학적 문제를 다룹니다. 물론 컴퓨터 그래픽스라는 방대한 주제를 단 한 장에서 자세히 설명할 수는 없습니다. 이 분야를 개괄하는 데만 책 한 권이 필요하기도 합니다. 이 책이 대화형 3차원 응용 프로그램을 다루는 방식과 마찬가지로, 이 장도 그래픽스의 전체 원리를 간략하게 살펴봅니다.
특히 수학이 핵심 역할을 하는 주제에 집중합니다. 다른 장들과 마찬가지로, 저자들의 경험상 다른 자료에서 쉽게 지나치거나 초보자가 혼란을 느끼는 주제에 특별히 주의를 기울이겠습니다.
좀 더 직접적으로 말하자면, 이 장만 읽고 화면에 멋진 그림을 띄우는 방법을 모두 배울 수는 없습니다. 하지만 그래픽스 강좌나 다른 책, 또는 독학 과정과 함께 읽거나 그보다 먼저 읽으면 좋습니다. 흔히 막히는 몇몇 지점을 수월하게 넘어가는 데 도움이 되기를 바랍니다. 장의 끝부분에 고수준 셰이딩 언어인 HLSL의 예제 코드가 나오지만, 원하는 효과를 내려면 어떤 DirectX나 OpenGL 함수를 호출해야 하는지 알려주는 내용은 그 밖에는 많지 않습니다.
이런 문제는 실무적으로 매우 중요합니다. 그러나 로버트 메이너드 허친스가 ‘빠르게 낡아가는 사실’이라고 부른 지식이기도 합니다. 저자들은 ATI가 새 그래픽 카드를 출시하거나 마이크로소프트가 새 DirectX 버전을 내놓을 때마다 격년으로 개정해야 하는 책을 쓰고 싶지는 않았습니다.
다행히 최신 API 설명과 예제는 인터넷에 풍부합니다. 그런 정보는 인터넷에서 얻는 편이 훨씬 적절합니다. API는 application programming interface, 즉 응용 프로그램 프로그래밍 인터페이스의 약자입니다. 이 장에서는 렌더링 하위 시스템과 통신할 때 사용하는 소프트웨어 인터페이스를 뜻합니다.
마지막으로, 이 책은 비디오 게임을 위한 수학책이므로 실시간 그래픽스에 무게를 둡니다. 그렇다고 광선 추적기를 만드는 데 관심이 있는 독자에게 쓸모없다는 뜻은 아닙니다. 다만 저자들의 전문 분야와 주된 관심이 실시간 그래픽스에 있다는 뜻입니다.
이 장은 대체로 추상적인 이론에서 출발해 실제 코드로 내려오는 순서로 구성되어 있습니다.
•
10.1절에서는 그래픽스를 전체 원리를 살펴보는 이론적 관점에서 살펴보고, 마지막에 렌더링 방정식에 도달합니다.
•
그다음에는 특정 플랫폼에 의존하지 않고 10년 뒤에도 유효한 설명을 유지하면서, 좀 더 직접적으로 활용할 수 있는 문제로 넘어갑니다.
◦
10.2절은 3D 장면을 바라보는 데 필요한 기본 수학을 다룹니다.
◦
10.3절은 중요한 좌표 공간과 변환을 소개합니다.
◦
10.4절은 장면 속 물체의 표면을 폴리곤 메시로 표현하는 방법을 살펴봅니다.
◦
10.5절은 텍스처 맵으로 물체의 ‘색’과 같은 재질 속성을 제어하는 방법을 보여줍니다.
•
이어지는 절들은 조명을 다룹니다.
◦
10.6절은 널리 쓰이는 블린–퐁 조명 모델을 정의합니다.
◦
10.7절은 광원을 표현하는 몇 가지 일반적인 방법을 설명합니다.
•
변하지 않는 이론에서 조금 더 벗어나, 집필 당시 특히 관심을 받던 두 주제를 다룹니다.
◦
10.8절은 골격 애니메이션을 설명합니다.
◦
10.9절은 범프 매핑의 작동 원리를 설명합니다.
•
장의 마지막 약 3분의 1은 가장 실무적인 만큼, 시간이 지나면서 낡을 가능성도 가장 큽니다.
◦
10.10절은 간단한 실시간 그래픽스 파이프라인을 개괄한 뒤, 각 단계를 따라가며 관련 수학 문제를 설명합니다.
◦
10.11절은 앞서 배운 기법을 보여주는 여러 HLSL 예제로 마무리합니다. 이 부분은 특히 ‘빠르게 낡아가는 사실’의 영역에 해당합니다.

10.1 그래픽스는 어떻게 작동하는가? (Rendering)

그래픽스에 대한 논의는 실제로 무엇이 어떻게 작동하는지 설명하는 데서 시작하겠습니다. 더 정확히는 모든 것을 올바르게 구현할 만큼 충분한 지식과 처리 능력이 있다면 어떻게 작동해야 하는지 살펴보겠습니다. 처음 공부하는 독자에게 한 가지 당부하겠습니다. 많은 입문 자료, 특히 인터넷의 튜토리얼과 API 문서는 전체적인 관점을 충분히 제공하지 않습니다.
그런 자료를 읽다 보면 디퓨즈 맵, 블린–퐁 셰이딩, 앰비언트 오클루전이 ‘현실 세계에서 영상이 만들어지는 방식 자체’인 것처럼 느껴질 수 있습니다. 하지만 실제로는 특정 조명 모델을 특정 언어와 API를 이용해 특정 하드웨어에서 구현하는 방법을 읽고 있는 경우가 많습니다.
구체적인 구현을 설명하는 자료라면 결국 조명 모델, 언어, 플랫폼, 색 표현 방식, 성능 목표 등을 선택해야 합니다. 이 장의 뒷부분에서도 그렇게 합니다. 전체적인 관점을 좁히는 것은 대개 의도적이며 합리적입니다. 그렇더라도 어떤 내용이 근본적이고 시간이 지나도 변하지 않는 원리인지, 어떤 내용이 근사와 절충에 따라 선택한 구현 방식인지는 구별해야 한다고 생각합니다.
후자는 기술적 한계의 영향을 받으며, 그 한계가 실시간 렌더링에만 해당하거나 가까운 미래에 바뀔 수도 있습니다. 그러므로 실시간 그래픽스 입문에 적합한 특정 렌더링 방식의 세부 사항으로 깊이 들어가기 전에, 렌더링이 본질적으로 어떻게 작동하는지 설명해 보겠습니다.
또 한 가지 미리 밝혀둘 점은 지금부터의 설명이 자연의 작동 방식을 흉내 내는 사실적인 영상, 즉 포토리얼리즘을 목표로 한다는 것입니다. 실제로는 이것이 목표가 아닌 경우도 많고, 이것만이 유일한 목표인 경우는 결코 없습니다. 자연을 이해하는 것은 매우 중요한 출발점이지만, 예술적·실용적 요인 때문에 자연을 그대로 시뮬레이션하는 것과 다른 전략을 택할 때가 많습니다.

10.1.1 렌더링에 접근하는 두 가지 주요 방법

최종 결과부터 생각해 봅시다. 렌더링의 최종 목표는 비트맵 한 장입니다. 애니메이션이라면 비트맵의 연속이 됩니다. 비트맵이 색을 직사각형 격자로 배열한 것이라는 사실은 이미 알고 있을 것입니다. 격자의 각 항목을 픽셀이라고 하는데, picture element, 즉 ‘그림의 구성 요소’를 줄인 말입니다. 영상을 만들어내는 동안 이 비트맵을 프레임 버퍼라고도 부릅니다. 프레임 버퍼를 최종 비트맵 출력으로 복사할 때 추가적인 후처리나 변환이 수행되기도 합니다.
각 픽셀의 색을 어떻게 결정할까요? 이것이 렌더링의 근본적인 질문입니다. 컴퓨터 과학의 많은 문제와 마찬가지로, 자연이 어떻게 작동하는지 살펴보는 것이 좋은 출발점입니다.
우리가 보는 것은 빛입니다. 우리가 지각하는 영상은 주변 환경을 돌아다니며 반사된 빛이 마침내 눈에 들어온 결과입니다. 이 과정은 한마디로 매우 복잡합니다. 빛이 반사되는 물리 과정뿐 아니라[각주 1], 눈 안의 감지 장치가 작동하는 생리 과정[각주 2], 머릿속에서 이를 해석하는 과정도 복잡합니다. 따라서 입문서가 으레 그렇듯 많은 세부 사항과 예외를 제쳐 두면, 렌더링 시스템이 각 픽셀에 대해 답해야 하는 기본 질문은 다음과 같습니다.
이 픽셀에 해당하는 방향에서 카메라로 다가오는 빛은 어떤 색인가?
기본적으로 두 가지 경우가 있습니다. 광원을 직접 바라보고 있어서 빛이 광원에서 눈으로 곧바로 들어오는 경우가 하나입니다. 더 흔한 경우는 광원을 떠난 빛이 다른 방향으로 진행하다가 한 번 이상 반사된 뒤 눈에 들어오는 경우입니다. 앞의 핵심 질문은 다음 두 작업으로 나눌 수 있습니다. 이 책에서는 이 두 작업을 묶어 ‘렌더링 알고리즘’이라고 부르겠습니다. 물론 이처럼 추상화한 두 단계 안에는 실제 구현 알고리즘의 엄청난 복잡성이 숨어 있습니다.
1.
보이는 표면 결정(visible surface determination): 현재 픽셀에 해당하는 방향에서 눈에 가장 가까운 표면을 찾습니다.
2.
조명(lighting): 그 표면이 눈 방향으로 방출하거나 반사하는 빛을 결정합니다.
지나치게 단순화한 것처럼 보일 것입니다. 마음속으로 손을 들고 ‘반투명한 물체는요?’, ‘반사는요?’, ‘굴절은요?’, ‘대기 효과는요?’라고 묻는 독자도 있을 것입니다. 질문은 설명이 끝날 때까지 잠시 기다려 주세요.
렌더링 알고리즘의 첫 단계는 보이는 표면 결정입니다. 이 문제를 해결하는 대표적인 방법은 두 가지입니다. 첫째는 광선 추적(raytracing)입니다. 발광 표면에서 출발한 빛이 실제로 진행하는 방향을 따라가는 대신, 광선을 거꾸로 추적합니다. 이렇게 하면 특정 방향에서 눈에 들어오는, 즉 우리에게 필요한 광선만 다룰 수 있습니다.
눈에서 각 픽셀의 중심을 통과하는 방향으로 광선을 내보내고[각주 3], 그 광선이 장면에서 처음으로 만나는 물체를 찾습니다. 그런 다음 그 표면에서 광선을 거슬러 눈 쪽으로 방출되거나 반사되는 색을 계산합니다. 코드 10.1은 이 알고리즘을 매우 단순화한 것입니다.
코드 10.1 — 광선 추적 알고리즘의 의사 코드
for (each x, y screen pixel) { // 이 픽셀을 위한 광선을 선택합니다. Ray ray = getRayForPixel(x, y); // 광선과 장면의 기하 구조가 교차하는지 검사합니다. // 교점뿐 아니라 표면 법선과 셰이딩에 필요한 정보도 구합니다. // 예: 물체 참조, 재질 정보, 로컬 S/T 좌표 등. // 이 코드는 개념을 보여주는 의사 코드임을 기억하세요. Vector3 pos, normal; Object* obj; Material* mtl; if (rayIntersectScene(ray, pos, normal, obj, mtl)) { // 교점을 셰이딩합니다. // 이 점이 카메라 쪽으로 방출하거나 반사하는 빛은 무엇일까요? Color c = shadePoint(ray, pos, normal, obj, mtl); writeFrameBuffer(x, y, c); } else { // 장면의 어떤 물체와도 만나지 않았으므로 배경색을 사용합니다. writeFrameBuffer(x, y, backgroundColor); } }
C++
복사
보이는 표면을 결정하는 또 하나의 주요 방법은 깊이 버퍼링(depth buffering)입니다. 이 책의 집필 당시 실시간 렌더링에서 사용하던 방식입니다. 기본 생각은 각 픽셀에 색뿐 아니라 깊이도 저장하는 것입니다. 깊이 버퍼에 기록하는 값은 그 픽셀의 색을 결정하는 빛을 반사하거나 방출하는 표면과 눈 사이의 거리를 나타냅니다.
코드 10.1에서 보았듯 광선 추적기의 가장 바깥 반복문은 화면 공간의 픽셀을 순회합니다. 반면 실시간 그래픽스에서 가장 바깥 반복문은 장면의 표면을 구성하는 기하 요소를 순회합니다.
여기서는 표면을 표현하는 여러 방식 자체가 중요하지 않습니다. 중요한 점은 표면을 화면 공간에 투영한 뒤, 래스터화(rasterization) 과정을 통해 화면의 픽셀에 대응시킬 수 있다는 것입니다. 표면이 만들어내는 각 픽셀 후보를 소스 프래그먼트(source fragment)라고 합니다.
그 위치에서 표면의 깊이를 계산하고 깊이 버퍼에 이미 기록된 값과 비교합니다. 기존 값에 해당하는 프래그먼트를 대상 프래그먼트(destination fragment)라고 부르기도 합니다.
현재 렌더링하는 소스 프래그먼트가 버퍼에 기록된 값보다 카메라에서 더 멀다면, 앞서 렌더링한 것이 현재 표면을 가리고 있다는 뜻입니다. 적어도 이 픽셀에서는 그렇습니다. 그러면 다음 픽셀로 넘어갑니다. 반대로 현재 깊이가 기존 값보다 가깝다면, 지금까지 렌더링한 것 가운데 이 표면이 눈에 가장 가깝다는 뜻입니다.
따라서 더 가까운 새 깊이로 깊이 버퍼를 갱신합니다. 이때 렌더링 알고리즘의 두 번째 단계도 수행하여, 그 표면의 해당 점에서 방출하거나 반사하는 빛의 색으로 프레임 버퍼를 갱신할 수 있습니다. 이것을 포워드 렌더링(forward rendering)이라고 하며, 기본 아이디어는 코드 10.2에 나옵니다.
코드 10.2 — 깊이 버퍼를 사용하는 포워드 렌더링의 의사 코드
// 프레임 버퍼와 깊이 버퍼를 초기화합니다. fillFrameBuffer(backgroundColor); fillDepthBuffer(infinity); // 모든 기하 프리미티브(보통 삼각형)를 순회합니다. for (each geometric primitive) { // 프리미티브를 래스터화합니다. for (each pixel x, y in the projection of the primitive) { // 더 가까운 표면이 이미 기록되었는지 깊이 버퍼로 검사합니다. float primDepth = getDepthOfPrimitiveAtPixel(x, y); if (primDepth > readDepthBuffer(x, y)) { // 이 프리미티브의 픽셀이 가려졌으므로 버립니다. continue; } // 이 위치에서 프리미티브의 색을 계산합니다. Color c = getColorOfPrimitiveAtPixel(x, y); // 색과 깊이를 모두 기록합니다. writeFrameBuffer(x, y, c); writeDepthBuffer(x, y, primDepth); } }
C++
복사
포워드 렌더링에 대응되는 방식은 디퍼드 렌더링(deferred rendering, 지연 렌더링)입니다. 오래된 기법이지만, 집필 당시 제작하는 영상과 하드웨어의 병목 위치가 달라지면서 다시 인기를 얻고 있었습니다. 디퍼드 렌더러는 프레임 버퍼와 깊이 버퍼 외에도 여러 버퍼를 사용합니다.
이들을 통틀어 G 버퍼(G-buffer)라고 하며, G는 geometry의 약자입니다. G 버퍼에는 각 화면 위치에서 눈에 가장 가까운 표면의 추가 정보를 저장합니다. 예를 들어 표면의 3D 위치, 표면 법선, 그리고 물체의 ‘색’이나 그 위치가 얼마나 ‘반짝이는지’처럼 조명 계산에 필요한 재질 속성을 저장합니다.
뒤에서 보겠지만 따옴표로 표시한 이런 직관적 표현은 렌더링에 쓰기에는 다소 모호합니다.
디퍼드 렌더러는 포워드 렌더러보다 앞서 제시한 두 단계 알고리즘을 더 문자 그대로 따릅니다. 먼저 장면을 G 버퍼로 ‘렌더링’합니다. 이때는 각 픽셀이 보는 점의 재질 속성만 가져오고 조명은 계산하지 않습니다. 본질적으로 가시성 결정만 하는 것입니다. 두 번째 패스에서 실제 조명 계산을 수행합니다. 코드 10.3은 이 과정을 의사 코드로 설명합니다.
코드 10.3 — 깊이 버퍼를 사용하는 디퍼드 렌더링의 의사 코드
// 기하 정보 버퍼와 깊이 버퍼를 초기화합니다. clearGeometryBuffer(); fillDepthBuffer(infinity); // 모든 프리미티브를 G 버퍼에 래스터화합니다. for (each geometric primitive) { for (each pixel x, y in the projection of the primitive) { // 더 가까운 픽셀이 이미 기록되었는지 검사합니다. float primDepth = getDepthOfPrimitiveAtPixel(x, y); if (primDepth > readDepthBuffer(x, y)) { continue; // 가려진 프래그먼트입니다. } // 다음 패스의 셰이딩에 필요한 정보를 가져옵니다. MaterialInfo mtlInfo; Vector3 pos, normal; getPrimitiveShadingInfo(mtlInfo, pos, normal); // G 버퍼와 깊이 버퍼에 저장합니다. writeGeometryBuffer(x, y, mtlInfo, pos, normal); writeDepthBuffer(x, y, primDepth); } } // 두 번째 패스에서는 화면 공간을 순회하며 셰이딩합니다. for (each x, y screen pixel) { if (readDepthBuffer(x, y) == infinity) { // 이 위치에는 기하가 없으므로 배경색을 기록합니다. writeFrameBuffer(x, y, backgroundColor); } else { // 기하 정보 버퍼에서 셰이딩 정보를 다시 읽습니다. MaterialInfo mtlInfo; Vector3 pos, normal; readGeometryBuffer(x, y, mtlInfo, pos, normal); Color c = shadePoint(pos, normal, mtlInfo); writeFrameBuffer(x, y, c); } }
C++
복사
다음으로 넘어가기 전에, 디퍼드 렌더링이 인기를 얻는 중요한 이유를 하나 짚겠습니다. 여러 광원이 같은 표면의 점을 비출 때, 하드웨어의 제약이나 성능 문제 때문에 앞의 의사 코드처럼 한 번의 계산으로 최종 픽셀 색을 얻을 수 없는 경우가 있습니다. 그러면 광원마다 하나의 패스를 수행하고, 각 광원이 만들어낸 반사광을 프레임 버퍼에 누적해야 합니다.
포워드 렌더링에서는 추가 패스마다 프리미티브를 다시 렌더링합니다. 반면 디퍼드 렌더링에서는 추가 패스가 영상 공간에서 진행되므로, 그 비용은 장면의 복잡도가 아니라 화면에서 광원이 차지하는 2D 크기에 따라 달라집니다. 바로 이런 상황에서 디퍼드 렌더링이 포워드 렌더링보다 큰 성능상의 이점을 보이기 시작합니다.

원문 각주

1.
실제로는 거의 모든 렌더링 시스템이 빛의 진짜 물리 현상을 더 단순한 기하광학으로 근사합니다.
2.
장치를 이야기하자면, 눈에서는 일어나지 않지만 카메라에서는 발생하는 현상이나 필름에 영상을 기록하면서 생기는 현상도 많습니다. 애니메이션이 실제로 촬영된 것처럼 보이게 하려고 이런 효과도 자주 모사합니다.
3.
픽셀에 ‘중심’이 있다고 생각하는 것은 사실 그리 좋은 생각이 아닐 수 있습니다. 픽셀은 본래 작은 직사각형 색 덩어리라기보다, 연속적인 신호에서 얻은 무한히 작은 점 표본으로 이해하는 편이 좋기 때문입니다. 어떤 사고 모형을 택하느냐는 매우 중요한 문제이며[원문 참고문헌 33, 66], 픽셀들을 결합해 영상을 복원하는 과정과 밀접하게 관련됩니다. CRT에서 픽셀은 확실히 작은 직사각형이 아니었습니다. LCD와 같은 현대 디스플레이에서는 ‘직사각형 색 덩어리’도 복원 과정을 설명하는 데 아주 나쁜 표현은 아닙니다. 어느 해석을 택하든 각 픽셀 중심으로 광선 하나만 내보낼 필요는 없습니다. 잘 설계한 배치에 따라 여러 광선, 즉 표본을 보내고 적절한 방식으로 평균을 낼 수도 있습니다.
💡
루프의 바깥쪽이 무엇을 순회하는가?
광선 추적은 ‘이 픽셀이 무엇을 보는가?’에서 시작합니다. 래스터화는 ‘이 삼각형이 어느 픽셀을 덮는가?’에서 시작합니다. 두 경우 모두 어느 표면이 보이는가와 그 표면에서 얼마만큼의 빛이 오는가는 서로 다른 질문입니다. 광선 추적을 썼다는 사실만으로 조명까지 물리적으로 정확해지는 것은 아닙니다.
flowchart LR
    A["픽셀에서 출발"] --> B["광선과 장면의 교차 검사"]
    C["삼각형에서 출발"] --> D["래스터화와 깊이 검사"]
    B --> E["보이는 표면"]
    D --> E
    E --> F["재질과 조명 계산"]
    F --> G["픽셀의 최종 색"]
Mermaid
복사
손으로 따라 해보기: 같은 픽셀을 덮는 빨간 삼각형과 파란 삼각형이 있고, 깊이가 각각 8과 3이라고 합시다. 가까울수록 깊이 값이 작다는 위 의사 코드의 규칙에서는, 어느 삼각형을 먼저 처리하든 최종 깊이가 3이고 파란 삼각형이 남습니다. 이것이 깊이 버퍼가 해결하는 문제입니다. 투명한 표면의 여러 층을 섞는 문제까지 이 단순한 비교로 해결되지는 않습니다.
시대에 따른 설명 구분: 위 본문에서 ‘현재’나 ‘집필 당시’라고 말하는 기술 상황은 2011년을 기준으로 합니다. 원문의 설명을 보존하기 위해 당시의 가정과 표현을 유지했습니다. 의사 코드는 구현 원리를 보여주며, 특정 그래픽 API에 그대로 붙여 넣는 완성 코드가 아닙니다.

10.1.2 표면의 성질 표현하기: BRDF

이제 렌더링 알고리즘의 두 번째 단계인 조명을 이야기해 봅시다. 눈에 가장 가까운 표면을 찾았다면, 그 표면이 직접 방출하는 빛과 다른 광원에서 출발해 그 표면에서 눈 방향으로 반사되는 빛의 양을 결정해야 합니다. 전구나 태양을 직접 바라보는 경우처럼 표면에서 눈으로 직접 전달되는 빛이 가장 단순한 경우입니다.
대부분의 장면에서 이런 발광 표면은 소수입니다. 대부분의 표면은 스스로 빛을 내지 않고, 다른 곳에서 온 빛을 반사할 뿐입니다. 따라서 여기서는 빛을 내지 않는 표면에 주로 관심을 두겠습니다.
일상적으로는 물체의 ‘색’을 이야기하지만, 실제로 우리가 지각하는 색은 눈으로 들어오는 빛이므로 여러 요인에 따라 달라집니다. 어떤 색의 빛이 어느 방향에서 표면에 들어오는가? 우리는 어느 방향에서 그 표면을 보는가? 물체가 얼마나 ‘반짝이는가’?[각주 4] 이런 질문이 중요합니다.
따라서 렌더링에 적합한 표면 설명은 단순히 ‘이 표면은 무슨 색인가?’에 답하는 것이 아닙니다. 거울의 색을 묻는 경우처럼 이 질문이 의미 없을 때도 있습니다. 대신 다음처럼 조금 더 복잡한 질문을 던져야 합니다.
주어진 색의 빛이 주어진 입사 방향에서 표면에 부딪힐 때, 그중 얼마나 많은 빛이 다른 특정 방향으로 반사되는가?
이 질문에 답하는 것이 양방향 반사 분포 함수(bidirectional reflectance distribution function), 줄여서 BRDF입니다. ‘물체는 무슨 색인가?’ 대신 ‘반사되는 빛은 어떻게 분포하는가?’를 묻는 것입니다.
BRDF를 기호로 쓰면 다음과 같습니다.[각주 5]
f(x,ω^in,ω^out,λ)f(\mathbf{x},\hat{\boldsymbol{\omega}}_{\mathrm{in}},\hat{\boldsymbol{\omega}}_{\mathrm{out}},\lambda)
이 함수의 값은 스칼라입니다. 점 x\mathbf{x}에 ω^in\hat{\boldsymbol{\omega}}_{\mathrm{in}} 방향에서 들어온 빛이 다른 방향이 아닌 ω^out\hat{\boldsymbol{\omega}}_{\mathrm{out}} 방향으로 반사되는 상대적인 경향을 나타냅니다. 굵은 글씨와 모자 기호가 나타내듯 ω^\hat{\boldsymbol{\omega}}를 단위 벡터로 표현할 수 있습니다. 더 일반적으로는 방향을 표현하는 어떤 방식을 사용해도 됩니다.
극좌표의 각도도 자연스러운 선택이며 자주 쓰입니다. 보통 빛의 색이 다르면 반사되는 방식도 달라지므로, 함수에는 빛의 색, 더 정확히는 파장을 나타내는 λ\lambda도 들어갑니다.
우리는 특히 발광 표면에서 오는 입사 방향과 눈을 향하는 출사 방향에 관심이 있지만, 일반적으로는 분포 전체가 중요합니다. 우선 광원, 눈, 표면은 움직일 수 있습니다. 따라서 ‘빨간 가죽’ 같은 표면의 성질을 정의할 때 어떤 방향이 중요해질지 미리 알 수 없습니다. 모든 표면과 광원과 눈이 고정된 특정 장면에서도 빛은 여러 번 반사될 수 있습니다. 그러므로 임의의 두 방향 사이에서 일어나는 빛의 반사를 나타낼 수 있어야 합니다.
다음으로 넘어가기 전에, 앞서 너무 모호하다고 했던 직관적인 재질 속성인 ‘색’과 ‘반짝임’을 BRDF로 어떻게 정확히 표현하는지 살펴보면 도움이 됩니다. 초록색 공을 생각해 봅시다. 초록 물체가 파란색이 아니라 초록색으로 보이는 이유는 다른 색의 입사광보다 초록 입사광을 더 강하게 반사하기 때문입니다.[각주 6] 예를 들어 초록 빛은 대부분 반사하고 조금만 흡수하지만, 빨강과 파랑 빛은 95%를 흡수하고 5%만 여러 방향으로 반사한다고 합시다.
흰 빛은 여러 색의 빛이 함께 섞인 것이므로, 초록 물체는 사실상 초록 이외의 색을 걸러내는 셈입니다.
다른 물체가 초록과 빨강에는 이 공과 같은 반응을 보이지만, 파랑은 50%를 흡수하고 50%를 반사한다면 그 물체는 청록색으로 보일 수 있습니다. 또는 모든 파장의 빛을 대부분 흡수하고 초록 빛만 조금 반사한다면 어두운 초록색으로 보일 것입니다. 정리하면, BRDF는 파장 λ\lambda에 대한 의존성을 통해 두 물체의 색 차이를 표현합니다. 각각의 파장에는 저마다의 반사 분포가 있습니다.
이제 반짝이는 빨간 플라스틱과 광택이 없는 빨간 색종이를 비교해 봅시다. 반짝이는 표면은 들어온 빛을 다른 방향에 비해 특정 방향으로 훨씬 강하게 반사합니다. 반면 확산 표면은 빛을 여러 출사 방향으로 더 고르게 흩뿌립니다. 거울 같은 완전한 반사체는 한 방향에서 들어온 빛을 하나의 출사 방향으로 모두 반사합니다.
완전히 확산하는 표면은 입사 방향과 관계없이 모든 출사 방향에 똑같이 빛을 반사합니다. 결국 BRDF는 입사 방향 ω^in\hat{\boldsymbol{\omega}}_{\mathrm{in}}과 출사 방향 ω^out\hat{\boldsymbol{\omega}}_{\mathrm{out}}에 대한 의존성으로 물체 사이의 ‘반짝임’ 차이를 설명합니다.
BRDF를 일반화하면 더 복잡한 현상도 표현할 수 있습니다. 방향 벡터가 표면 안쪽을 향하도록 허용하면 반투명과 굴절을 포함할 수 있습니다. 원문에서는 이런 수학적 일반화를 양방향 표면 산란 분포 함수(bidirectional surface scattering distribution function, BSSDF)라고 부를 수 있다고 설명합니다.
때로는 빛이 물체에 들어가 내부에서 여러 번 반사된 다음 다른 지점으로 나오기도 합니다. 이것이 표면하 산란(subsurface scattering)이며, 피부나 우유 등 흔한 물질의 외관을 결정하는 중요한 요소입니다. 이를 표현하려면 하나였던 반사 위치 x\mathbf{x}를 입사 위치 xin\mathbf{x}_{\mathrm{in}}과 출사 위치 xout\mathbf{x}_{\mathrm{out}}으로 나누어야 합니다.
원문은 이때도 양방향 표면 산란 분포 함수라는 이름과 BSSDF라는 약자를 사용합니다. 안개나 표면하 산란 같은 체적 효과도 표현할 수 있습니다. 이름에서 ‘표면’을 떼어내고, 표면뿐 아니라 공간의 모든 점에 양방향 산란 분포 함수(bidirectional scattering distribution function, BSDF)를 정의하면 됩니다.
얼핏 쓸모없는 추상화처럼 보일 수 있지만, 실제 도구를 어떻게 설계해야 할지 이해하는 데 도움이 될 수 있습니다.
한편 BRDF가 물리적으로 타당하려면 만족해야 할 조건들이 있습니다. 첫째, 어떤 방향으로 반사되는 빛의 양이 음수일 수는 없습니다. 둘째, 반사광 전체가 입사광보다 많을 수는 없습니다. 표면이 에너지 일부를 흡수하여 반사광이 더 적어지는 것은 가능합니다. 이 규칙을 보통 정규화 제약(normalization constraint)이라고 부릅니다.
마지막으로, 덜 직관적이지만 실제 표면이 따르는 헬름홀츠 상반성(Helmholtz reciprocity)이 있습니다. 임의의 두 방향을 택했을 때 어느 것을 입사 방향으로 삼고 어느 것을 출사 방향으로 삼든 반사되는 비율은 같아야 한다는 원리입니다. 즉,
f(x,ω^1,ω^2,λ)=f(x,ω^2,ω^1,λ).f(\mathbf{x},\hat{\boldsymbol{\omega}}_1,\hat{\boldsymbol{\omega}}_2,\lambda) =f(\mathbf{x},\hat{\boldsymbol{\omega}}_2,\hat{\boldsymbol{\omega}}_1,\lambda).
헬름홀츠 상반성 때문에 일부 저자는 BRDF의 두 방향을 ‘in’과 ‘out’으로 구분하지 않습니다. 물리적으로 타당하려면 계산이 두 방향에 대해 대칭이어야 하기 때문입니다.
BRDF는 특정 지점에서 표면이 빛을 어떻게 반사하는지 설명하므로, 그 지점의 물체 외관에 대한 완전한 설명을 담습니다. 당연히 이 함수를 설계할 때는 많은 고민이 필요합니다. 지난 수십 년 동안 수많은 조명 모델이 제안되었습니다. 놀랍게도 초창기 모델 중 하나인 블린–퐁(Blinn–Phong)은 집필 당시에도 실시간 그래픽스에서 널리 쓰이고 있었습니다.
이 모델은 물리적으로 정확하지 않습니다. 정규화 제약을 위반하므로 물리적으로 타당하지도 않습니다. 그럼에도 학습을 위한 좋은 디딤돌이자 그래픽스 역사의 중요한 일부이므로 이 책에서 다룹니다. 사실 ‘역사’라고 부르는 것은 희망 섞인 표현입니다. 이 모델을 공부해야 하는 가장 중요한 이유는 여전히 널리 쓰이고 있다는 점일지도 모릅니다.
특정 방법이 마치 ‘그래픽스가 작동하는 방식 자체’인 것처럼 소개된다는, 장의 첫머리에서 지적한 현상을 가장 잘 보여주는 사례이기도 합니다.
조명 모델마다 목표가 다릅니다. 어떤 모델은 거친 표면을, 어떤 모델은 여러 층으로 이루어진 표면을 잘 모사합니다. 어떤 모델은 조절값에 물리적인 의미가 있는지와 상관없이, 아티스트가 직관적으로 조절할 수 있는 ‘손잡이’를 제공하는 데 집중합니다. 또 어떤 모델은 고니오포토미터(goniophotometer)라는 특수한 측정 장치로 실제 표면을 측정하는 데 기반을 둡니다.
본질적으로 BRDF를 표본화한 뒤, 표에 저장한 데이터로부터 보간을 통해 함수를 복원하는 방식입니다. 10.6절의 블린–퐁 모델은 단순하고 계산 비용이 적으며 아티스트에게 익숙하다는 점에서 유용합니다. 여러 조명 모델의 개요는 추천 도서를 참고하세요.

원문 각주

1.
프레임 버퍼에 어떤 색을 기록할지를 결정하려면 전반적인 관찰 조건에 대해서도 질문할 수 있습니다. 다만 이 요인들은 눈으로 들어오는 빛 자체가 아니라, 우리가 그 빛을 지각하는 방식에 영향을 줍니다.
2.
ω\omega와 λ\lambda는 각각 그리스어 소문자 오메가와 람다입니다.
3.
여기와 다른 곳에서 사용하는 ‘색’이라는 말은 엄밀하게 따지면 다소 부정확하지만, 대부분의 그래픽스 시스템이 빛과 색에 대해 두는 가정 아래에서는 괜찮습니다.
💡
BRDF를 ‘입력 방향 → 출력 방향’ 표로 생각하기
손전등을 고정해 두고 공 주위를 돌면서 본다고 합시다. 입사 방향은 그대로인데 관찰 방향이 달라지면서 반짝이는 부분이 보였다가 사라집니다. BRDF는 이렇게 어디서 들어와 어디로 나가는지를 함께 묻는 함수입니다. 색만 저장하는 하나의 RGB 값으로는 이 변화를 설명할 수 없습니다.
flowchart LR
    A["입사 방향과 파장"] --> C["표면의 BRDF"]
    B["관찰할 출사 방향"] --> C
    C --> D["그 방향으로 반사되는 분포"]
Mermaid
복사
용어 보충: 위 원문은 투과를 포함하는 일반화와 입사·출사 위치가 다른 산란을 설명하면서 BSSDF라는 이름을 중복해서 사용합니다. 두 현상은 구별해야 합니다. 같은 표면 위치에서 반사와 투과를 함께 다루는 경우는 보통 BSDF, 입사 위치와 출사 위치가 달라지는 표면하 산란은 보통 BSSRDF라고 구분합니다. 위 본문의 BSSDF 표기는 원문의 표기이므로, 이 두 개념을 구분해서 읽어 주세요.
주의할 점: BRDF 값 자체를 단순한 ‘0~1의 반사 확률’로 이해하면 안 됩니다. 특정 방향에 대한 분포 밀도이므로, 에너지 보존은 값 하나의 상한보다 반구 전체에 대한 적분으로 검사합니다. 이 차이는 다음 절의 단위와 렌더링 방정식에서 연결됩니다.

10.1.3 색채 측정과 복사 측정의 아주 짧은 소개

그래픽스는 빛을 측정하는 일과 깊이 관련되어 있습니다. 여기서 모든 세부 사항을 설명할 수는 없지만, 중요한 미묘한 차이 몇 가지는 알고 있어야 합니다. 첫째는 빛의 색을 어떻게 측정하는가이고, 둘째는 밝기를 어떻게 측정하는가입니다.
중학교 과학 시간에 모든 빛의 색이 빨강·초록·파랑, 즉 RGB 빛의 혼합이라고 배웠을지도 모릅니다. 널리 알려진 설명이지만 완전히 정확하지는 않습니다. 빛은 가시광선 영역의 어느 한 주파수로 이루어질 수도 있고, 여러 주파수의 조합일 수도 있습니다. 색은 인간의 지각 현상으로서 주파수와 정확히 같은 개념이 아닙니다. 서로 다른 주파수 조합의 빛이 같은 색으로 지각되기도 합니다. 이런 조합을 메타머(metamer, 조건 등색)라고 합니다.
빛의 주파수에는 무한히 많은 조합이 있습니다. 피아노로 연주할 수 있는 모든 화음에, 건반 사이의 음높이까지 더한 것과 비슷합니다. 이 비유에서 인간의 색 지각은 화음 속의 개별 음을 모두 골라낼 수 없습니다. 대신 어떤 화음이든 가온 도와 파와 솔의 조합처럼 듣는 셈입니다.
물리학에서 색 채널 세 개가 특별한 숫자인 것은 아닙니다. 세 개라는 수는 인간의 시각에 특유한 것입니다. 원문은 대부분의 다른 포유류는 두 종류의 수용기를 가져 인간 기준으로는 ‘색맹’에 해당하고, 물고기·파충류·새는 네 종류의 색 수용기를 가져 그들의 기준에서는 인간이 ‘색맹’일 것이라고 설명합니다.
그런데 매우 정교한 렌더링 시스템조차 가시광선의 연속적인 스펙트럼을 어떤 이산적인 기저에 투영하며, 가장 흔한 것이 RGB 기저입니다. 거의 모든 곳에서 쓰는 단순화이지만, 이것으로 설명하지 못하는 현상도 있으므로 단순화라는 사실은 짚고 싶었습니다. RGB는 유일한 색 공간도 아니고, 여러 목적에서 반드시 가장 좋은 색 공간인 것도 아닙니다.
하지만 대부분의 디스플레이가 사용한다는 점에서 매우 편리한 기저입니다. 디스플레이에서 RGB를 널리 사용하는 이유도 인간의 시각 시스템과 닮아 있기 때문입니다. Hall의 책[원문 참고문헌 29]은 RGB 체계의 한계를 잘 설명합니다.
전자기 스펙트럼의 가시 영역은 연속적이므로 다음 표현도 이론적으로는 파장 λ\lambda에 대해 연속적이어야 합니다.
f(x,ω^in,ω^out,λ)f(\mathbf{x},\hat{\boldsymbol{\omega}}_{\mathrm{in}},\hat{\boldsymbol{\omega}}_{\mathrm{out}},\lambda)
실제로는 사람이 볼 영상을 만들기 때문에, 무한히 다양한 λ\lambda를 세 개의 특정 파장으로 줄여 취급합니다. 보통 빨강·초록·파랑으로 지각되는 세 파장을 선택합니다. 실무적인 관점에서는 식에 나타나는 λ\lambda를 세 가지 이산적인 ‘색 채널’ 중 어느 채널을 계산하는지 선택하는 정수처럼 생각해도 됩니다.

색에 관한 핵심 사항 — 원문의 정리

•
빛의 스펙트럼 분포를 설명하려면 숫자 세 개가 아니라 연속적인 함수가 필요합니다. 하지만 사람이 그 빛을 어떻게 지각하는지 설명하는 데는 본질적으로 숫자 세 개면 충분합니다.
•
RGB는 편리한 색 공간이지만 유일한 색 공간은 아니며, 실무적인 목적에 따라 가장 좋은 공간도 아닐 수 있습니다. 실무에서 빛을 주로 빨강·초록·파랑의 조합으로 다루는 것은 사람이 볼 영상을 만들기 때문입니다.
빛의 세기를 측정하는 여러 방식도 알아두어야 합니다. 물리학의 관점에서는 빛을 전자기 복사의 형태로 전달되는 에너지로 보고, 복사 측정(radiometry) 분야의 단위를 사용합니다. 가장 기본적인 양은 복사 에너지(radiant energy)이며, SI에서는 에너지의 표준 단위인 줄(J)로 측정합니다.
다른 에너지와 마찬가지로 단위 시간에 얼마만큼의 에너지가 흐르는지에도 관심이 있습니다. 이것이 일률(power)입니다. SI에서 일률은 와트(W)로 측정하며, 1와트는 초당 1줄입니다.
1 W=1 J/s1\,\mathrm{W}=1\,\mathrm{J/s}
전자기 복사 형태의 일률을 복사 일률(radiant power) 또는 복사속(radiant flux)이라고 합니다. flux는 ‘흐름’을 뜻하는 라틴어 fluxus에서 유래했으며, 어떤 단면을 가로질러 흐르는 양을 말합니다. 따라서 복사속은 단위 시간 동안 어떤 면적에 도착하거나, 그 면적에서 떠나거나, 그 면적을 가로질러 흐르는 에너지의 총량입니다.
면적이 1제곱미터인 표면과 100제곱미터인 다른 표면에서 똑같은 복사속이 방출된다고 상상해 보세요. 분명 작은 표면이 더 ‘밝습니다’. 더 정확히 말하면 단위 면적당 복사속, 즉 복사속 밀도(flux density)가 더 큽니다. 원문에서는 단위 면적당 복사속을 나타내는 복사 측정 용어를 라디오시티(radiosity)라고 설명하며, 단위는 제곱미터당 와트입니다.
복사속과 라디오시티의 관계는 힘과 압력의 관계에 비유할 수 있습니다. 둘을 혼동하면 힘과 압력을 혼동할 때와 비슷한 개념 오류가 생깁니다.
라디오시티와 관련된 동등한 단위의 용어가 여러 개 있습니다. 먼저 복사속 밀도나 총 복사속은 임의의 단면을 가로질러 측정할 수 있습니다. 유한한 면적을 가진 실제 표면에서 방출되는 복사 일률을 측정할 수도 있고, 광원을 둘러싼 가상의 구 표면처럼 수학적으로만 존재하는 경계면을 빛이 통과하는 양을 측정할 수도 있습니다. 원문은 이들이 모두 복사속 밀도를 측정한다는 공통점에 주목하면서, 빛이 들어오는지 나가는지에 따라 더 구체적인 용어를 사용한다고 설명합니다.
빛이 표면에 도착하는 경우에는 복사조도(irradiance)라고 합니다. 빛이 표면에서 방출되는 경우에는 복사출사도(radiant exitance 또는 radiant emittance)라고 합니다. 디지털 영상 합성 분야에서 라디오시티(radiosity)라는 말은 주로 반사되었든 자체적으로 방출되었든 표면에서 떠나는 빛을 가리킵니다.
특정 한 점의 밝기를 이야기할 때는 단순한 복사 일률을 사용할 수 없습니다. 점의 면적이 무한히 작아 사실상 0이기 때문입니다. 한 점에서의 복사속 밀도는 이야기할 수 있지만, 복사속을 측정하려면 그 양을 합할 유한한 면적이 필요합니다. 유한한 표면 전체의 총량을 숫자 하나로 나타낸다면 복사속을 사용합니다. 반면 그 표면 안에서 어느 위치가 다른 위치보다 더 밝다는 사실까지 표현하려면, 위치에 따라 달라지는 함수로 복사속 밀도를 나타냅니다.
이제 그래픽스에서 가장 핵심적인 측정량 중 하나인, 빛의 ‘광선’ 하나가 지닌 세기를 생각해 볼 준비가 되었습니다. 앞의 생각을 조금 확장하면 라디오시티가 왜 이 목적에 맞지 않는지 알 수 있습니다. 표면의 한 점이 빛을 내는 돔에 둘러싸여 있고, 표면 법선을 중심으로 하는 반구의 모든 방향에서 빛을 받아 일정한 복사조도를 가진다고 합시다.
다른 한 점도 같은 복사조도를 받지만, 이번에는 모든 빛이 한 방향의 아주 가느다란 빔으로 들어온다고 합시다. 직관적으로 그 빔을 따라오는 광선 하나는 첫 번째 점을 비추는 광선 하나보다 더 ‘밝습니다’. 복사조도가 어떤 의미에서 더 조밀한 것입니다. 여기서는 단위 입체각당 더 조밀합니다.
입체각이라는 개념이 낯설 수 있지만 평면의 각도와 비교하면 쉽게 이해할 수 있습니다. 보통의 각도를 라디안으로 측정할 때는 단위원에 투영된 호의 길이를 사용합니다. 이와 비슷하게 입체각(solid angle)은 그 점을 둘러싼 단위 구에 투영된 면적을 측정합니다. SI 입체각 단위는 스테라디안(steradian)이며 sr로 줄여 씁니다. 구 전체의 입체각은 4π sr4\pi\,\mathrm{sr}, 반구의 입체각은 2π sr2\pi\,\mathrm{sr}입니다.
단위 입체각당 빛의 양을 측정하면, 한 점의 빛 세기를 입사 방향에 따라 달라지는 함수로 표현할 수 있습니다. 광선의 세기를 설명할 단위에 거의 도달했지만, 그림 10.1의 작은 함정이 하나 남아 있습니다. 아주 가느다란 광선 다발이 표면에 부딪히는 모습을 확대해 봅시다. 위쪽에서는 광선이 표면에 수직으로 부딪히고, 아래쪽에서는 같은 세기의 광선이 다른 표면에 비스듬히 부딪힙니다.
핵심은 위쪽 표면의 면적이 아래쪽보다 작다는 것입니다. 따라서 동일한 광선이 ‘같은 개수’만큼 도착하더라도, 위쪽 표면의 복사조도가 더 큽니다.
그림 10.1 — 같은 광선 다발을 받지만 아래쪽 표면의 면적이 더 커서 복사조도는 더 작습니다.
표면이 기울어져 있으면 입사광이 더 넓은 면적에 퍼지고 복사조도에 덜 기여하는 이 기본 현상을 램버트 법칙(Lambert’s law)이라고 합니다. 10.6.3절에서 다시 설명하겠습니다. 지금은 광선 다발이 표면의 복사조도에 기여하는 양이 그 표면의 기울기에 따라 달라진다는 점이 중요합니다.
그래픽스에서 광선의 세기를 나타내는 복사휘도(radiance)는 이러한 램버트 법칙을 고려하여, 단위 투영 면적당, 단위 입체각당 복사속으로 정의합니다. 투영 면적은 실제 표면을 광선에 수직인 평면으로 투영한 면적입니다. 그림 10.1에서 아래쪽 표면을 위쪽 표면으로 투영한다고 생각하면 됩니다. 본질적으로는 표면 기울기로 생기는 램버트 법칙의 효과를 상쇄하는 셈입니다. 표 10.1은 중요한 복사 측정 용어를 정리합니다.
표 10.1 — 자주 쓰는 복사 측정 용어
물리량
차원
SI 단위
대략적인 의미
복사 에너지(radiant energy)
에너지
J
어떤 시간 구간 동안의 빛 에너지 총량
복사속(radiant flux)
일률
W
유한한 면적에 대해 모든 방향을 합한 밝기
복사속 밀도(radiant flux density)
단위 면적당 일률
W/m²
한 점에서 모든 방향을 합한 밝기
복사조도(irradiance)
단위 면적당 일률
W/m²
들어오는 빛의 복사속 밀도
복사출사도(radiant exitance)
단위 면적당 일률
W/m²
방출되는 빛의 복사속 밀도
라디오시티(radiosity)
단위 면적당 일률
W/m²
방출되거나 반사되어 떠나는 빛의 복사속 밀도
복사휘도(radiance)
단위 투영 면적당·단위 입체각당 일률
W/(m²·sr)
광선 하나의 밝기
복사 측정이 빛의 실제 에너지를 측정하는 물리학적 관점이라면, 측광(photometry)은 같은 빛을 인간의 눈의 민감도로 가중해서 측정하는 분야입니다. 각 복사 측정 용어에 대응하는 측광 용어가 있으며 표 10.2에 정리했습니다. 원문은 실제 에너지에서 지각된 밝기로 바꾸는 비선형 변환이 두 체계의 차이라고 설명합니다.
표 10.2 — 복사 측정과 측광의 측정 단위
복사 측정 용어
측광 용어
SI 측광 단위
복사 에너지
광량(luminous energy)
탈보트(talbot), 또는 루멘초(lm·s)
복사속
광속(luminous flux / luminous power)
루멘(lm)
복사조도
조도(illuminance)
럭스(lx = lm/m²)
복사출사도
광출사도(luminous emittance)
럭스(lx = lm/m²)
복사휘도
휘도(luminance)
lm/(m²·sr)
이 장의 나머지 부분에서는 가능한 한 올바른 복사 측정 단위를 사용하겠습니다. 하지만 그래픽스의 실무에서는 특히 두 가지 이유로 단위를 다루기가 혼란스러워집니다. 첫째, 표면의 색 같은 어떤 ‘신호’를 적분하는 일이 흔합니다. 실제로는 해석적으로 적분할 수 없어 수치적으로 계산해야 하며, 이는 결국 많은 표본의 가중 평균을 구하는 형태가 됩니다.
수학적인 연산 모양만 보면 가중 평균이므로 보통은 단위가 변하지 않을 것 같습니다. 그러나 실제로 하고 있는 일은 적분입니다. 따라서 각 표본에 미소 면적이나 미소 입체각 같은 미소량이 곱해지고 있으며, 그 때문에 물리 단위가 달라집니다.
둘째, 현실에서는 0이 아닌 유한한 영역에 걸쳐 존재하는 신호를 컴퓨터 안에서는 한 점에서만 0이 아닌 신호로 표현하기도 합니다. 수학적으로는 디랙 델타의 배수라고 말합니다. 12.4.3절을 참고하세요. 예를 들어 실제 광원에는 유한한 면적이 있고, 그 발광 표면의 어느 점에서 어느 방향으로 나가는 복사휘도에 관심이 있습니다.
하지만 실무에서는 복사속을 일정하게 유지한 채 광원의 면적을 0으로 줄였다고 가정합니다. 그러면 복사속 밀도는 이론적으로 무한대가 됩니다.
실제 면광원이라면 복사속 밀도의 분포를 나타내는 신호가 필요합니다. 반면 점광원에서는 복사속 밀도가 무한대가 되므로, 그 대신 총 복사속으로 광원의 밝기를 설명합니다. 점광원을 다룰 때 이 내용을 다시 이야기하겠습니다.

복사 측정에 관한 핵심 사항 — 원문의 정리

•
더 구체적인 복사 측정 용어를 쓸 수 있다면 ‘세기’나 ‘밝기’ 같은 모호한 표현은 피하는 편이 좋습니다. 숫자의 절대적인 크기는 그리 중요하지 않으며 실제 SI 단위를 꼭 사용할 필요도 없습니다. 하지만 서로 다른 물리량을 잘못 섞지 않으려면 각 양이 무엇을 측정하는지는 이해해야 합니다.
•
유한한 면적에 걸쳐 모든 방향의 빛을 합한 총 밝기는 복사속으로 측정합니다.
•
한 점에서 모든 방향을 합한 밝기는 복사속 밀도로 측정합니다. 복사조도와 복사출사도는 각각 들어오는 빛과 방출되는 빛의 복사속 밀도입니다. 라디오시티는 반사되었든 방출되었든 표면에서 떠나는 빛의 복사속 밀도입니다.
•
램버트 법칙 때문에, 같은 광선이라도 표면에 비스듬히 들어올 때보다 수직으로 들어올 때 미소 복사조도에 더 크게 기여합니다.
•
광선의 밝기는 복사휘도로 측정합니다. 더 정확하게는 단위 투영 면적당·단위 입체각당 복사속입니다. 투영 면적을 쓰는 이유는 그 광선의 값이 광선 자체의 성질만 나타내고, 측정에 사용하는 표면의 방향에 의존하지 않도록 하기 위해서입니다.
•
올바른 단위를 쓰려는 노력은 실무적인 사정 때문에 어려워집니다. 수치적분은 가중 평균과 비슷해 실제로 일어나는 단위 변화를 감춥니다. 점광원 등 디랙 델타로 표현하는 대상도 혼란을 더합니다.
💡
손전등 하나로 단위 구분하기
같은 손전등 빛을 좁은 종이에 모으거나 넓은 벽에 퍼뜨려 봅시다. 전체 빛의 일률이 같아도, 한 제곱미터가 받는 양은 다릅니다. 그래서 W와 W/m²를 구별합니다. 이제 같은 지점에 같은 총량의 빛이 오더라도 사방에서 오는지, 한 방향에 몰려오는지를 구별하고 싶다면 입체각까지 필요합니다.
flowchart LR
    A["전체 에너지의 흐름<br>복사속 · W"] -->|"면적으로 나눔"| B["표면의 수광 밀도<br>복사조도 · W/m²"]
    B -->|"방향과 투영 면적까지 구별"| C["광선의 복사휘도<br>W/(m²·sr)"]
Mermaid
복사
원문 오타 교정: 인쇄본 355쪽의 ‘watts per meter’는 같은 장 표 10.1과 차원에 맞춰 ‘제곱미터당 와트(W/m²)’로 옮겼습니다. 인쇄본 358쪽 정리의 ‘projected angle’은 앞의 정의와 일치하도록 ‘투영 면적(projected area)’으로 옮겼습니다. 둘 다 내용을 줄인 것이 아니라 명확한 단위 오기를 표시하고 바로잡은 것입니다.
정확한 구분: RGB 채널을 세 개의 단일 파장 그 자체로 받아들이면 안 됩니다. 실제 색채 측정은 스펙트럼에 색 대응 함수를 적용해 얻은 값을 사용합니다. 또한 측광량은 스펙트럼에 시감 효율을 가중하여 합한 물리량이며, 사람이 주관적으로 느끼는 밝기와도 구별됩니다. 원문의 ‘세 파장’과 ‘비선형 변환’ 설명은 입문을 위한 직관으로 읽어야 합니다.
생물학적 일반화: 물고기·파충류·새를 모두 수용기 네 종류로 단정할 수는 없습니다. 종과 환경에 따른 차이가 있습니다. 원문의 비유가 전달하려는 핵심은 ‘인간의 세 색 채널이 빛 자체의 물리 법칙은 아니다’라는 점입니다.

10.1.4 렌더링 방정식

이제 BRDF를 렌더링 알고리즘에 끼워 넣어 봅시다. 10.1절에서 설명한 렌더링 알고리즘의 두 번째 단계에서는 특정 표면에서 눈 방향으로 나가는 복사휘도를 구하려고 합니다. 반사광의 경우에는 어느 방향에서 표면에 도착한 빛이 우리 쪽으로 반사되어야 합니다. BRDF를 배운 덕분에 이제 이를 나타낼 방법이 있습니다.
표면에 빛이 들어올 수 있는 모든 방향을 생각해 봅시다. 점 x\mathbf{x}를 중심으로 하고 그 위치의 표면 법선 n^\hat{\mathbf{n}}에 맞춰 방향을 정한 반구를 이룹니다. 가능한 입사 방향 ω^in\hat{\boldsymbol{\omega}}_{\mathrm{in}}마다 그 방향에서 들어오는 빛의 색을 측정합니다. BRDF는 그 빛 중 흡수되거나 다른 방향으로 흩어지는 대신, 우리 눈 쪽의 ω^out\hat{\boldsymbol{\omega}}_{\mathrm{out}} 방향으로 반사되는 몫을 알려줍니다.
가능한 입사 방향 전체에 대해 눈 쪽으로 반사되는 복사휘도를 더하면, 그 방향으로 눈에 들어오는 총 반사 복사휘도를 얻습니다. 여기에 표면 자체가 우리 쪽으로 방출하는 빛을 더합니다. 대부분의 표면에서 이 방출량은 0입니다. 그러면 총 복사휘도가 됩니다. 이를 수학적으로 쓰면 렌더링 방정식(rendering equation)을 얻습니다.
식 10.1 — 렌더링 방정식
Lout(x,ω^out,λ)=Lemis(x,ω^out,λ)+∫ΩLin(x,ω^in,λ)f(x,ω^in,ω^out,λ)(−ω^in⋅n^) dω^in.\begin{aligned} L_{\mathrm{out}}(\mathbf{x},\hat{\boldsymbol{\omega}}_{\mathrm{out}},\lambda) ={}&L_{\mathrm{emis}}(\mathbf{x},\hat{\boldsymbol{\omega}}_{\mathrm{out}},\lambda)\\ &+\int_{\Omega} L_{\mathrm{in}}(\mathbf{x},\hat{\boldsymbol{\omega}}_{\mathrm{in}},\lambda) f(\mathbf{x},\hat{\boldsymbol{\omega}}_{\mathrm{in}},\hat{\boldsymbol{\omega}}_{\mathrm{out}},\lambda) (-\hat{\boldsymbol{\omega}}_{\mathrm{in}}\cdot\hat{\mathbf{n}}) \,d\hat{\boldsymbol{\omega}}_{\mathrm{in}}. \end{aligned}
식 10.1은 근본적인 식이지만, 그 정립은 비교적 최근의 일입니다. Kajiya가 1986년 SIGGRAPH에서 발표했습니다[원문 참고문헌 37]. 더구나 이 식은 사실적인 영상을 만드는 여러 전략의 출발점이라기보다 그 결과로 나왔습니다. 그래픽스 연구자들은 해결하려는 문제를 설명할 공통 틀이 마련되기 전부터, 저마다 타당하다고 생각한 여러 기법으로 영상 제작을 시도했습니다.
그 뒤로도 여러 해 동안 비디오 게임 업계의 많은 개발자는 자신들이 해결하려던 문제가 마침내 명확하게 정의되었다는 사실을 모르고 있었습니다. 원문은 여전히 모르는 사람도 많다고 덧붙입니다.
이 식을 일상적인 말로 풀어 뜻을 살펴봅시다. 먼저 모든 함수에 x\mathbf{x}와 λ\lambda가 나타난다는 점을 보세요. 방정식 전체는 하나의 표면 위치 x\mathbf{x}에서 하나의 파장, 즉 ‘색 채널’ λ\lambda에 대한 복사휘도 균형을 나타냅니다. 이 균형식은 표면의 모든 점과 각각의 색 채널에 동시에 적용됩니다.
등호 왼쪽의 Lout(x,ω^out,λ)L_{\mathrm{out}}(\mathbf{x},\hat{\boldsymbol{\omega}}_{\mathrm{out}},\lambda)는 단순히 ‘이 점에서 ω^out\hat{\boldsymbol{\omega}}_{\mathrm{out}} 방향으로 나가는 복사휘도’입니다. x\mathbf{x}가 어떤 픽셀에서 보이는 표면 위치이고 출사 방향이 그 점에서 눈을 향한다면, 바로 픽셀의 색을 정하기 위해 필요한 양입니다. 하지만 방정식 자체는 더 일반적입니다. 눈을 향하는지와 관계없이 임의의 위치와 임의의 출사 방향에 대해 나가는 복사휘도를 계산할 수 있습니다.
등호 오른쪽은 두 항의 합입니다. 첫째 항 LemisL_{\mathrm{emis}}는 ‘x\mathbf{x}에서 출사 방향으로 직접 방출되는 복사휘도’이며, 특별한 발광 표면에서만 0이 아닙니다. 두 번째 항인 적분은 ‘x\mathbf{x}에서 출사 방향으로 반사되는 빛’입니다. 전체적으로 보면 다음처럼 당연한 관계를 말합니다.
출사 방향의 총 복사휘도=그 방향으로 방출한 복사휘도+그 방향으로 반사한 복사휘도.\text{출사 방향의 총 복사휘도} =\text{그 방향으로 방출한 복사휘도} +\text{그 방향으로 반사한 복사휘도}.
이제 무시무시해 보이는 적분 안으로 들어가 봅시다. 미적분을 배우지 않았고 11장도 아직 읽지 않았다면, 여기서는 ‘적분’을 ‘합’으로 바꾸어 읽어도 핵심을 놓치지 않습니다. BRDF를 이야기하면서 이미 작동 원리를 설명했지만, 다른 말로 다시 해보겠습니다. 적분 항은 다음 뜻입니다.
출사 방향으로 반사된 복사휘도=∫Ω각 입사 방향에서 들어와 출사 방향으로 반사된 기여량 dω^in.\text{출사 방향으로 반사된 복사휘도} =\int_{\Omega} \text{각 입사 방향에서 들어와 출사 방향으로 반사된 기여량} \,d\hat{\boldsymbol{\omega}}_{\mathrm{in}}.
보통 적분 구간을 쓰는 자리에 그리스어 대문자 오메가 Ω\Omega가 있습니다. ‘가능한 입사 방향으로 이루어진 반구 전체에 대해 더하라’는 뜻입니다. 각 입사 방향마다 그 방향에서 들어와 관심 있는 출사 방향으로 흩어진 복사휘도를 계산합니다. 서로 다른 모든 입사 방향의 기여를 더하면 출사 방향으로 반사되는 총 복사휘도가 됩니다.
입사 방향은 무한히 많기 때문에 적분을 사용합니다. 실무에서는 이를 해석적으로 적분할 수 없어, 유한한 방향을 표본화합니다. 이렇게 하면 적분 기호 ∫\int가 합 기호 ∑\sum로 바뀝니다.
이제 피적분 함수를 분해하는 일만 남았습니다. 세 요인의 곱입니다.
Lin(x,ω^in,λ)⏟입사 복사휘도f(x,ω^in,ω^out,λ)⏟BRDF(−ω^in⋅n^)⏟램버트 인자\underbrace{L_{\mathrm{in}}(\mathbf{x},\hat{\boldsymbol{\omega}}_{\mathrm{in}},\lambda)}_{\text{입사 복사휘도}} \underbrace{f(\mathbf{x},\hat{\boldsymbol{\omega}}_{\mathrm{in}},\hat{\boldsymbol{\omega}}_{\mathrm{out}},\lambda)}_{\text{BRDF}} \underbrace{(-\hat{\boldsymbol{\omega}}_{\mathrm{in}}\cdot\hat{\mathbf{n}})}_{\text{램버트 인자}}
첫 번째 요인은 해당 방향에서 들어오는 복사휘도입니다. 두 번째는 BRDF로, 그 방향에서 들어온 빛이 우리가 관심을 두는 출사 방향으로 얼마나 반사되는지 알려줍니다. 마지막은 램버트 인자(Lambert factor)입니다. 표면에 비스듬히 들어올 때보다 수직으로 들어올 때 단위 표면적당 반사에 이용할 수 있는 빛이 더 많다는 사실을 반영합니다.
n^\hat{\mathbf{n}}은 표면 바깥쪽을 향하는 단위 법선입니다. 내적 −ω^in⋅n^-\hat{\boldsymbol{\omega}}_{\mathrm{in}}\cdot\hat{\mathbf{n}}은 광선이 표면에 수직으로 들어올 때 1로 가장 크고, 표면을 스치듯 들어올수록 0에 가까워집니다. 램버트 인자는 10.6.3절에서 한 번 더 다룹니다.
순수하게 수학적으로 말하면 렌더링 방정식은 적분 방정식입니다. 장면 표면에서의 빛 분포라는 미지의 함수 LoutL_{\mathrm{out}}를, 그 함수 자체가 관련된 적분으로 나타냅니다. 재귀적인 식이라는 점이 처음에는 잘 드러나지 않을 수 있지만, 실제로 LoutL_{\mathrm{out}}은 등호 양쪽에 모두 나타납니다.
오른쪽에서는 LinL_{\mathrm{in}}을 구하는 과정에 들어 있습니다. 이 입사 복사휘도는 처음에 각 픽셀에 대해 풀려고 했던 질문, 즉 ‘특정 방향에서 한 점에 도착하는 복사휘도는 얼마인가?’와 정확히 같은 문제입니다.
점 x\mathbf{x}에서 나가는 복사휘도를 구하려면, 모든 방향에서 그 점으로 들어오는 복사휘도를 알아야 합니다. 그런데 그 점에 들어오는 빛은, 그 점에서 보이는 다른 표면들이 그 점을 향해 내보내는 빛과 같습니다.
장면을 사실적으로 렌더링하려면 렌더링 방정식을 풀어야 합니다. 이론적으로는 카메라에 도착하는 복사휘도뿐 아니라 장면의 모든 점에서 모든 방향으로 분포하는 복사휘도 전체를 알아야 합니다. 표면 위치의 집합과 가능한 입사·출사 방향의 집합이 모두 무한하므로, 유한한 디지털 컴퓨터에 완전한 해를 요구할 수는 없습니다. 디지털 영상 합성 소프트웨어를 만드는 진짜 기술은 제한된 계산 시간과 메모리를 가장 효율적으로 배분하여, 가능한 한 좋은 근사를 얻는 데 있습니다.
10.10절에서 제시할 단순한 렌더링 파이프라인은 직접광만 고려합니다. 한 표면에서 반사되어 다른 표면으로 도달하는 간접광은 고려하지 않습니다. 다시 말해 렌더링 방정식의 재귀를 ‘한 단계’만 수행하는 셈입니다. 사실적인 영상에서 매우 중요한 요소는 간접광을 포함하는 것, 즉 렌더링 방정식을 더 충실하게 푸는 것입니다. 이를 위한 여러 방법을 전역 조명(global illumination) 기법이라고 부릅니다.
이것으로 그래픽스가 어떻게 작동하는지에 대한 전체 원리에 관한 설명을 마칩니다. 아직 실용적인 아이디어를 하나도 제시하지 않았다는 점은 인정합니다. 하지만 무엇을 근사하려는지 이해하고 나서 근사를 시작하는 것이 매우 중요하다고 생각합니다. 실시간 처리를 위해 감수하는 절충은 상당히 크지만, 사용할 수 있는 계산 능력은 계속 증가합니다.
OpenGL 튜토리얼이나 그래픽 카드 업체의 데모, 실시간 렌더링에만 집중한 책으로만 그래픽스를 접한 게임 프로그래머는 미래의 전역 조명 기법은 물론이고 집필 당시의 전역 조명 기법을 이해하는 데도 더 큰 어려움을 겪을 것입니다.
💡
‘들어온 빛’은 다른 물체의 ‘나간 빛’
햇빛이 빨간 벽을 비추고, 그 벽에서 반사된 빛이 흰 공을 비추는 장면을 떠올려 보세요. 공의 색을 계산하려면 공에 들어오는 빛을 알아야 합니다. 그중 일부는 벽에서 나온 빛입니다. 벽에서 나오는 빛을 구하려면 다시 벽에 들어온 햇빛을 알아야 합니다. 이것이 식이 재귀적인 이유입니다.
flowchart LR
    S["광원의 방출광"] --> W["벽에서 반사"]
    W --> B["공에 입사"]
    B --> C["공에서 반사"]
    C --> E["눈 또는 카메라"]
Mermaid
복사
부호 규약: 이 원문에서 입사 방향 벡터는 빛이 진행하여 표면으로 들어오는 방향입니다. 바깥쪽 법선과 반대쪽을 향하므로 램버트 인자에 마이너스가 붙습니다. 표면에서 광원 쪽으로 향하는 벡터를 쓰는 다른 자료에서는 같은 기하 관계가 플러스 내적으로 나타납니다. 수식의 기호만 복사하기 전에 벡터가 어느 쪽을 향하는지 확인하세요.
합으로 근사할 때: 방향을 몇 개 골라 함수값을 더하는 것만으로 적분이 완성되지는 않습니다. 표본이 대표하는 입체각이나, 무작위 표본을 골랐다면 그 확률 밀도를 반영한 가중치가 필요합니다. 단순히 표본 수를 늘릴수록 화면이 무조건 밝아진다면 이 가중치를 빠뜨렸는지 확인해야 합니다.

보충 설명 참고 자료

복사 측정 단위·투영 면적과 BRDF 용어는 PBRT 4판: Radiometry 및 BSDF Representation을 참고하여 교정 설명을 구분해 덧붙였습니다.
BSSRDF 용어와 표면 아래 빛 전달에 관한 보충 설명은 PBRT 4판: Surface Reflection에서도 확인할 수 있습니다.