Post

[OpenGL ES를 이용한 3차원 컴퓨터 그래픽스 입문] 9. 라이팅

빛과 물체의 상호작용을 디퓨즈/스페큘러/앰비언트/발산광 네 항으로 계산하는 퐁 모델과, 이를 구현하는 쉐이더 구성까지 정리했습니다.

[OpenGL ES를 이용한 3차원 컴퓨터 그래픽스 입문] 9. 라이팅

개요


라이팅(lighting 혹은 illumination)은 빛과 물체 간 상호작용을 처리하는 기술이다. 이 장에서는 컴퓨터 그래픽스 분야의 선구적 연구자 “퐁”이 제안한 라이팅 기법(이를 퐁 모델이라 칭한다)을 소개하고, 이것이 어떻게 쉐이더로 구현되는지 설명할 것이다. 한편 이 책의 2부 16장에서는 퐁 모델의 문제점을 논의한 후, 이와는 판이하게 다른 라이팅 기법인 광선 추적래디오시티 알고리즘을 소개할 것이다.


9.1 퐁 모델


라이팅을 위해서는 우선 광원(light source)을 정의해야 한다. 간단한 광원 중 하나는 점 광원(point light source)으로, 이는 3차원 공간의 한 점으로부터 전방위로 빛이 발산되는 것을 말한다. 한편, 점 광원으로부터 멀리 떨어진 물체일수록 빛을 덜 받게 되는데, 이는 빛이 물체까지 이동하는 동안 점차 희석되기 때문이다.

한편, 매우 강력한 광원이 아주 멀리 존재할 경우를 생각해 보자. 태양이 좋은 예인데, 햇빛을 받는 지상의 가상 물체를 렌더링한다면, 이 물체 표면의 여러 점에 입사하는 햇빛의 방향은 서로 평행하다고 가정해도 무리가 없다. 이런 광원을 방향성 광원(directional light source)이라고 부른다. 또한, 물체 표면의 각 점들로부터 태양까지의 거리는 다르겠지만, 태양이 아주 멀리 떨어져 있으므로 그 차이는 무시할만하다. 따라서 방향성 광원을 다룰 때에는, 광원의 색상과 단일한 입사 방향만 고려하면 된다. 이 장에서는 방향성 광원을 사용하여 퐁 모델을 기술할 것이다.

물체를 라이팅하기 위해서는 물체 표면으로 들어오는 빛(irradiance)과 카메라를 향해 나가는 빛(radiance) 사이의 관계를 이른바 BRDF(Bidirectional Reflectance Distribution Function; 양방향 반사율 분포 함수)로 정의해야 한다. 퐁 모델은 실시간 렌더링을 위해서 이 BRDF를 극단적으로 단순화했다. 퐁 모델은 물체 표면에 감지되는 색상을 디퓨즈(diffuse), 스페큘러(specular), 앰비언트(ambient) 반사와 발산광(emissive light) 네 가지 항목으로 분리해서 처리한다. 디퓨즈 및 스페큘러 항은 광원으로부터 물체 표면에 직접 들어오는 빛 즉 직접 조명 을 다루는 반면, 앰비언트 항은 다른 물체가 반사하는 빛 즉 간접 조명을 다룬다. 한편 발산광은 물체 스스로 빛을 발산하는 경우에 사용된다. 그림 9.1은 이 네 가지 항과 이를 결합한 결과를 보여준다. 이제부터 퐁 모델의 네 가지 항을 차례차례 살펴보도록 하자.

img 그림 9.1. 물체 표면의 p점에 들어오는 빛은 파란색 화살표로, 반사되는 빛은 및은 주황색 화살표로, 카메라에 도달하는 빛은 빨간색 화살표로 나타내었다.


9.1.1. 디퓨즈 항 - 난반사

디퓨즈 항은 램버트의 법칙(Lambert’s law)에 따라 정의된다. 즉 램버시안 표면(Lambertian surface) 혹은 디퓨즈 표면이라 불리는 이상적은 표면으로 들어온 빛은 그림 9.1.a에 보인 바와 같이 모든 방향을 따라 같은 강도로 반사된다. 이를 난반사라 하는데, 카메라에 의해 감지되는 빛은 카메라의 시선에 무관하며 오로지 물체 표면에 들어오는 빛의 양에 비례하게 된다.

