Depth Buffer Based Ambient Occlusion (= SSAO)

a0008416_4ac18fea75366

<픽셀 당 16 rays>

미리 계산된 depth 값으로 주변 픽셀과의 차폐정도를 구해 ambient 값을 산출 하는 방법.
크라이시스에서 처음 도입하였고, 구현 방법도 비교적 간단해서 왠만한 엔진에서는 기본적으로 지원하는 시대가 됐다..
(개인적으로는 SSAO 라는 용어 보다 depth buffer based AO 가 좀 더 정확한 용어가 아닌가 싶다..)

기본적인 방법은 다음과 같다.

깊이값 -> 뷰 공간 3d 좌표를 구해서 ray 를 쏨 -> ray 의 스크린 2d 좌표를 구함 -> 구한 좌표의 깊이값과 처음 깊이값 비교

#1
깊이값 -> 뷰공간 3D 좌표:

ndc.z = depth * 2 – 1;
viewPos.z = -projectionMatrix[2][3] / (ndc.z + projectionMatrix[2][2]);
viewPos.x = viewPos.z * tan(fragFovX * 0.5);
viewPos.y = viewPos.z * tan(fragFovY * 0.5);

#2
뷰공간 좌표 -> 화면 2D 좌표:

ndc.x = projectionMatrix[0][0] * viewPos.x / viewPos.z + projectionMatrix[0][2];
ndc.y = projectionMatrix[1][1] * viewPos.y / viewPos.z + projectionMatrix[1][2];
screen.xy = ndc.xy * 0.5 + 0.5;

꽁수 1 : 2x downscaled depth buffer 사용
꽁수 2 : 랜덤 ray 벡터를 랜덤 벡터로 reflect (회전 변환보다 싸다)
꽁수 3 : view normal 값을 사용할 수 있다면 self occlusion 을 피하기 위해 sign(dot(ray, n)) 을 곱한다
꽁수 4 : 카메라와 가까이 있는 픽셀의 ray 는 작게 scale 하여 어색함을 줄임
꽁수 5 : 깊이값 비교 함수를 적절히 조절 ^^;

참고 자료:
http://en.wikipedia.org/wiki/Screen_Space_Ambient_Occlusion
http://www.gamedev.net/community/forums/topic.asp?topic_id=545825
http://developer.amd.com/gpu_assets/S2008-Filion-McNaughton-StarCraftII.pdf

Leave a Reply

Your email address will not be published. Required fields are marked *