SSAO and Kawase Blur
개인적으로는 SSAO 를 사용하지 않고 있고 이 전 프로젝트에서도 5년 전부터는 사용하지 않았습니다. 최근에는 GTAO 도 모바일 디바이스 게임개발 환경에서 자주 사용되고 있을 만큼 최적화가 되었습니다. 게다가 SSAO 를 아티스트나 아트디렉터분들이 별로 안좋아하더라고요... 시각적인 품질이 좀... ;
1주일 전쯤부터 유니티6 렌더그래프에 GroundTruth AO 피처를 추가 하는 과정에서 피처와 페스 업그레이드 때문에 살펴 보던 와중에... 간단히 서머리 해 보는 것도 나쁘지 않겠다 생각이 들었네요.
신입들을 만나게 되면 꼭 올드스쿨 이라고 해서 변천사를 좀 아는 것이 그 다음 5년 후의 변천과 미묘한? 연결점도 있다고 생각 합니다. 그리고 또 예전 기술의 일부는 여전히 쓰이고 있는 것도 사살 이거든요.
Morgan 2011의 "Alchemy screen-space ambient obscurance algorithm"은 게임 엔진에서 사용되는 중요한 Screen Space Ambient Occlusion(SSAO) 알고리즘입니다. NVIDIA Research에서 발표된 이 알고리즘의 주요 특징은 다음과 같습니다:
주요 시각적 효과
- 모서리, 균열, 주름의 어두워짐
- 근접 차폐(proximity darkening)
- 접촉 그림자(contact shadows)
핵심 기술적 특징
- 화면 공간 차폐(screen-space obscurance)의 새로운 유도 방식 사용
- visibility integral에서 falloff 함수를 사용하여 효율적인 연산 구현
- 깊이 버퍼와 노말 버퍼에서 샘플 포인트를 읽어 차폐도 추정
조절 가능한 4가지 파라미터
- World-space radius (월드 공간 반경)
- Bias (편향)
- Intensity (강도)
- Contrast (대비)
이 알고리즘은 현재 Unity URP의 SSAO 구현의 기반이 되었으며, 실시간 렌더링에서 효율적으로 주변 차폐 효과를 생성할 수 있는 방법을 제시했습니다.
이 알고리즘의 가장 큰 장점은 다양한 스케일의 지오메트리에서 차폐를 포착할 수 있고, 표면에 자연스럽게 순응하는 접촉 그림자를 만들 수 있다는 점입니다.
최적화를 위해(매우 보편적인) Blue Noise 텍스처를 사용하고 있으며 다운셈플링을 지원하고 최근 XR/VR 을 위한 Foveated 렌더링을 지원 합니다.
블러필터 옵션을 보면
- Bilateral Blur
- Gaussian Blur
- Kawase Blur
이렇게 3가지가 있습니다.
우리는 Kawase Blur 에 관심을 갖을 필요가 있습니다.
Bloom 을 최적화 할 때도 사용할 수 있기 때문입니다.
// ------------------------------------------------------------------
// Kawase Blur
// ------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Developed by Masaki Kawase, Bunkasha Games
// Used in DOUBLE-S.T.E.A.L. (aka Wreckless)
// From his GDC2003 Presentation: Frame Buffer Postprocessing Effects in DOUBLE-S.T.E.A.L (Wreckless)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
half KawaseBlurFilter( half2 texCoord, half2 pixelSize, half iteration )
{
half2 texCoordSample;
half2 halfPixelSize = pixelSize * HALF_HALF;
half2 dUV = ( pixelSize.xy * half2( iteration, iteration ) ) + halfPixelSize.xy;
half cOut;
// Sample top left pixel
texCoordSample.x = texCoord.x - dUV.x;
texCoordSample.y = texCoord.y + dUV.y;
cOut = SAMPLE_BASEMAP_R(texCoordSample);
// Sample top right pixel
texCoordSample.x = texCoord.x + dUV.x;
texCoordSample.y = texCoord.y + dUV.y;
cOut += SAMPLE_BASEMAP_R(texCoordSample);
// Sample bottom right pixel
texCoordSample.x = texCoord.x + dUV.x;
texCoordSample.y = texCoord.y - dUV.y;
cOut += SAMPLE_BASEMAP_R(texCoordSample);
// Sample bottom left pixel
texCoordSample.x = texCoord.x - dUV.x;
texCoordSample.y = texCoord.y - dUV.y;
cOut += SAMPLE_BASEMAP_R(texCoordSample);
// Average
cOut *= half(0.25);
return cOut;
}
half4 KawaseBlur(Varyings input) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
half2 uv = input.texcoord;
half2 texelSize = _SourceSize.zw * rcp(DOWNSAMPLE);
half col = KawaseBlurFilter(uv, texelSize, 0);
col = HALF_ONE - col;
return half4(col, col, col, 1);
}
SSAO.hlsl 에 포함 된 카와세 블러 코드블럭 입니다.
KawaseBlurFilter 함수.
half KawaseBlurFilter(half2 texCoord, half2 pixelSize, half iteration)
4개의 이웃 픽셀을 샘플링한 후 블러 효과를 생성 합니다.
픽셀의 UV 좌표, 텍스처의 텍셀 크기 및 블러 이터레이션 회수를 매개변수로 갖습니다.
현재 픽셀을 중심으로 4개의 코너 픽셀을 샘플링 하고 각 샘플의 R 채널 값을 수집하여 평균을 낸 후 최종 블러값을 위해 0.25를 곱합니다.
KawaseBlur 함수.
half4 KawaseBlur(Varyings input) : SV_Target
KawaseBlurFilter를 실제로 적용하는 픽셀 셰이더 스테이지 입니다.
UV 좌표와 텍셀 크기 계산을 하고 KawaseBlurFilter 를 적용 합니다. 결과값을 반전하여 SSAO 에 적합한 형태로 변환 합니다. 이때 그레이스케일 값을 RGBA 로 확장 하여 반환 합니다. Kawase Blur 는 다른 블러 방식들에 비해 성능 측면에서 좋지만 품질은 낮은 특징이 있습니다. 모바일 디바이스 성능이 제한된 환경에서 유용 하며 품질이 낮은 부분을 Dual Filter 로 개선 할 수 있는 여지가 있습니다.
관심 있게 카와세 블러와 듀얼 카와세 블러 등으로 살펴볼 수 있습니다.
아래 git link 처럼
URP 카와세 블러
UI 의 Blur 에도 주로 사용 됩니다.
듀얼 카와세 블러
AMD 에서 오래 전 발표 한 아래 내용도 매우 좋은 참조자료가 됩니다.
듀얼 필터링.