물체 표면으로 들어오는 빛의 방향은 이른바 빛 벡터(light vector)에 의해 정의된다. 그런데, 방향성 광원을 사용한다면, 라이팅을 수행할 장면의 모든 지점은 동일한 빛 벡터를 가진다. (만약 점 광원을 사용한다면, 빛 벡터는 각 표면 점마다 변할 것이다. 또한, 물체 표면의 한 점에 들어오는 빛의 양 계산에 있어 그 점과 광원과의 거리도 고려해야 한다. 그 거리에 비례해서 빛이 희석되기 때문이다.) 그림 9.2.a에서 빛 벡터는 l로 표기되었는데, 계산 상 편의를 위해 실제 빛이 들어오는 방향과 반대로 정의되어 있다. 한편, 물체 표면의 점 p의 노멀 n과 빛 벡터 l 사이의 각도 $\theta$를 입사각(incident angle)이라고 하는데, 세타가 작을수록 p는 더 많은 빛을 받는다. n과 l이 정규화되어 단위 벡터로 표현되어 있다면, n과 l의 내적을 사용해서 p에 들어오는 빛의 양을 결정할 수 있다.

\[n \cdot l = ||n|| ||l|| cos \theta = cos \theta \tag{9.1}\]

그림 9.2.b에 보인 것처럼, 세타 = 0도일 경우, 즉 n과 l이 같다면, n $\cdot$ l = 1이 되어 p는 최대 빛을 받는다. 반면, 그림 9.2.c에 보인 것처럼, 세타가 90도일 경우, n $\cdot$ l = 0이 되어 p는 빛을 받지 않는다. 마지막으로, 그림 9.2.d와 같이 세타가 90도보다 크다면 p는 빛을 받지 않는다. 그러나 이 경우에 식 (9.1)의 n $\cdot$ l은 음수가 된다. 이 문제를 해결하기 위해서 식 (9.1)을 다음과 같이 확장한다.

\[max(n \cdot l, 0) \tag{9.2}\]

위 식은 n $\cdot$ l이 음수가 되는 경우 0을 선택하여 p에 들어오는 빛의 양을 0으로 만든다.

그런데, 식 (9.2)의 $max(n \cdot l, 0)$은 p에 들어오는 빛의 ‘강도’만을 결정한다. 반사되는 빛의 ‘색상’은 다음과 같이 정의된다.

\[s_d \otimes m_d \tag{9.3}\]

여기에서 $s_d$는 RGB 색상을, $m_d$는 물체의 디퓨즈 계수(diffuse reflectance)를 나타낸다(우리의 표기법에서 s는 광원을, m은 재질을 의미한다). 예를 들어, 노란색 광원이라면 $s_d$는 (1,1,0)이다. 만약 $m_d$가 (1,1,1)이라면, $s_d$와 $m_d$의 같은 원소 간 곱셈으로 정의되는 $s_d \otimes m_d$는 (1,1,0)이 된다. 이는 노란색이 그대로 반사됨을 의미한다. 만약 $m_d$가 (1,0,1)이라면, $s_d \otimes m_d$는 (1,0,0)이 되는데, 이는 광원의 RGB 색상 중 G 요소는 물체에 의해 흡수되고 오직 R 요소만이 반사됨을 의미한다.

퐁 모델의 디퓨즈 항은 식 (9.2)와 (9.3)을 결합하여 다음과 같이 정의된다.

\[max(n \cdot l, 0) s_d \otimes m_d \tag{9.4}\]

그림 9.1.a의 주전자는 디퓨즈 항에 의해서만 렌더링되었다.


9.1.2 스페큘러 항 - 정반사

img 그림 9.3. 스페큘러 반사. (a) 반사 벡터와 시선 벡터는 각각 r과 v로 표기된다. (b) r을 중심으로 한 원뿔 안에 v가 놓이게 되면 카메라는 p에서 하이라이트를 볼 수 있다.

퐁 모델의 스페큘러 항은 물체 표면에 하이라이트를 만드는 데 사용된다. 이를 위해서는 시선 벡터(view vector)와 반사 벡터(reflection vector)가 필요하다. 그림 9.3.a에 보인 바와 같이 시선 벡터는 물체 표면의 점 p와 카메라를 연결하는 것으로 v로 표기된다. 빛 벡터 l과 마찬가지로 v 역시 실제 카메라 시선과 반대 방향으로 정의된다.

