원문 : https://software.intel.com/en-us/articles/adaptive-screen-space-ambient-occlusion


샘플 소스 : https://github.com/GameTechDev/ASSAO/


주의 : 번역이 개판이므로 이상하면 원문을 참고하세요.


주의 : 허락받고 번역한 것이 아니므로 언제든 내려갈 수 있습니다.



By Filip Strugar, published on November 9, 2016, updated Feburary 13, 2017


이 기사는 어댑티브 스크린 스페이스 앰비언트 오클루전( adaptive screen space ambient occlusion )( ASSAO )라 불리는 이펙트( effect )의 새로운 구현에 대해서 소개합니다. 그것은 저전력 디바이스에서부터 고해상도를 가진 고성능 데스크탑들까지를, 통일된 외견( look ), 설정들, 업계 표준과 동일한 품질을 가진 하나의 구현하에서, 다룰 수 있도록 특별하게 설계되었습니다. 


SSAO 는 작은 범위의 앰비언트 이펙트들과 콘택트( contact ) 셰도우( shadow ) 이펙트들을 생성하기 위해 실시간 렌더링에서 사용되는 대중적인 이펙트입니다. 많은 현대의 게임 엔진들에서 사용되고 있으며, 보통 프레임 GPU 시간의 5 ~ 10 퍼센트만큼을 사용하게 됩니다. 여러 개의 알려진 구현들이 이미 존재하기는 하지만, 그 어떤 것도 오픈 소스이거나 무료로 이용할 수 있거나 저전력 모바일로부터 데스크탑 디바이스에 이르기까지 요구되는 성능 범위 단계( level of performance scaling )를 제공하지는 않습니다. 이 부분을 ASSAO 가 만족시켜줄 수 있습니다.


이 기사는 샘플코드를 이해하고 더 나아가 그것을 통합하거나 포팅( port )하는 방법에 대해서 초점을 맞추고 있습니다. 또한 구현 명세들과 이용가능한 옵션들과 설정들, 그리고 그것을 사용하는 데 있어 발생하는 트레이드 오프( trade-off )들에 다룹니다. 구현의 세부사항에 대해서 다루는 기사는 앞으로 나올 GPU Zen( GPU Pro* 8 )에 있습니다.


그림 1. Unity 4* 의 씬에 적용된 ASSAO 의 예제.


Full DirectX* 11 implementation is provided under MIT license in an easy-to-integrate package.


Algorithm Overview


ASSO 는 확장성( scalability )와 유연성( flexibility )을 위해 튜닝( tune )된  SSAO 구현입니다. AO 구현은 입체각( solid-angle ) 오클루전 모델에 기반합니다. 이는 novel progressive sampling kernel disk 를 사용하는 [Bavoil et al. 2008] 의 "Horizon-Based Ambient Occlusion" 과 유사합니다. 그것을 둘러싼 성능 프레임워크( performance framework )는 캐시 친화적인 deinterleaved rendering 의 2 x 2 버전입니다( 역주 : 이 방식에 대해서는 [ Deinterleaved Texturing for Cache-Efficient Interleaved Sampling ] 에서 다루고 있습니다 ). 그것은 "Deinterleaved Texturing for Cache-Efficient Interleaved Sampling" [Bavoil 2014] 와 선택적 뎁스( depth ) MIP-mapping 인 "Scalable Ambient Obscurance" [McGuire et al. 2012 ] 에서 언급되었습니다.


성능 관점에서 확장성 품질은 ( 점진적인 샘플링 커널( progressive sampling kernel )에 의해 활성화된 ) 다양한 AO 탭( tap )의 개수와 다양한 프리셋 레벨에서의 개별 기능들을 토글링( toggling )함으로써 결정됩니다.


