시작하며 #
3D 게임에서의 대부분의 장면들은 높은 깊이 복잡성(depth complexity)을 가지는 경향이 있습니다. 깊이 복잡성(Depth complexity)이란 장면이 랜더링되는 동안 화면상의 한 픽셀이 몇번이나 찍히는가를 의미합니다.

그림 1은 같은 장면에 대한 세가지 다른 뷰를 보여주고 있씁니다. 와이어프레임은 중복 랜더링된부분이 많다는 것이 확실하다는 것을 보여줍니다. 가장 오른쪽의 이미지는 이미지의 깊이 복잡성을 나타냅니다 : 점이 더 밝은 부분은 더많이 중복 랜더링 되었다는 것을 나타냅니다.
깊이 복잡성을 줄이기 위해, 여러분은 occlusion culling을 사용할 수 있습니다. 객체 A가 완전히 객체 B의 뒤에 놓여 있을때, A는 B에 의해 차단(occlude)되었다고 말하며, 이는 랜더링 될 필요가 없습니다. 이 아티클의 나머지에서는 occlusion culling을 실행할 수 있는 한가지 방법으로서 그림자 볼륨(shadow volume)을 언급하고자 합니다.
개념 #
다음의 장면을 가정해봅시다. 검정 선은 FOV(Field Of View : 시야)를 의미합니다.

그림자 볼륨 기술에 대한 아이디어는 다음과 같습니다.