img 그림 9.4. 반사 벡터 계산.

한편, p에 들어온 빛이 입사각 세타와 동일한 각도를 이루며 반사되는 것을 정반사라 하는데, 이 방향을 따른 벡터가 반사 벡터이며 r로 표기한다. 이를 계산해 보자. 그림 9.4에서 n과 l이 이루는 입사각 세타는 n과 r이 이루는 반사각과 같다. 그림에서 두 직각 삼각형은 벡터 $ncos\theta$로 표현된 변을 공유한다. 왼쪽 삼각형의 l과 $ncos\theta$를 연결하는 벡터를 s로 표기하자.

\[s = n cos \theta - l \tag{9.5}\]

오른쪽 삼각형에서도 역시 s를 정의될 수 있는데 이는 아래와 같다.

\[s = r - n cos \theta \tag{9.6}\]

식 (9.5)와 식 (9.6)을 이용하여 다음과 같이 r을 계산할 수 있다.

\[r = 2ncos \theta - l \tag{9.7}\]

n과 l은 단위 벡터이고 $n \cdot l = cos \theta$이므로 r은 다음과 같이 바꿔 쓸 수 있다.

\[r = 2n (n \cdot l ) - l \tag{9.8}\]

l이 단위 벡터이므로 r 역시 단위 벡터가 된다.

그림 9.3.a로 돌아가서 r과 v 사이의 각 p를 생각해보자. 완벽하게 매끄러운 표면이라면 p에서의 하이라이트는 p = 0일 경우에만 즉 r과 v가 일치할 경우에만 카메라에 포착될 것이다. 그런데 완벽하게 매끄러운 표면이 아닌 경우, p가 정확히 0이 아니더라도 0에 가깝다면 카메라는 하이라이트를 볼 수 있다. 반사광이 퍼지기 때문이다. 즉, p = 0일 때 최대의 하이라이트를 보게 되고, p가 커짐에 따라 하이라이트의 밝기는 빠르게 감소할 것이다. 하이라이트를 볼 수 있는 영역은 그림 9.3.b에 보인 바와 같이 r을 중심으로 한 원뿔 모양으로 묘사할 수 있다. 만약 v가 원뿔 안에 놓이면 카메라는 하이라이트를 볼 수 있다. 원뿔 속에서 하이라이트가 감소되는 정도는 다음과 같이 근사적으로 계산된다.

\[(r \cdot v)^{sh} \tag{9.9}\]

여기에서 sh는 shininess의 앞 글자로 표면의 매끈함의 정도를 나타낸다. r과 v가 같으면 sh값에 관계없이 $(r \cdot v)^{sh}$ = 1이 되고 최대의 하이라이트가 카메라에 보인다. 하지만 r과 v가 다르면 sh가 커질수록 하이라이트는 급격히 감소하게 된다.

퐁 모델의 스페큘러 항은 다음과 같이 정의된다.

\[(max(r \cdot v, 0))^{sh} s_s \otimes m_s \tag{9.10}\]

여기에서 $s_s$는 광원의 색상이고, $m_s$는 물체의 스페큘러 계수(specular reflectance)이다. 디퓨즈 항과 마찬가지 이유로 max 함수가 필요하다. 일반적으로 $s_s$는 식 (9.4)에 사용된 $s_d$와 동일한 값을 가진다. 하지만, 식 (9.4)의 $m_d$와 달리 $m_s$는 (0.9,0.9,0.9), (0.8,0.8,0.8) 등과 같은 회색조(gray-scale)로 표현되는데, 이는 물체 표면의 하이라이트가 광원의 색을 반영하도록 하기 위함이다. 예를 들어 빨간색의 금속성 물체에 흰색 광원이 비치는 경우를 상상해 보자. 물체 표면이 빨간색이더라도 하이라이트 영역은 흰색으로 빛날 것이다. 따라서 $m_s$는 회색조로 설정되어. $s_s$가 반사되는 정도를 조절하게 된다. 그림 9.1.b의 주전자는 스페큘러 항에 의해서만 렌더링되었다.


9.1.3. 앰비언트 항