마지막에 노이즈 제거( de-noise ) 블러가 적용된 인접 픽셀들 사이의 ( 회전되고 스케일링된 샘플링 디스크에 따른 ) AO 값을 공유하기 위해서 확률적( stochastic ) 샘플링을 사용합니다. 노이즈 제거 블러는 앞이나 뒤에 있는 오브젝트들에 AO 효과가 스며들어( bleeding ) 헤일로( halo )가 발생하는 것을 막기 위해 엣지를 고려합니다( edge-aware ). 가장자리는 뎁스에만 기반하거나 뎁스와 노멀( normal )에 기반합니다( 후자는 더 좋은 품질을 생성하지만, 처리하는 데 더 많은 비용을 사용합니다 ). 이런 스마트( smart ) 블러는 최적의 캐시 효율정을 위해 2 x 2 deinterleaved 영역( domain )에서 수행됩니다. Interleaving( 재구성 ) 패스 동안에 마지막 패스에서만 전체 해상도가 사용됩니다.


경험적으로, 그것은 다중 패스 픽셀 셰이더 기반 기법입니다. High 프리셋에서의 주요 단계들은 다음과 같습니다:


  1. 뎁스들을 준비합니다.
    1. 2 x 2 deinterleave 입력 스크린 뎁스를 4 개의 쿼터( quarter )-뎁스 버퍼들로 만들고, 값들을 뷰스페이스( viewspace )로 변환합니다. 입력 스크린 노멀들이 제공되지 않는다면, 그것들을 뎁스로부터 재구성합니다.
    2. 각각의 작은 뎁스 버퍼들을 위해 MIP 들을 생성합니다( Lowest 프리셋에서는 하지 않고, Low 프리셋이나 Medium 프리셋에서는 합니다 ).
  2. AO 항과 엣지를 고려한 블러를 4 개의 2 x 2 deinterleaved 파트( part )들에 대해서 계산합니다.
    1. AO 항과 엣지들을 계산하고 R8G8 텍스쳐에 저장합니다.
    2. 엣지를 고려한 스마트 블러를 적용합니다( 한 패스에서 여섯 패스까지, 사용자 설정에 달려 있습니다 ).
  3. 네 파트를 전체 해상도 버퍼에 합칩고 최종적으로 엣지를 고려한 블러 패스를 적용합니다.


Highest/Adaptive 품질 프리셋은 추가적인 기반( base ) AO 패스를 가지고 있으며, 이는 메인( main ) AO 패스의 픽셀당 변수 샘플 카운트를 안내( guide )하는 중요한 휴리스틱( heuristic )들을 제공하는데 사용됩니다.


표1 은 성능 수치들에 대한 개요를 제공합니다. 이 수치들은 참고용이며 드라이버와 하드웨어 명세에 따라 달라질 수 있습니다. 'radius' 같은 이펙트 설정을 변경하는 것은 성능에 영향을 주지 않습니다. 하지만 엣지를 고려한 블러의 경우에는 예외입니다; 블러 패스의 개수를 증가시키는 것은 비용을 증가시킵니다.


표1. 다양한 프리셋, 해상도, 하드웨어에서 ASSAO 이펙트 비용을 밀리세컨드( millisecond ) 단위로 표시.


스크린 노멀이 제공되고, 2-패스 블러와 Highest adaptive target 가 0.45 로 설정되면, Lowest/Low/Medium/High/Highest 프리셋들 사이의 이펙트 스케일링( 품질 vs 성능 )이 다양한 AO 탭의 개수와 개별 기능들에 대한 on/off 를 통해 결정됩니다. 표 2 는 이런 프리셋들의 세부적인 설정들을 보여 줍니다.


표 2. ASSAO 프리셋의 세부사항.


Sample Overview


샘플은 DirectX 11 을 사용하고 Windows* 7 64-bit 이상, 그리고 Microsoft Visual Studio* 2015 와 호환됩니다.


그림 2. ASSAO 샘플 레이아웃( layout ).