각각의 차단가능한 모든 객체에 대하여, 여러분은 그림자 볼륨을 생성합니다. 시점이 광원인것처럼 상상해보시기 바랍니다. 객체의 그림자 볼륨은 객체의 그림자 내부공간이 됩니다. 물론, 핵심은 다른 객체의 그림자 볼륨내에 놓여있는 객체는 보이지 않으므로, 컬링(culling)이 가능합니다. 그림에서는, 구분을 위해 그림자 볼륨을 해당 객체와 같은 색상으로 설정했습니다. 보다시피, 파란 상자는 가장 중요한 차단자(occluder)임에 틀림없습니다.
좋은 차단자를 찾아내기 #
그림자 볼륨 기술의 목적은 깊이 복잡성을 줄이는 것입니다만, 장면마다 모든 객체에 대한 그림자 볼륨을 생성해야만하고 그 과부하는 절약되는 것보다 더 커질 수 있습니다. 여러분은 장면상의 객체들 중에서 최선의 차단자 후보들을 제한할 필요가 있습니다.
여기에서는 장면이 폴리곤 수프(polygon soup)로 구성되어있다고 가정합니다 - 다시말하자면, 계층구조 또는 분할같은 기술이 전혀 사용되지 않았다는 의미입니다. 이것은 차단자로서 가능한한 큰 크기의 폴리곤들을 찾아야한다는 것을 의미합니다. 폴리곤들을 사용하는 것은 모든 것을 더 간단하게 만들어주는 잇점을 가지고 있습니다 : solid 객체에 대하여 그림자 볼륨을 생성하는것은 비교적 어렵지만, 폴리곤에 있어서는 별거아닌 일입니다.
물론 모든 폴리곤이 좋은 차단자가 되는 것은 아닙니다. 여러분은 장면상에서 가장 큰 것을 선택함으로서 처리를 시작하기를 원할 것입니다. 만약 삼각폴리곤들에서만 처리하려한다면, 몇몇 삼각형들을 묶어 그룹화하여 더 큰 폴리곤으로 만들고 이것을 차단자로 사용하는 것이 더 효율적일 수 있습니다. 여러분은 랜더링 처리를 위해 여전히 삼각형들을 사용할 수 있으므로, 문제점은 발생하지 않을 것입니다. 명심해야할 단 한가지는 차단자는 볼록(convex) 다각형이어야한다는 점입니다.
알맞은 큰 폴리곤 그룹의 선택이 끝났다면, 실제로 그것이 좋은 차단자인지를 시험해보고 싶을 것입니다. 여러분은 폴리곤 주위에 난수위치의 뷰포트들을 생성하고, 이들 뷰포트로부터 차단된 폴리곤이 몇 개인가를 검사함으로서 이 실험을 진행할 수 있습니다. 물론, 어플리케이션 사용자가 실제로 위치할 수 있는 뷰포트만을 선택하여야만 하므로, 뷰포트들이 장면안에 생성되었는지를 검사하여야합니다. 가장 좋은 결과를 내는 차단자만을 남겨두고 나머지는 버립니다.
컬링(Culling) #
물론 차단자를 선택하는것은 전처리로서 종료되어야하는데, 이는 시도와 오류를 통하여 이 작업이 진행되므로 꽤 오랜 처리시간이 걸리기 때문입니다. 어쨌든, 한번 차단자를 선택하였다면 나머지 작업은 매우 직관적입니다. 장면을 랜더링할 때, 모든 차단자들을 처리하고, 이들에 대한 그림자 볼륨들을 생성한다음 차단자에 포함된 모든것을 컬링처리해버립니다.
컬링 처리를 최적화하기위해서, 여러분은 차단자들을 정렬할 필요가 있는데 이는 가장 중요한 차단자가 먼저 처리되어야하기 때문입니다. 여러분은 차단자 하나가 얼마나 "중요한"가를 진단하기위한 몇가지 측정기준이 필요할 것입니다. 이 기준은 차단자의 화면상에 차지하는 공간에 기초할 수도 있고, 카메라와의 거리가 될 수도 있습니다. 더욱이, 앞면이 뒤로 향한 차단자들은 무시되어야만 합니다. (이들은 확실히 시야 밖에 위치하기 때문입니다)
어느 한 폴리곤의 그림자 볼륨을 생성하는 것은 별거아닌 작업입니다. 3개의 점들로부터 평면을 정의하는 것은 쉬운 작업이고, 이것이 여러분이 할 일의 전부입니다. 폴리곤의 각각의 귀퉁이 선분마다, 카메라 위치와 선분의 양 끝 점들을 사용하여 평면을 생성합니다. 또한 생성한 다음에는 폴리곤 자신이 놓여있는 평면을 추가합니다 - 그렇지않으면 차단자 앞에 놓여있는 객체들을 컬링해버릴 수 있습니다. 생성한 모든 평면의 노멀 벡터 정점은 같은 방향을 향해야한다는 것을 명심하여야합니다(그림자 볼륨의 안쪽이든 바깥쪽이든 말이죠)
그림자 볼륨을 생성한 다음, 이에 대하여 전체 장면을 클리핑할 필요가 있습니다. 이때 볼륨 내에 있는 모든 것을 취소해버립니다. 이것은 물론 (볼륨내에 포함되어있는) 다른 차단자들에게도 마찬가지로 적용되는데, 보이지않는 차단자를 처리할 필요는 없기 때문입니다. 이 경우 실제 클리핑 작업은 매우 쉽습니다 : 폴리곤이 컬링되어야한다면, 그 폴리곤의 모든 정점은 그림자 볼륨내에 놓여있어야만 합니다. 따라서, 여러분이 검사해야할 일은 그림자 볼륨의 평면 방정식에 대하여 각각의 정점들을 검사하기만 하면 됩니다.
각각의 모든 폴리곤을 모든 그림자 볼륨에 대하여 검사하는 것은 조금 처리비용이 들어갈수 있는 작업이므로, 이를 개선할 몇가지 방법이 필요할 것입니다. octree는 그림자 볼륨에 대하여 독립적인 폴리곤대신 각각의 상자들만 검사하면 되도록 만들어줍니다. 이 방법을 사용하면 장면의 큰 부분을 매우 빨리 제거할 수 있을 것입니다. 여러분이 원한다면, 나중에 남은 폴리곤들을 검사할 수도 있을 것입니다.
결론 #
여기서 언급한 그림자 볼륨 기술은 occlusion culling을 위해 사용가능한 한가지 방법일 뿐입니다. 더많은 내용을 알고 싶다면, 검색엔진에서 찾을 수 있는 몇몇 다른 occlusion 알고리즘이 있습니다(hierarchical Z-buffering, lazy occlusion grids, hierarchical occlusion maps가 그 예입니다.) 또한, HP에서 occlusion culling을 GL_HP_occlusion_test opengl 확장으로서 하드웨어 가속적인 방법으로 지원한다는 사실도 흥미로워할거라 생각합니다.
대부분의 occlusion culling 알고리즘의 성능은 좋은 차단자(occluder)들을 선택하는데 많이 좌우됩니다. 이 아티클은 차단자로서 거대한 폴리곤들을 사용한다는 것을 가정했지만, 여러분의 장면 데이타가 폴리곤 수프(polygon soup)보다 더 상위수준의 방법으로 정의되었다면, 여러분은 이 방법보다 더 많은 방법들을 사용할 수 있을 것입니다.
차단자들은 장면내의 실제 객체 또는 폴리곤과 일치할 필요가 없다는 것을 명심하세요. 예를 들자면, 여러분은 크고 상세한 구형 객체를 가지고 있다고 하면, 그 내부에 XY, YZ, XZ 평면에 기준하여 정렬된 3개의 팔각형을 넣어둘수 있을 것입니다. 실제 구와 일치하는 원모양의 다각형을 사용하는 것보다는 다소 정확성이 떨어지지만, 이 방법은 더 빨리 실행될 것입니다.
대부분의 건물안(indoor) 3D 슈팅 엔진에서는 아마도 포탈(portal) 랜더링을 사용하는 것이 더 효과적일 것입니다. 하지만, 부담을 덜어주는 별도의 제약사항을 적용하지 않았다면, 더 복잡한 장면에서는 의심의 여지가 없이 더 유용하다는 것을 증명해줄 것입니다. 숲, 도시, 산이 많은 지형들 - 이들은 모두 occlusion culling을 통하여 많은 실행상의 이득을 취할 수 있는 것들입니다.








![[http]](/wiki/imgs/http.png)