공간 내 다양한 물체로부터 반사된 빛을 앰비언트 빛(ambient light)이라 부르는데, 이는 간접 조명에 해당한다. 앰비언트 빛은 장면의 모든 지점에서 반사된 빛이 어우러진 것이므로 어떤 특정한 방향이 아닌 ‘모든 방향을 따라’ p점에 들어온다. 따라서 이는 p에서 ‘모든 방향을 따라’ 반사된다. 결국 p에 들어오는 앰비언트 빛의 양은 p의 노멀에 무관하고, p에서 반사되는 빛의 양은 카메라 시선에 무관하다. 따라서 앰비언트 반사는 다음과 같이 간단하게 정의된다.

\[s_a \otimes m_a \tag{9.11}\]

여기에서 $s_a$는 앰비언트 빛의 RGB 색상이고, $m_a$는 앰비언트 계수(ambient reflectance)이다. 그림 9.1.c의 주전자는 앰비언트 항에 의해서만 렌더링되었다. 이는 2차원 물체처럼 보이는데, 표면 노멀 및 카메라 시선에 무관한 식 (9.11)로는 주전자 표면에 음영 차이를 만들 수 없기 때문이다.

간접 조명을 표현하는 앰비언트 항 덕분에 우리는 광원으로부터의 빛이 직접 닿지 않는 부분에도 조명 효과를 줄 수 있게 된다. 예를 들어, 그림 9.1.a와 9.1.b를 보면 직접 조명을 받지 않는 주전자 오른쪽 아래 부분은 완벽한 검은색임을 알 수 있다. 하지만, 그림 9.1.c에서 이 부분은 주전자의 다른 부분과 마찬가지로 약간의 조명을 받는다. 하지만, 식 (9.11)은 실세계 간접 조명의 디테일을 잡아내기에는 너무 단순화되어 있다. 우리는 16.4절에서 보다 세련된 앰비언트 반사 기법을 배울 것이다.


9.1.4. 발산광

퐁 모델의 발산광 항은 물체 자신이 빛을 발산하는 경우에 사용된다. 이 RGB 색상은 $m_e$로 표기된다. 그림 9.1.d의 주전자는 발산광 항에 의해서만 렌더링되었다(이 예에서 주전자는 사실 발산광을 거의 내지 않는다). 앰비언트 항의 경우와 마찬가지 이유로, 그 결과는 2차원처럼 보인다. 한편, 퐁 모델은 발산광을 가진 물체를 광원으로 취급하지 않는다. 따라서 같은 공간의 다른 물체를 라이팅하는 데 기여하지 못한다. 이것은 퐁 모델의 명백한 한계 중 하나이다.

퐁 모델은 이상의 네 개 항을 더하여 다음과 같이 정의된다.

\[max(n \cdot l, 0) s_d \otimes m_d + (max(r \cdot v, 0))^{sh} s_s \otimes m_s + s_a \otimes m_a + m_e \tag{9.12}\]

그림 9.1.e는 네 개의 항에서 산출된 RGB 값들을 산술적으로 더한 결과를 보여준다. 빛을 발산하지 않는 물체의 경우, 발산광 $m_e$를 삭제하면 된다. 만약 물체가 램버시안 표면에 가깝다면 $m_d$를 크게, $m_s$를 작게 설정한다. 반면, 반짝이는 금속성 물체를 표현하기 위해서는 $m_s$를 크게 설정한다.


9.2 퐁 라이팅을 위한 쉐이더


img 그림 9.5. 라이팅 계산에 필요한 벡터들.

이 절은 퐁 라이팅 구현을 위한 정점 쉐이더 및 프래그먼트 쉐이더를 소개한다. 그림 9.5는 한 물체 표면의 두 점을 보여주는데, 한 점마다 하나의 프래그먼트가 생성된다고 가정해보자. 그러면 프래그먼트 쉐이더는 각 점마다 식 (9.12)를 이용해 라이팅을 수행할 것이다. 이를 위해서는 빛 벡터 l, 노멀 n, 반사 벡터 r, 시선 벡터 v가 필요하다. 이 장에서는 방향성 광원만을 다루므로 그림 9.5의 두 점에서 l은 동일한 방향을 가진다. 따라서 이는 프래그먼트 쉐이더에게 유니폼으로 제공된다. 반면, 나머지 n, r, v는 그림 9.5의 두 점에서 모두 다른데, 프래그먼트 쉐이더에게 실제로 입력되는 것은 n과 v이다. 그러면 프래그먼트 쉐이더는 식 (9.8)을 이용해 r을 계산한 후, 최종적으로 식 (9.12)를 구현한다.