샘플에 포함된 Crytek Sponza* 씬이 기본으로 사용되며 기본 이펙트 프로우파일링 측정치( metric ) 이 우상단쪽 그래프에 나옵니다. 그래프 아래에는, 이펙트 설정, 품질, 혹은 이펙트 디버깅을 변경하기 위해 사용되는 여러 개의 다이얼( dial )들이 있습니다. 주요 설정은 다음과 같습니다:


  1. Effect enabled
    이펙트의 on/off 를 토글합니다.

  2. Effect radius
    뷰스페이스 단위의 앰비언트 오클루전의 반지름입니다.

  3. Effect strength
    선형 이펙트 배율( multiplier ). 이펙트 파워( power )와 함께 이펙트의 강도를 조절하고 이펙트를 페이드( fade ) 인/아웃( in/out )하는 데 유용합니다.

  4. Effect power
    지수적인( exponential ) 이펙트 수정자입니다: occlusion = pow( occlusion, effectPower ). 이펙트 커브의 파워를 변경( tweak )하는 최상의 방법입니다.

  5. Detail effect strength
    고주파수( high-frequency ) 이펙트를 추가하는 데 사용하는 2 픽셀 넓은 추가 커널입니다. 높은 값을 지정하면 에일리어싱( aliasing )과 일시적인 불안정성( temporal instability )이 증가합니다.

  6. Blur amount
    블러 패스의 개수를 더 높게 설정하면 더 낮은 고주파수 버전( less high-frequency variation )을 사용하는 것보다 더 부드러운 결과를 산출합니다. 이는 ( 에일리어싱을 줄여주는 ) 이점을 가지지만, 비용을 증가시킵니다.

  7. Blur sharpness
    거리 기반( 그리고 선택적인 노멀 기반 ) 가장자리가 흐려지는 것을 막는 정도를 결정합니다. 다른 앞뒤의 오브젝트들 사이에서 이펙트가 번지는 것을 막는데 사용됩니다. 이펙트가 번지면 헤일로와 다른 문제들이 발생합니다. 1 값이 의미하는 것은 완전히 날카로워( 엣지에서 블러링하지 않음 )지고 제약이 완화됨을 의미합니다. 1 에 가까운 값들은 에일이어싱을 제어하는 데 유용합니다.

  8. Deferred Path
    디퍼드 경로에서, 이펙트를 위한 입력들은 스크린 뎁스 텍스쳐와 노멀맵 텍스쳐입니다. 하지만, 포워드 패스가 사용되면, 뎁스 텍스쳐만이 입력으로 사용됩니다. 반면에 노멀맵은 뎁스로부터 재구성되는데, 이로 인해 비용이 추가되며 약간 다른 결과를 산출하게 됩니다.

  9. Expand resolution
    스크린 가장자리 근처에서는 이펙트 커널이 스크린 밖에서 처리되는 부분이 있습니다. 다양한 샘플링 모드( 즉 clamp/mirror )들이 다양한 결과를 산출하는데 사용될 수 있지만( m_amplerStateViewspaceDepthTab ), 최적의해결방법은 뎁스 퍼버를 생성하는 동안에 일정 비율만큼 더 크게 렌더링 영역과 해상도를 확장하는 것입니다. 그래서 AO 이펙트가 사용하는 데이터가 가장자리에서도 이용될 수 있게 합니다. ASSAO 는 선택적인 시저 사각형( scissor rectangle )을 사용해서 확장된 ( 보이지 않는 ) 영역들에 대한 AO 계산이 이루어지지 않도록 합니다.

  10. Texturing enabled
    AO 이펙트를 더 잘보이게 만들기 위해 ( 라이팅은 여전히 적용됨 ) 텍스쳐링을 토글합니다.

  11. Quality preset
    표 1 과 2 에서 설명되어 있듯이, 네 개의 품질 프리셋 사이에서 프리셋을 교체합니다.
    Highest/Adaptive 프리셋의 경우, Adaptive 타깃은 점진적인( progressive ) 품질 타깃을 제어하는데, 이는 품질과 성능을 빠르게 교환( trade-off )하기 위해 런타임에 변경될 수 있습니다.

  12. Switch to advanced UI
    이펙트를 더 자세히 디버깅하기 위해서, 샘플이 진보된 UI 로 변경되도록 할 수 있습니다. 이는 추가적인 씬들에 대한 접근을 제공하고 이펙트의 개발자 버전을 제공합니다. 이는 더 자세한 프로우파일링을 허용하며, 노멀, 검출된 가장자리, 선택된 픽셀에 대한 모든 AO 샘플들, adaptive effect heatmap 등을 보여 주는 다양한 디버그 뷰를 제공합니다.

