Post

[OpenGL ES를 이용한 3차원 컴퓨터 그래픽스 입문] 15. 쉐도우 매핑

광원에서 본 깊이를 담은 쉐도우맵으로 그림자를 판정하는 두 단계 렌더링과, 바이어스 설정, PCF 필터링, 하드/소프트 쉐도우를 정리했습니다.

[OpenGL ES를 이용한 3차원 컴퓨터 그래픽스 입문] 15. 쉐도우 매핑

개요


실세계에서 그림자가 없는 장면을 찾기는 어렵다. 따라서 렌더링된 영상의 시각적 사실감을 높이는 데 있어 그림자는 필수불가결한 항목이다. 또한 그림자는 물체들 사이의 공간적 관계를 이해하는 데도 도움을 준다. 그림 15.1.a에서 캐릭터와 지면 간 상대적인 위치는 명확하지 않은 반면, 그림 15.1.b에서는 캐릭터가 지면에 착지하는 중임을 쉽게 알아낼 수 있다.

img 그림 15.1. 그림자는 3차원 장면의 구조를 이해하는데 도움을 준다. (a) 캐릭터와 지면의 공간적 관계가 불명확하다. (b) 캐릭터와 지면의 공간적 관계가 명확하다.


15.1 두 단계 렌더링


img 그림 15.2. 쉐도우 매핑을 위한 두 단계 알고리즘. (a) 첫 번째 패스는 쉐도우맵을 생성한다. (b) 두 번째 패스는 3차원 장면의 점이 광원에서 보이는지 검사하기 위해 쉐도우맵을 사용한다.

쉐도우 매핑 알고리즘은 두 번의 렌더링 패스(rendering pass)를 통해 수행된다. 첫 번째 패스에서는 쉐도우맵(shadow map)이라는 특수한 텍스처를 생성한다. 그림 15.2.a를 보자. 광원에서 나온 빛이 미치는 표면은 굵은 선으로 표시되었다. 이들 표면을 균일하게 샘플하여, 각 샘플점 p마다 광원까지의 거리를 쉐도우맵에 저장한다. 이 거리를 z로 표기하는데, 이는 광원에서 본 3차원 장면의 깊이다. 따라서, 쉐도우맵은 광원 기준의 깊이맵(depth map)이라고도 한다.

두 번째 패스에서는 실제 렌더링을 수행하는데, 이 과정에서 쉐도우맵을 사용하여 그림자를 생성한다. 그림 15.2.b에서 프래그먼트 f1을 처리하는 경우를 보자. 이 프래그먼트에 해당하는 월드 공간의 점을 q1이라 하자. 광원과 q1 사이의 거리 d1은 쉐도우맵에 저장된 깊이 값 z1보다 크다. 이는 z1이라는 깊이 값을 가진 어떤 점이 광원과 q1 사이에 놓여 있어서 q1으로 향하는 빛을 가리고 있다는 것을 의미한다. 따라서 q1은 그림자에 속하는 점으로 판정된다. 반면, 프래그먼트 f2에 해당하는 월드 공간 점 q2의 경우, 광원까지의 거리 d2는 쉐도우맵에 저장된 값 z2와 같다. 즉, q2는 광원에서 보이는 점이다. 따라서 q2는 빛을 받는 점으로 판정된다.

이상 설명한 바와 같이 쉐도우 매핑 알고리즘은 개념적으로 매우 간단하다. 하지만, 이를 그대로 구현할 경우, 여러 문제와 마주치게 된다. 그림 15.3.a는 장면 및 카메라 구성을, 그림 15.3.b는 쉐도우 매핑을 사용해 장면을 렌더링한 결과를 보여준다. 완전하게 빛을 받는 지역에 자잘한 그림자가 섞여 있다.

다시 그림 15.2.b로 돌아가 보자. f2의 월드 공간 점 q2는 쉐도우맵을 생성할 때 샘플한 점과 일치했다. 하지만 실제 이 같은 경우는 거의 발생하지 않는다. 즉, 첫 번째 패스에서 샘플한 점과 두 번째 패스에서 샘플한 점은 대개의 경우 불일치한다. 그림 15.3.c의 예를 보자. q1은 첫 번째 패스에서 쉐도우맵을 구성하기 위하여 샘플한 어떤 점과도 일치하지 않는다.

