복셀 베이스 맵에서의 비동기 SW Occlusion Culling.
삼각형 베이스 맵에 적용했던 비동기 S/W Occlusion Culling을 복셀 베이스 맵에도 적용했다.
S/W Occlusion Culling은 대단히 부하가 많이 걸리는 작업이기 때문에, 이를 매 프레임마다 수행하면 GPU성능이 충분한 경우 오히려 전체적인 응답성을 떨어뜨릴 수 있다.
이번 구현의 목표는
‘S/W Occlusion Culling으로 이득을 보되, 최악의 경우에도 S/W Occlusion Culling때문에 느려지는 사태를 방지한다.’
는 것이다.
기본적으로 S/W Occlusion Culling을 별도 스레드로 분리한다. S/W Occlusion Culling을 비동기적으로 수행한다고 하는 것은, 항상 이전 프레임(적어도 1프레임 전)의 S/W Occlusion Culling결과를 사용하게 된다는 뜻이다. 카메라 상태가 변화하지 않았다면 이전 프레임의 결과를 그대로 사용해도 문제가 없다. 대부분의 경우 1프레임 사이에 카메라 상태가 크게 변하지는 않는다. 따라서 일정 정도의 변화량 미만이면 카메라의 상태가 변화하지 않았다고 간주한다.
구현은 다음과 같다.
[메인스레드]
- 렌더링될 복셀 오브젝트를 탐색하는 함수로 진입한다.
- 현재 프레임에서 KD-Tree를 탐색해서 렌더링될 leaf들과 leaf에 속한 복셀 오브젝트들을 수집한다.
- 이 복셀 오브젝트들로부터 삼각형을 수집한다.
- 비동기 S/W Rasterizer/Tester에 이 심각형들을 전달한다. 대기 상태였던 Raster/Test스레드를 깨운다.
- Raster/Test스레드가 SW Occlusion Culling결과를 저장해둔게 있는지 확인한다. 없으면 8로.
- 저장된 결과가 있으면 SW Occlusion Culling을 수행할 당시의 카메라 상태와 현재 카메라 상태 사이에 유의미한 변화가 있었는지 확인한다.
- 유의미한 변화가 없었다고(안변했다고) 판단되면 Raster/Test스레드가 저장한 leaf들로부터 Voxel오브젝트들을 수집한다.
- 찾아낸 Voxel 오브젝트들을 리턴한다.
[Raster/Test스레드]
- 메인스레드에 의해 깨어난다. 메인스레드로부터 전달받은 삼각형들(Voxel오브젝트로부터 얻은, Occluder로 사용할 삼각형)을 Frame Buffer에 그린다.
- 저달받은 leaf들이 정말 화면에서 보이는지 테스트한다. leaf는 육면체가 되므로 12개의 삼각형을 얻을 수 있다. 이 삼각형들을 Frame Buffer에 depth test한다.
- depth test를 통과한, 보인다고 판정된 leaf들만 결과 버퍼에 저장한다.
- wait상태로 진입
[S/W Occlusion Culling Off, H/W Occlusion Culling Off] , 렌더링되는 오브젝트 9817개
[S/W Occlusion Culling On, H/W Occlusion Culling Off] , 렌더링되는 오브젝트 90개
[S/W Occlusion Culling On, H/W Occlusion Culling On] , 렌더링되는 오브젝트 82개