Integration Details


DirectX 11 코드를 빠르게 통합하려면, 샘플 프로젝트에서 세 개의 파일들만 필요합니다:


  • Projects\ASSAO\ASSAO\ASSAO.h
  • Projects\ASSAO\ASSAO\ASSAODX11.h
  • Projects\ASSAO\ASSAO\ASSAO.hlsl


DirectX 11 API 를 제외한 다른 종속성 없이 전체 ASSAO 구현들이 포함되어 있습니다.


기본적인 ASSAO 통합 단계는 다음과 같습니다:


  1. ASSAO.h 와 ASSAODX11.cpp 를 프로젝트에 추가합니다.
  2. ASSAO.hlsl 파일을 로드할 수 있는 곳에다가 추가하십시오. 혹은 바이너리로 .hlsl 파일을 쉽게 임베드하는 방법( 그리고 커스텀 빌드 단계에 대한 )의 세부사항을 원한다면 ASSAOWrapperDX11.cpp "USE_EMBEDDED_SHADER" 를 참조하십시오.
  3. DirectX 11 디바이스 생성 후에, 정적 ASSAO_Effect::CreateInstance(...) 에다가 ID3D11Device 포인터와 셰이더 소스 버퍼를 제공함으로써, ASSAO_Effect 오브젝트 인스턴스를 생성하십시오. DirectX 디바이스가 파괴되기 전에 ASSAO_Effect::DestroyInstance() 를 호출해서 오브젝트를 파괴하는 것을 잊어 버리면 안 됩니다.
  4. 포스트 프로세싱 파이프라인 안에서 적절한 위치를 찾으십시오: SSAO 는 보통 스크린 스페이스 이펙트들이 실행되기 전에 라이트 누적( accumulation ) 버퍼나 포스트-톤맵 컬러 버퍼들에 직접적으로 적용되는데, 항상 곱( multiplication ) 블렌드 모드를 사용합니다. 라이팅 패스에서 나중에 사용하기 위한 개별 버퍼에다가 AO 항을 렌더링하기 위해 종종 더욱 물리적으로 정확한 접근법이 사용됩니다. 어떤 경우든지 간에, 요청되는 입력들은 씬 뎁스( 그리고 가능하다면 스크린 스페이스 노멀 )이므로, ASSAO 는 그것들을 이용할 수 있는 시점에 그려져야 합니다.
  5. 프레임당 입력 구조체를 ASSAO_InputsDX11 에서 채웁니다:
    1. SissorLeft/Right/Top/Bottom 은 Expand resolution 접근법이 사용되는 경우처럼 이펙트 출력이 더 작은 사각형으로 제한될 때만 사용됩니다. 그렇지 않으면 기본값인 0 이 사용되며, 이는 전체 뷰포트로 출력이 나간다는 것을 의미합니다.
    2. ViewportX/Y 는 반드시 0 이어야 하며 ViewportWidth/Height 는 입력 뎁스 텍스쳐 해상도 및 스크린 스페이스 노멀 텍스쳐 해상도와 출력 렌더 타깃의 크기여야 합니다.
    3. ProjectionMatrix 는 뎁스 버퍼를 그릴 때 사용된 프로젝션이어야 합니다. 왼손 좌표계와 오른손 좌표계가 역전된 Z( reversed Z )와 함께 모두 지원됩니다( http://outerra.blogspot.de/2012/11/maximizing-depth-buffer-range-and.html )( 역주 : 역전된 Z 와 관련해서는 [ Depth Precision Visualized ] 에 번역해 둔 다른 자료도 있습니다  ).
    4. NormalsWorldToViewspaceMatrix ( 선택적임 ) 는 입력 스크린 스페이스 노말이 뷰스페이스에 존재하지 않을 때 필요합니다. 이 경우에는 이 행렬이 뷰스페이스로 변환되어야 합니다.
    5. MatricesRowMajorOrder 는 입력 ProjectMatrix NormalsWorldtoViewspaceMatrix 의 메모리 레이아웃을 정의합니다.
    6. NormalsUnpackMul NormalsUnpackAdd 의 기본값은 2 와 -1 입니다. 그리고 노멀들을 일반적으로 저장되는 UNORM[0,1] 텍스쳐로부터 [-1,1] 범위로 언패킹하는데 사용됩니다. 노멀들이 부동소수점 수 텍스쳐로 제공된다면, 이 값들은 각각 1 (mul) 과 0 ( add ) 으로 설정될 필요가 있습니다.
    7. DrawOpaque 는 블렌딩 모드를 지정합니다: 이 값이 true 라면 선택된 렌더 타깃의 내용이 덮어써질 것입니다; 이 값이 false 라면 multiplicative 블렌딩 모드가 사용됩니다.
    8. DeviceContext ( DirectX 11 전용 ) 는 이펙트를 렌더링하는데 사용되는 ID3D11DeviceContext 포인터로 설정되어야 합니다.
    9. DepthSRV ( DirectX 11 전용 ) 는 입력 뎁스 데이터로 설정되어야 합니다.
    10. NormalSRV ( DirectX 11 전용 ) 는 입력 스크린 스페이스 노멀로 설정되거나 이용할 수 없다면 nullptr 로 설정되어야 합니다( 이 경우에 노멀들은 뎁스 데이터로부터 재구성됩니다 ).
    11. OverrideOutputRTV ( DirectX 11 전용 ) 는 nullptr 로 설정되거나 출력 렌더 타깃으로 설정되어야 합니다. 이 값이 nullptr 로 설정되면, 현재 선택되어 있는 RTV 가 사용됩니다.
  6. ASSAO_Settings 에 정의된 설정 구조체를 채웁니다. Sample overview 섹션에서 자세히 설명하고 있습니다.
  7. ASSAO_Effect::Draw 함수를 호출합니다. 현재 모든 DirectX 11 스테이트( state )들은 끈임없는 통합을 보장하기 위해서 그 호출 이후에 백업되고 복구됩니다.
샘플 프로젝트에 있는 다음 파일들은 통합 예제를 제공합니다:

  • Projects\ASSAO\ASSAOWrapper.h
  • Projects\ASSAO\ASSAOWrapper.cpp
  • Projects\ASSAO\ASSAOWrapperDX11.cpp


가장 최신의 소스 코드는 https:/github.com/GameTechDev/ASSAO 에서 다운로드할 수 있습니다.


Citations


[Bavoil et al. 2008] Bavoil, L., Sainz, M., and Dimitrov, R. 2008. "Image-Space Horizon-Based Ambient Occlusion.” In ACM SIGGRAPH 2008 talks, ACM, New York, NY, USA, SIGGRAPH ’08, 22:1–22:1.


[McGuire et al. 2012] Morgan McGuire, Michael Mara, David Luebke. “Scalable Ambient Obscurance.” HPG 2012.


[Bavoil 2014] Louis Bavoil, “Deinterleaved Texturing for Cache-Efficient Interleaved Sampling.” NVIDIA 2014.


Notices


This sample source code is released under the MIT License.

+ Recent posts