광원이 월드 공간에 있으므로 빛 벡터 l은 월드 공간에서 정의된다. 따라서, 퐁 모델 디퓨즈 항에서 l과 결합될 n 역시 월드 공간 벡터여야 한다. 이를 위해 정점 쉐이더는 오브젝트 공간에서 정의된 정점 노멀을 월드 공간으로 변환한 뒤 이를 래스터라이저에게 넘겨줄 것이다. 래스터라이저는 이를 보간하여 각 프래그먼트마다 월드 공간 노멀 n을 할당할 것이다. 그림 9.6.a는 구를 표현하는 저해상도 메시인데, 두 정점 $p_1$과 $p_2$를 보자. 그림 9.6.b는 이 구의 단면인데, $p_1$과 $p_2$ 각각의 월드 공간 노멀인 $n_1$과 $n_2$를 보여준다. 한편, $p_1$과 $p_2$를 잇는 선분 상의 두 점 a와 b가 각각 프래그먼트를 생성한다고 가정하자. 래스터라이저는 $n_1$과 $n_2$를 보간하여 a의 노멀 $n_a$와 b의 노멀 $n_b$를 계산할 것이다.

img 그림 9.6.a. 프래그먼트별 라이팅. 구를 표현하는 저해상도 메시의 두 정점.

img 그림 9.6.b. 프래그먼트별 라이팅. 노멀 보간.

img 그림 9.6.c. 프래그먼트별 라이팅. 시선 벡터 보간.

img 그림 9.6.d와 e. 프래그먼트별 라이팅. (d) 라이팅 계산에 참여하는 프래그먼트별 벡터. (e) 텍스처링 및 라이팅 결과.

두 프래그먼트 a와 b는 시선 벡터를 필요로 한다. 이를 각각 $v_a$와 $v_b$로 표기하자. 이들도 월드 공간에서 정의되어야 한다. 이를 위해 정점 쉐이더는 각 정점의 오브젝트 공간 좌표를 월드 공간으로 변환한 후 이를 카메라(EYE)와 연결하여, 그림 9.6.c에 보인 것처럼 정점의 월드 공간 시선 벡터 $v_1$과 $v_2$를 계산한다. 래스터라이저는 이들을 보간하여 프래그먼트 별 월드 공간 시선 벡터 $v_a$와 $v_b$를 계산한다.

이렇게 해서, 라이팅 계산을 담당할 프래그먼트 쉐이더가 필요로 하는 데이터는 모두 준비되었다. 즉, n과 v는 래스터라이저가 제공하고, l은 GL 프로그램이 유니폼으로 제공한다. 이런 입력이 들어오면 프래그먼트 쉐이더는 우선 식 (9.8)을 이용해 r을 계산한 후, 최종적으로 식 (9.12)를 구현한다. 프래그먼트 쉐이더가 식 (9.12) 구현을 위해 사용하는 l, n, r, v는 모두 월드 공간 벡터임을 다시 상기하자. 스크린 공간 프래그먼트의 색상 계산을 위하여 월드 공간 데이터를 이용하는 것이다.

그림 9.6의 구가 금속성의 매끄러운 표면을 가졌다고 가정하자. 그림 9.6.d는 a와 b에서의 스페큘러 반사를 비교한다. a와 b는 동일한 l을 가진다. 한편, a의 경우, 반사 벡터 $r_a$와 시선 벡터 $v_a$ 사이의 각도가 크다. 따라서, 카메라는 a에서 하이라이트를 거의 보지 못할 것이다. 반면, b의 경우 반사 벡터 $r_b$와 시선 벡터 $v_b$가 일치하므로, 카메라는 b에서 강력한 하이라이틀르 볼 것이다. 그림 9.6.e는 퐁 모델로 라이팅을 수행한 결과를 보여준다. 물론 텍스처링도 이뤄졌다.


참고

This post is licensed under CC BY 4.0 by the author.