쉐도우맵은 텍스처의 한 종류이므로 이를 어떻게 필터링할 것인지 미리 정해야 하는데, 근접점 샘플링(nearest point sampling)을 사용한다고 가정하자. 그러면 그림 15.3.c의 q1의 경우, 쉐도우맵에서 z1을 읽어올 것이다. 이는 q1과 광원 사이의 거리 d1보다 작기 때문에 q1은 그림자에 속하는 점으로 판정된다. 이는 잘못된 판정이다. 반면, f1에 인접한 프래그먼트 f2를 보자. f2의 월드 공간 점 q2에 대해서는 쉐도우맵에서 z2를 읽어오므로, q2는 빛을 받는다고 판정된다. 이는 옳은 판정이다. 이처럼 완전하게 빛을 받는 지역임에도 일부 프래그먼트는 빛을 못 받는 것으로 판정되어 그림 15.3.b처럼 자잘한 그림자가 생성되는 것이다.

img 그림 15.3.a와 b. 쉐도우 매핑의 문제점과 해결 방법. (a) 장면 및 카메라 구성. (b) 렌더링 오류.

img 그림 15.3.c. 그림자 진 q1과 빛을 받는 q2

img 그림 15.3.d. 바이어스 기반 해결 방법

img 그림 15.3.e와 f와 g. (e) 개선된 그림자. (f) 너무 작은 바이어스. (g) 너무 큰 바이어스

이 문제를 해결하는 방법은 간단하다. 두 번째 패스에서 샘플한 점들을 광원 쪽으로 약간 이동하면 된다. 즉 광원까지의 거리 d에서 일정한 값들을 빼는 것이다. 이 값을 바이어스(bias)라 한다. 그림 15.3.d에서는 d1에서 바이어스를 빼서 d1’를 만든 후 이를 z1과 비교하였다. d1’가 z1보다 작으므로 q1은 빛을 받는 것으로 판정된다. 그림 15.3.e는 이러한 방법을 통해 쉐도우 매핑을 개선한 결과를 보여준다.

쉐도우 매핑에서는 적절한 바이어스를 설정하는 것이 중요한데, 바이어스가 너무 작을 경우 불필요한 자잘한 그림자를 완벽히 제거할 수 없다. 그림 15.3.f의 공 표면을 보자. 반면, 바이어스가 너무 크면 그림 15.3.g에 보인 것처럼 그림자가 과도하게 축소될 수 있다. 그늘져야 할 부분이 빛을 받는 것으로 판정된 결과이다. 바이어스는 대개 몇 번의 시험을 거쳐 적절한 값으로 설정된다.


15.2. 쉐도우맵 필터링


그림 15.4.a의 월드 공간 점 q1과 q2를 보자. 이는 쉐도우맵으로 투영되어 두 텍셀 p1과 p2 사이에 놓이게 된다. 근접점 샘플링으로 쉐도우맵을 필터링하면, q1은 p1과 비교되어 그림자 지는 것으로 판정되고, q2는 p2와 비교되어 빛을 받는 것으로 판정된다. 즉, 하나의 프래그먼트는 완전히 빛을 받거나 완전히 그늘지거나 둘 중 하나로 판정될 뿐, 다른 여지는 없다. 그 결과 그림 15.4.b처럼 거친 윤곽선을 가진 그림자가 생성된다. 이는 그림 8.9.a에 보인 문제점과 유사하다.

img 그림 15.4. 쉐도우맵 필터링. (a) 쉐도우맵에 투영된 q1과 q2. (b) 근접점 샘플링으로 생성된 그림자의 거친 윤곽선

이제 겹선형보간으로 쉐도우맵을 필터링해 보자. 그림 15.4.c는 쉐도우맵에 투영된 프래그먼트 q를 보여준다. q를 둘러싼 네 개 텍셀의 깊이 값은 쉐도우맵에서 읽어온 것이다. 이 깊이 값을 겹선형보간하면 64가 된다. 만약 q의 깊이가 80이라면, q는 그늘진 것으로 판정된다. 즉, 완전히 빛을 받거나 완전히 그늘지거나 둘 중 하나로 판정되는 문제는 여전하다. 그림 15.4.c 오른쪽 그림을 보자. 그림자의 윤곽선은 여전히 거칠다. 그림 8.9.b와는 달리, 겹선형보간이 문제를 해결해 주지 않는다.

