KH_C++
그림자 매핑(Shadow Mapping) 본문
[ Shadow Mapping ]
그림자는 폐색으로 인해 빛이 없는 결과입니다. 광원의 광선이 다른 개체에 의해 가려져 개체에 닿지 않으면 개체가 그림자에 있는 것입니다. 그림자는 조명이 켜진 장면에 많은 사실감을 더하고 뷰어가 개체 간의 공간 관계를 더 쉽게 관찰할 수 있도록 합니다. 그들은 우리의 장면과 물체에 더 큰 깊이감을 줍니다. 예를 들어 그림자가 있거나 없는 장면의 다음 이미지를 살펴보도록하겠습니다.
그림자를 사용하면 개체가 서로 어떻게 관련되어 있는지 훨씬 더 분명해집니다. 예를 들어 큐브 중 하나가 다른 큐브 위에 떠 있다는 사실은 그림자가 있을 때만 눈에 띕니다.
그러나 그림자는 구현하기가 약간 까다롭습니다. 특히 현재 실시간(래스터화된 그래픽) 연구에서 완벽한 그림자 알고리즘이 아직 개발되지 않았기 때문입니다. 몇 가지 좋은 그림자 근사 기법이 있지만 모두 우리가 고려해야 하는 작은 단점과 성가심을 가지고 있습니다.
괜찮은 결과를 제공하고 비교적 구현하기 쉬운 대부분의 비디오 게임에서 사용되는 한 가지 기술은 다음과 같습니다.
그림자 매핑은 이해하기 너무 어렵지 않고 성능에 너무 많은 비용이 들지 않으며 보다 고급 알고리즘인 전 방향성 음영 맵(Omnidirectional Shadow Maps) 및 계단식 음영 맵(Cascaded Shadow Maps) 등으로 쉽게 확장됩니다.
그림자 매핑 이면의 아이디어는 매우 간단합니다. 우리는 빛의 관점에서 장면을 렌더링하고 빛의 관점에서 보는 모든 것은 조명을 받고 우리가 볼 수 없는 모든 것은 그림자 안에 있어야 합니다. 자체와 광원 사이에 큰 상자가 있는 바닥 섹션을 상상해 보십시오. 광원은 특정 바닥 섹션이 그림자에 있어야 하는 방향을 볼 때 바닥 섹션이 아닌 이 상자를 볼 것입니다.
여기서 모든 파란색 선은 광원이 볼 수 있는 조각을 나타냅니다. 차단된 조각은 검은색 선으로 표시되며 그림자가 있는 것으로 렌더링됩니다. 선을 긋거나 레이광원에서 가장 오른쪽 상자의 조각으로 이동하면 광선이 가장 오른쪽 컨테이너에 도달하기 전에 떠다니는 컨테이너에 먼저 도달하는 것을 볼 수 있습니다. 결과적으로 떠있는 컨테이너의 조각이 켜지고 맨 오른쪽 컨테이너의 조각이 켜지지 않아 그림자가 생깁니다.
우리는 광선에 처음으로 물체를 치는 지점을 얻고 이 가장 가까운 지점을 이 광선의 다른 지점과 비교하려고 한다. 그런 다음 기본 테스트를 수행해 테스트 포인트의 광선 위치가 가장 가까운 포인트보다 광선 아래에 있는지 확인한다.
그렇다면 테스트 포인트가 그림자에 있어야한다. 그러한 광원으로부터의 수천 개의 광선을 반복해서 반복하는 것은 극히 비효율적인 접근이며, 실시간 렌더링에 좋지 않다. 대신 The Depth Buffer 을 사용할 것이다.
깊이 테스트 튜토리얼에서 깊이 버퍼의 값은 카메라의 관점에서 [0,1]로 고정된 조각의 깊이에 해당한다는 것을 기억할 것이다. 빛의 관점에서 장면을 렌더링하고 결과 깊이 값을 텍스처에 저장한다면 어떨까? 이렇게하면 광원의 관점에서 볼 때 가장 가까운 깊이 값을 샘플링 할 수 있다. 결국 깊이 값은 광원의 관점에서 볼 수 있는 첫 번째 조각을 보여준다. 이 모든 깊이 값을 깊이 맵 (Depth map) 또는 그림자 맵(Shadow map) 이라고하는 텍스처에 저장한다.
왼쪽 이미지는 큐브 아래의 표면에 그림자를 드리우는 방향 광원을 보여준다. 깊이 맵에 저장된 깊이 값을 사용해 가장 가까운 점을 찾고 이를 사용해 조각이 그림자에 있는지 여부를 확인한다. 우리는 광원에 특정한 뷰 및 투영 행렬을 사용해 장면을 렌더링함으로써 깊이 맵을 생성한다. 이 투영 및 뷰 매트릭스는 3D 위치를 조명의 가시적인 좌표 공간으로 변환하는 변환 T를 함께 형성한다.
- Directional light는 무한히 멀리 모델링된 위치를 갖지 않는다. 그러나 그림자 매핑을 위해 우리는 빛의 관점에서 장면을 렌더링해야하므로 빛 방향의 어딘가의 위치에서 장면을 렌더링해야한다.
오른쪽 이미지에서 우리는 동일한 지향성 빛과 뷰어를 본다. 우리는 그림자가 있는지 여부를 결정해야하는 지점 P에서 조각을 렌더링한다.
이렇게 하기 위해 우리는 먼저 T를 사용해 점 P를 빛의 좌표 공간으로 변환한다. 점 P는 빛의 관점에서 본 것처럼 이제 Z 좌표는 이 예에서 0.9인 깊이에 해당합니다. 점 P를 사용해 깊이 맵을 인덱싱해 광원의 관점에서 가장 가까운 눈에 보이는 깊이를 얻을 수 있다.
이 깊이는 샘플 깊이 0.4의 지점 C에 있다. 깊이 맵을 인덱싱하면 점 P에서의 깊이보다 더 작은 깊이가 반환되었으므로 점 P가 폐색되어 그림자에 있다고 결론을 내릴 수 있다.
그림자 매핑은 두 가지 패스로 구성된다. 먼저 깊이 맵을 렌더링하고 두 번째 패스에서 장면을 보통으로 렌더링하고 생성된 깊이 맵을 사용해 조각이 그림자에 있는지 여부를 계산한다.
출처:
https://learnopengl.com/Advanced-Lighting/Shadows/Shadow-Mapping
'공부' 카테고리의 다른 글
키 프레임 애니메이션(Key frame Animation) (0) | 2023.06.29 |
---|---|
포워드 렌더링(Forward Rendering), 디퍼드 렌더링(Deferred Rendering) (0) | 2023.06.28 |
노멀 매핑(Normal Mapping), 탄젠트 스페이스(Tangent Space) (0) | 2023.06.26 |
스키닝(Skinning) (0) | 2023.06.23 |
SIMD (Single Instruction Multiple Data) (0) | 2023.06.20 |