Why Use Cascaded Shadow Maps for Directional Light?
Why Use Cascaded Shadow Maps for Directional Light?
Shadow Mapping 은 결국 광원의 위치에서 바라본 Depth Buffer를 만드는 과정이다.
로컬 라이트들의 경우, 이 방식은 아래처럼 비교적 직관적이다.
- Spot Light: 카메라처럼 방향을 가지므로 원뿔 형태의 Frustum을 설정한다.\
- Point Light: 정해진 방향이 없으니 모두 커버하기 위해 여섯 방향의 depth를 기록할 수 있는 Cube Map을 사용한다.
(퀄리티 문제로 더는 안 쓰이지만, 2개의 hemisphere를 찍는 Dual Paraboloid를 사용할 수도 있겠다).
그렇다면 Directional Light는 어떻게 할까. 태양광처럼 scene 전체를 평행하게 내리쬐는 이 광원은 고정된 위치도, 구체적인 범위도 없다.
scene 전체를 담을 정도로 충분히 큰 shadow map 을 그려야 하는데, 크기를 아무리 키워도 퀄리티가 무너진다.
1. 플레이어의 시야와 원근 앨리어싱 (Perspective Aliasing)
현실적으로 무한한 맵을 만들 수 없으므로, 우리는 플레이어가 현재 보고 있는 시야에 대해서만 shadow map을 저장한다.
이건 다른 빛도 마찬가지다. 당장 보지 않는 부분에 대해서도 depth를 매번 그리는 건 이상하다. 어차피 culling 되어 나타나지 않을
옆방 테이블에 놓인 주전자에 대해 그 위에 조명이 있다고 계속 depth를 계산할 필요가 없다.
그런데 이 방식에도 치명적인 한계가 있다. Perspective Aliasing 이다.
directional light의 Shadow map은 orthographic projection 이기 때문에 그 밀도가 일정하다. 반면, 카메라는 보통 Perspective Projection이다.\
- 근거리 문제 : 카메라와 가까운 물체는 화면에서 크게 보이지만, 섀도우 맵 상에서는 먼 물체와 동일한 해상도를 가진다. 퀄리티가 망가진다.
- 원거리 낭비 : 반대로 멀리 있는 물체는 화면에서 아주 작게 보임에도 불구하고, 가까운 곳과 동일한 정밀도의 shadow map 을 가지니 메모리가 낭비가 심하다.
근본적인 문제는 카메라 혹은 플레이의 위치와 상관 없는 곳에서 일정한 shadow map 을 만드는 데 있다.
화면 끄트머리 저 멀리 위치한 픽셀 몇 개를 위해 너무 정교한 작업이 들어가고 있어 지금 당장 눈앞의 테이블에 필요한 자원을 빼앗기고 있다.
이쯤 되면 LOD 가 떠오른다.
LOD? »> Wireframe Outline Rendering
2. CSM (Cascaded Shadow Maps)
이 해상도 불균형 문제를 해결하기 위해 도입된 기법이 바로 CSM(Cascaded Shadow Maps)이다. 원리는 간단하다.
카메라가 보는 시야, View Frustum를 거리 별로 여러 구간으로 쪼개서 해상도에 차등을 둔다.
작동 원리
-
Frustum Splitting: View Frustum을 Near, Mid, Far 등의 단계(Cascade)로 나눈다.
보통 근거리의 품질을 위해 카메라에 가까울수록 구간을 더 세밀하게 나눈다. - 단계별 Shadow Map 생성:
- Near Cascade: 카메라와 아주 가까운 좁은 영역만 담는다. 좁은 범위라 shadow map의 해상도가 높고 그림자도 선명하다.
- Far Cascade: 훨씬 멀리까지, 넓은 영역을 담는다. 동일한 텍스처 크기를 사용하더라도 커버하는 범위가 넓어 밀도는 낮아진다.
- 셰이더 샘플링: 픽셀 셰이더에서 현재 픽셀의 Depth 값을 확인하여 어떤 Cascade에 속하는지 판단하고, 해당 섀도우 맵에서 값을 읽어온다. 이때 경계면이 어색하지 않도록 인접한 Cascade 간의 블렌딩 처리를 할 수 있다.
CSM을 적용하기 전까지 우리의 시야에서 shadow map의 해상도는 아래와 같았다.
이제는 아래와 같다. 마치 폭포수가 퍼져나가며 잠잠해지는 것 같지 않은가.
또 어떻게 directional light에서 shadow map을 그릴 지도 감이 잡혔다.
관건은 카메라가 보는 곳만, 차등을 둬서 그린다.
GitHub 계정으로 댓글을 작성합니다.
현재 추천 수: 조회 중...
GitHub 이슈의 👍 반응을 집계합니다.
추천(👍) 남기기
이 문서 작업실에서 편집하기