이 문제를 해결하는 방법은 네 개의 텍셀 각각에 대해 q의 가시성을 결정한 후 이를 보간하는 것이다. 그림 15.4.d를 보자. 왼쪽 위의 텍셀만 고려하면 q에는 그림자가 맺힌 것으로 판정될 것이다. 즉, 이 텍셀에 대한 q의 가시성은 0이다. 반면, 나머지 세 개의 텍셀에 대해서는 q는 빛을 받는 것으로 판정된다. 즉, 이들에 대한 q의 가시성은 1이다. 네 개의 가시성 값을 겹선형보간하면 q의 가시성은 0.58로 계산된다. 이 값은 q가 빛을 받는 정도를 나타낸다. 즉, 완전히 빛을 받거나 완전히 그늘지거나 둘 중 하나를 택하는 대신, [0, 1] 범위 안의 값을 취하게 된다. 0에 가까우면 어둡게, 1에 가까우면 밝게 처리된다. 이 결과 그림 15.4.d 오른쪽에 보인 것처럼 그림자의 윤곽선은 그림 15.4.c보다 부드러워졌다.

img 그림 15.4. 쉐도우맵 필터링(계속). (c) 겹선형보간은 근접점 샘플링과 큰 차이를 생성하지 않는다. (d) 각 텍셀에 대해 가시성이 계산되고 겹선형보간된다.

쉐도우맵에서 여러 개의 텍셀을 참조하여 이들에 대한 픽셀의 가시성을 결정하고 그 결과를 결합하는 기법으로 일반적으로 PCF(percentage closer filtering)라고 부른다. 그런데, 그림 15.4.c와 d의 왼쪽을 비교해 보면, PCF는 기존의 겹선형보간과 다른 방식으로 구현되어야 한다는 것을 알 수 있다. 이에 대해서는 다음 절에서 다룬다.


15.3. 쉐도우 매핑을 위한 GL 프로그램과 쉐이더 (생략)


15.4. 하드 쉐도우와 소프트 쉐도우


img 그림 15.7. 하드 쉐도우

그림 15.7을 보면, 점 광원(point light)에서 나오는 빛을 받는 지역과 받지 않는 지역이 명확하게 구분되는데, 이렇게 만들어진 그림자를 하드 쉐도우(hard shadow)라 부른다. 반면, 점 광원과 달리 ‘면적’을 가진 광원을 영역 광원(area light)이라고 부르는데, 이는 소프트 쉐도우 (soft shadow)를 생성한다. 그림 15.8.a를 보면, 완전하게 빛을 받는 지역과 완전하게 그늘진 지역 사이에 ‘부분적으로 그늘진’ 지역이 있음을 알 수 있다. 이는 반그림자, 영문으로는 penumbra라고 부르는데, 여기에 속하는 표면의 각 점은 광원에서 나오는 빛의 일부만을 받는다. 따라서 완전하게 빛을 받는 지역과 완전하게 그늘진 지역을 부드럽게 이어준다.

반그림자 지역에 속하는 표면 점에 대해서는 ‘밝기 정도’를 계산해야 하는데, 이는 보통 그 점에서 영역 광원이 얼마나 많이 보이는지 측정하여 결정한다. 예를 들어 그림 15.8.b의 q1에서는 영역 광원이 많이 안 보이지만 그림 15.8.c의 q2에서는 보다 넓은 부분을 볼 수 있다. 따라서 q2는 더 큰 ‘밝기 정도’를 할당받을 것이다. 쉐도우 매핑 알고리즘을 확장하여 소프트 쉐도우를 생성하는 많은 실시간 기법이 존재하는데, 이들은 대개 반그림자 지역 표면의 각 점에서 영역 광원이 얼마만큼 보이는지 계산한다.

img 그림 15.8. 소프트 쉐도우. (a) 영역 광원이 생성하는 소프트 쉐도우. (b) q1에서는 영역 광원이 많이 보이지 않으므로 q1은 비교적 어둡게 처리된다. (c) q2에서는 영역 광원이 많이 보이므로 q2는 비교적 밝게 처리된다.

그림 15.4로 돌아가 보자. 그림 15.4.d의 그림자 윤곽선은 그림 15.4.b 및 c에 비해 부드럽게 보이지만 이는 소프트 쉐도우가 아니라 앤티에일리어싱(anti-aliasing) 처리된 하드 쉐도우라는 것을 이해하자. 소프트 쉐도우는 면적을 가진 영역 광원에 의해 만들어지는데, 전술한 PCF 알고리즘은 점 광원을 처리한 것이다.


참고

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