3D 그래픽스에서 광원은 단순히 물체를 보이게 만들어주는 역할에 그치지 않는다. 우리가 살아가는 물리 공간에서 그러하듯이 광원은 물체의 색을 결정하는 중요한 요소이다. 광원을 어떻게 설정하느냐에 따라 물체가 색을 지니게 되고, 그 색에 따라 물체 표면의 색이 결정된다. 지금부터 3D 그래픽스에서 사용되는 광원 모델과 DirectX9에서 이 광원을 사용하는 방법에 대해서 알아보겠다.
Local Illumination Model
현실의 물리 공간은 빛이 계속적으로 반사하여, 셀 수 없이 수많은 빛이 합해진 결과로 물체의 색상이 결정된다. 우리가 당연하게 생각하고 살아가는 공간 속에 물체의 색은 이렇게 결정된다. 아래의 그림은 물리 공간에서 빛이 반사되어 색이 결정되는 모델을 흉내내어 그래픽 처리한 결과이다.
붉은 벽과 푸른 벽에 빛이 반사되고, 이 색이 흰 색 구의 표면에 비치게 된다. 그래서 구면이 은은하게 붉은 색과 푸른 색을 띈다. 현실과 가장 유사하게 표현할 수 있다는 장점을 지닌 이런 광원 모델이 바로 Global Illumination Model이다. 하지만 Global Illumination Model은 치명적인 단점이 있다. 연산량이 지나치게 많다는 점이다. 광원으로부터 나온 빛이 끊임없이 반사되어 물체의 재질과 상호작용하는 모든 과정을 연산하는 것은 심각한 성능 저하를 발생시킨다. 그래서 반사되는 횟수를 제한하여 Global Illumination Model의 성능 회적화를 꾀하기도 한다.
하지만 게임과 같은 Realtime Rendering 환경에서 일반적으로 Local Illumination Model을 사용한다. Local Illumination Model은 성능을 향상시키기 위해서 Global Illumination Model처럼 복잡한 연산 과정을 거치는 대신에, 이 과정을 간소화하여 표현한 모델이다. Local Illumination Model 중 Phong Reflection Model을 예로 들어 살펴보자.
Phong Illumination Model
주변광(Ambient Light)
Phong Reflection Model은 세 개의 항으로 이루어져있다. Ambient, Diffuse, Specular 세 개의 항은 바로 그것들이다. Ambient 항은 주변광을 의미한다. 주변광이란 광원의 위치와 무관하게 똑같은 양으로 모든 점에 반사되는 색을 의미한다. 실제 물리 공간에서는 빛에 직접 노출되지 않는 곳도 눈으로 볼 수 있다. 이것이 가능한 이유는 물체 면에 반사된 빛이 다른 물체면에 반사되어, 이런 과정이 반복적으로 이뤄지다보면 빛에 직접 노출되지 않는 면에도 빛이 도달하게 된다. 하지만 이런 과정을 컴퓨터로 연산하고 시뮬레이션하기는 쉽지 않다. 그래서 Phong Reflection Model에서는 이런 형태의 반사를 연산하지 않고, 시점의 위치와는 무관하게 모든 물체면에 대해서 일정하게 빛이 비춰진다고 설정한다. 위 그림 가장 왼쪽에 보이는 Ambient를 살펴보자. 주변광은 거리와 상관없이 모든 물체면에 빛이 일정하다 비친다고 하였다. 그래서 물체의 굴곡에 상관없이 일정한 밝기의 빛이 비춰지므로 주변광만 비춰진다면 모든 물체는 동일한 색을 띄게 된다. 주목할 사실은 주변광은 모든 물체면에 동일하게 비춰지기 때문에 주변광만으로는 입체감을 전혀 느낄 수 없다는 점이다. 주변광을 수식으로 표현하면 다음과 같다.
K는 주변광 계수를 나타내고, L은 주변광에 관해서 물체면에 입사되는 입사광의 세기를 나타낸다. K를 증가시키면 물체의 모든 면이 동일하게 밝아진다.
확산광(Diffuse Light)
이제 Diffuse 항에 대해서 알아보자. Diffuse는 확산광을 의미한다. 먼저 아래의 그림을 보도록하자.
L은 광원을 나타내는 벡터이고, R은 표면에 반사한 빛을 나타내는 벡터이다. 표면에 비치닌 빛의 세기는 무엇에 영향을 받을까? L과 N이 이루는 각도에 영향을 받는다. 이 각도가 작으면 작을수록 표면에 도달하는 빛의 세기는 강해진다. 정오에 태양빛이 가장 뜨겁게 느껴지는 것과 같은 원리이다. 이를 수식으로 근사화하여 표현할 수 있는데, 좋은 모델이 될 수 있는 것이 바로 코사인 함수이다.
코사인 함수에서 볼 수 있듯이 L과 N이 이루는 각도가 0일 경우 1, 90도 일 경우 0이 된다. 빛의 세기를 표현하는 모델에 대한 한트를 얻었으니 확산광을 나타내는 수식을 살펴보자.
L과 N을 정규화한 벡터가 각각 l과 n이라면, l과 n을 내적한 결과는 코사인 값이 된다. 주변광과 마찬가지로 K는 확산광 계수, L은 확산광에 관해서 물체면에 입사되는 입사광의 세기를 나타낸다.
반사광(Specular Light)
반사광은 우리가 흔히 하이라이트라고 말하는 현상을 표현한다. 당구공처럼 매끈한 물체의 표면에 빛을 비추면 물체의 표면색과는 상관없이 반짝이는 현상을 확인할 수 있다. 이를 하이라이트라 부른다. 반사광은 이런 하이라이트를 표시하는 빛이다. 먼저 어떤 경우 반사광을 확인할 수 있는지 알아보자.
반사광은 확산광의 방향과 이를 바라보는 시점의 방향이 일치하면 확인할 수 있다. 위의 그림에서 세타 값이 0에 가까울수록 반사광의 세기는 강해진다. 이는 확산광을 표현하는 것과 유사한 모델을 적용할 수 있다는 생각이 든다. 각도의 크기가 0인 경우 반사광의 세기는 1, 각도가 커지면 반사광의 세기가 점점 작아진다를 사실을 코사인 함수로 표현할 수 있다.
r은 표면에 반사된 빛의 방향을 나타내는 벡터를 정규화한 것이고, v는 시점의 위치를 정규화한 벡터이다. r과 v를 내적하면 코사인 값만 남게 된다. 결국 우리가 표현하고자 했던 반사광을 수식으로 잘 나타낼 수 있음을 확인할 수 있다.
위의 수식에서 알파 값이 의미하는 것은 하이라이트의 크기이다. r과 v를 내적한 값은 0에서 1 사이 값을 지니게 된다. 알파 값이 커질 수록 결국 빛의 세기는 점점 약해진다. 이를 코사인 그래프로 확인하면 다음과 같다.
알파 값이 커지면 커질수록 하이라이트의 크기는 작아지게 된다. 이 알파값을 광택 계수(Shineness Coefficient)라고 부른다.
완성된 Phong Reflection Model
주변광, 확산광, 반사광을 합한 결과가 바로 Phong Reflection Model의 결과이다.
이 모델은 광원의 특성에 해당하는 I 값들, 물체 특성을 나타내는 K 값들(반사 계수)을 정해지면, 그에 따른 결과가 나온다. 그리고 I 값과 K 값은 R, G, B로 세분화되어 표현된다.
DirectX9의 광원 사용
DirectX9에서 광원을 사용할 때는 지금까지 설명한 Local Illumination Model과 같은 복잡한 과정을 거칠 필요없이 프레임워크에서 제공하는 재질과 광원만 설정해주면 손쉽게 사용할 수 있다. 하지만 DirectX9에서 사용하는 광원 모델은 고정된 파이프라인을 사용할 때만 유효하고, 셰이더를 사용하게 되면 쓸모없게 된다고 한다. 그러니 알아두도록 하자.
다시 DirectX9로 돌아와서 재질에 대해서 알아보도록 하자. 재질은 물체의 표면 상태를 말하는 것으로, 빛이 재질에 반사되어 변화되는 과정을 계산하기 위해 설정하는 값이다. 재질의 종류에는 네 가지가 있다.
- 주변색(Ambient): 광원의 위치와 무관하게 똑같은 양으로 모든 점에서 반사되는 색
- 확산색(Diffuse): 광원에 반사될 때 출력되는 가장 주된 색
- 반사색(specular): 특정한 방향으로만 반사되는 색, 광원의 위치와 카메라의 위치에 따라 달라진다.
- 방출색(emissive): 메시 표면에서 자체적으로 방출되는 색(이 색이 다른 메시에 영향을 주지는 못한다)
재질을 설정하는 코드는 다음과 같다.
재질 설정이 끝나면 광원을 설정한다. DirectX9에서 광원은 네 종류가 있다.
- 주변 광원(Ambient Light): 3차원 공간 내에서 메시의 배치나 위치와는 전혀 상관없이 똑같은 양으로 모든 곳을 비추는 빛의 강도(방향, 위치를 가지지 않으며 색과 강도만을 가진다)
- 점 광원(Point Light): 백열전구와 같은 빛이다. 광원의 위치에 따라 빛의 강도가 달라진다.
- 방향성 광원(Directional Light): 태양과 같이 하나의 방향으로 비춰지는 빛이다. 광원의 위치는 상관없고, 방향이 가장 중요한 요소이다.
- 점적광원(spot Light): 정해진 위치와 범위에만 비추는 특수한 조명이다. 무대 조명을 생각하면 이해하기 편하다.
광원을 설정하는 코드는 다음과 같다.
원통을 빙글빙글 도는 방향성 광원
정리하면
- 재질은 메시(혹은 물체)의 표면 상태를 의미하는 것으로 빛이 물체의 표면에서 반사되어 변화되는 과정을 수학적으로 모델링하기 위해 사용하는 값들이다.
- DirectX9에서는 재질과 광원을 설정하며 물체에 작용하는 빛을 표현한다.