3D Rendering

Shadow map

Keisa 2023. 9. 29. 12:01

출처: https://choi-dan-di.github.io/computer-graphics/shadow-mapping/

 

깊이 버퍼는 카메라를 기준으로 픽셀의 거리를 기록한 Map이다. 하지만 Shadow Map은 카메라가 아니라 Light를 기준으로 깊이를 기록한 Map.

 

아래는 출처에서 퍼온 내용

두 단계 렌더링

쉐도우 매핑 알고리즘은 두 번의 렌더링 패스(Rendering Pass)를 통해 수행된다. 첫 번째 패스에서는 쉐도우맵(Shadow Map)이라는 특수한 텍스처를 생성한다. 두 번째 패스에서는 실제 렌더링을 수행하게 된다.

위 이미지에서 광원에서 나온 빛이 미치는 표면은 굵은 선으로 표시되었다. 이들 표면을 균일하게 샘플하여, 각 샘플점 p마다 광원까지의 거리(z)를 쉐도우맵에 저장한다. 이는 광원에서 본 3차원 장면의 깊이값이다. 따라서, 쉐도우맵은 광원 기준의 깊이맵(Depth Map)이라고도 한다.

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

이렇게 쉐도우 매핑 알고리즘은 개념적으로 매우 간단하지만 이를 그대로 구현할 경우 위 오른쪽 이미지처럼 완전하게 빛을 받는 지역에 자잘한 그림자가 섞여 있는 것 같은 문제를 포함하여 여러 문제와 마주치게 된다.

쉐도우맵은 텍스처의 한 종류이므로 이를 어떻게 필터링할 것인지 미리 정해야 한다. 근접점 샘플링(Nearest Point Sampling)을 사용한다고 가정하자. 쉐도우 매핑이 수행되면서 샘플된 프래그먼트 점과 그 근처에 위치한 라이팅이 비교될 것이다. 이 결과는 정확한 결과를 보장하지 않아 자잘한 그림자가 발생하는 문제가 생긴다.

이 문제를 해결하는 방법은 간단하다. 두 번째 패스에서 샘플한 점들을 광원 쪽으로 약간 이동하면 된다.

즉, 광원까지의 거리 d에서 일정한 값을 빼는 것이다. 이 값을 바이어스(Bias)라 한다. 위 이미지에서 보면 d1에서 바이어스를 뺀 d1‘를 만든 후, 이를 z1과 비교한다. 이는 d1‘가 z1보다 작으므로 샘플된 점은 빛을 받는 것으로 판정된다. 이러한 방법으로 쉐도우 매핑을 개선할 수 있다.

쉐도우 매핑에서는 적절한 바이어스를 설정하는 것이 중요한데, 바이어스가 너무 작을 경우 불필요한 그림자를 완벽히 제거할 수 없고 바이어스가 너무 크면 그림자가 과도하게 축소될 수 있다. 바이어스는 대개 몇 번의 시험을 거쳐 적절한 값으로 설정된다.

쉐도우맵 필터링

앞서 보았던 근접점 샘플링을 이용하면 하나의 프래그먼트는 완전히 빛을 받거나 완전히 그늘지거나 둘 중 하나로 판정될 뿐, 다른 여지는 없다. 그 결과 이미지 텍스처링에서 보았던 모자이크화되는 문제가 발생할 수 있다.

이를 보완하기 위해 겹선형 보간을 사용하여 쉐도우맵을 필터링해 보자.

위 왼쪽 이미지가 겹선형 보간을 이용하여 쉐도우맵을 필터링한 결과이다. 쉐도우맵에 투영된 프래그먼트 q를 둘러싼 네 개 텍셀의 깊이 값을 보간하여 q의 깊이값과 비교하게 된다. 이 결과로 q의 깊이가 더 크다면 그늘진 것으로 판정된다. 이 역시 완전히 빛을 받거나 완전히 그늘지거나 둘 중 하나로 판정되는 문제는 여전하다.

이 문제를 해결하는 방법은 네 개의 텍셀 각각에 대해 q의 가시성(Visibility)을 결정한 후 이를 보간하는 것이다. 위 오른쪽 이미지가 이에 해당하는데, 왼쪽 위의 텍셀만 고려하면 q에는 그림자가 맺히는 것으로 판정될 것이다(q의 깊이값이 더 크기 때문이다). 즉, 이 텍셀에 대한 q의 가시성은 0이다. 반면, 나머지 세 개의 텍셀에 대해서는 q는 빛을 받는 것으로 판정되기 때문에 가시성은 1이 될 것이다. 이 네 개의 가시성 값을 겹선형 보간하면 q의 가시성은 0.58로 계산된다. 이 값은 q가 빛을 받는 정도를 나타내며 완전히 빛을 받거나 완전히 그늘지거나 둘 중 하나를 택하는 대신 [0, 1] 범위 안의 값을 취하게 되며 0에 가까우면 어둡게, 1에 가까우면 밝게 처리된다. 이 방법을 통해 그림자의 윤곽선을 조금 더 부드럽게 만들 수 있을 것이다.