반응형




http://kyruie.tistory.com/31




원문 : http://wiki.gamedev.net/index.php/D3DBook:Screen_Space_Ambient_Occlusion


SSAO( Screen Space Ambient Occlusion )



컴퓨터로 생성된 이미지에 사실성을 향상시키기 위한 방법들은 매우 많다. 그런 방법들 중 하나가 물체의 라이팅 방정식을 이용해 값을 구할때 그림자 효과를 계산하는 방법이다. 실시간 컴퓨터 그래픽에서 유용한 그림자 기법들은 매우 많으며, 그러한 각각 기법들은 장단점을 모두 보인다. 일반적으로, 그림자 기법들은 그림자 품질과 실행 효율 사이의 균형을 취하려 노력한다.

그런 기법들중 하나가 바로 SSAOScreen Space Ambient Occlusion라고 불리는 기법이다. 이 기법은 Martin Mittring이 2007 SIGGRAPH 컨퍼런스에서 발표한 논문 "Finding Next Gen"에서 처음 논의되었다. 이 알고리즘의 기본 컨셉은  
 전역 조명 과정Ambient lighting term을 장면의 한 점이 얼마나 차폐되는지를 구하는 기반으로 바꾸는 것이다. 이 방법이 AO의 컨셉을 처음으로 이용하는 기법은 아니지만, 이후의 장chapter에서 보게 되겠찌만 SSAO는 꽤나 현명한 추정과단순함으로 매우 높은 성능을 유지하면서도 만족할만한 결과를 보여준다.



그림 1. SSAO를 이용한 샘플 렌더링 화면

이 번 장에서는, SSAO의 배경이 되는 이론을 살펴보고, Direct3d 10 파이프라인을 이용하여 이 기법을 구현하는 방법을 제공하며, 성능과 품질의 향상을 위해 구현 단계에서 사용할 수 있는 파라미터들에 대하여 논의할 것이다. 마지막으로, 주어진 구현을 이용한 데모에 대하여 논의하여 이를 통해 알고리즘의 성능에 대해서 몇 가지 사항을 알리고자 한다.

알고리즘 이론

이제 우리는 SSAO의 유래에 관한 배경지식에 대해서 살펴보았으므로, 기법에 대하여 더욱 자세하게 살펴볼 준비가 되었다. SSAO는 단 하나의 단순한 명제를 사용함으로써 이전의 기법들과는 다른점을 보인다: SSAO는 이전에 레스터화되기 이전의 장면 정보를 사용하는 대신 현재 장면에서 주어진 점의 차폐의 양을 구하는데 오직 깊이 버퍼만을 이용한다. 이를 위해 깊이 버퍼를 직접적으로 사용하는 방법이나 깊이 정보를 보관하기 위해 특별한 렌더타겟을 생성하는 방법 모두 가능하다. 깊이 정보는 주어진 점의 주변점을 구하는 즉시 세밀하게 조사하여 그 점이 얼마나 차폐되었는지 계산하는데 사용한다. 차폐 인수occlution factor은 한지점에 얼마만큼의 전역광을 적용할것인지, 그 양을 조절하는데 사용한다.

SSAO 알고리즘에서 사용하는 차폐 인수을 생성하는 방법은 논리적으로 두 단계 과정으로 이루어져 있다. 먼저 우리는 장면의 현재 시점을 기준으로 깊이 텍스처를 생성해야하고, 이 깊이 텍스처를 이용하여 현 장면의 최종 화면에서 각 픽셀의 차폐 정도를 결정한다. 이 과정은 아래의 그림 2에서 볼 수 있다.

그림2. SSAO 알고리즘의 개요
깊이 버퍼만을 사용하는 이 단순함은 성능과 품질면에서 몇가지 효과가 있다. 장면 정보가 렌더타겟으로 레스터화 하는 경우, 장면을 나타내는데 사용하는 정보가 3차원에서 2차원으로 줄어들게 된다. 데이터 축소는 매우 효율적인 명령을 제공하는 표준 GPU 파이프라인 하드웨어를 통해 수행된다. 또한 장면의 전체 차원을 줄임으로, 2D 장면 표현을 장면의 가시 영역으로 한정하여 이 프레임에 보이지 않는 물체에 대한 불필요한 연산을 제거할 수 있게 된다.

데이터 축소는 차폐 인수을 계산하는데 있어서 확실한 성능상의 이득을 제공하지만, 동시에 연산시에 필요한 정보 또한 제거한다. 이것은 우리가 계산으로 얻은 차폐 인수 값이 꼭 정확한 값이 아닐 수 있음을 의미하지만, 이후의 장에서 보게 되겠지만  전역 조명 과정은 근사치 일지라도 훌륭하게 장면의 현실감을 부여해 준다.

텍스처에 장면의 깊이 정보를 저장한 뒤, 깊이 값의 직접 인접에 기반하여 각 점이 얼마나 차폐되었는지 결정해야 한다. 이 연산은 다른 AO 기법들과 꽤나 비슷하다. 그림 3에 보이는 바와같이 깊이 버퍼를 고려해야한다 :

그림 3. 뷰view 방향이 아래쪽으로 향한 샘플 깊이 버퍼

이상적으로 주어진 점을 중심으로 둘러싼 반지름 r인 구를 생성하고, 그 구와 깊이 버퍼에 있는 물체와 교차하는 부피를 구하기 구를 따라 통합해 나간다. 이 컨셉은 여기 그림 4에서 볼 수 있다.

그림 4. 차폐를 계산하기 위한 이상적인 샘플링 구

물론, 렌더된 이미지의 모든 픽셀에서 복잡한 3D 통합을 수행하는 것은 전적으로 비효율적이다. 대신, 이 구의 부피 내에 존재하는 3D 샘플링 커널을 이용하여 이 구를 추정할 것이다. 샘플링 커널은 명시된 지점의 깊이 버퍼를 살펴, 그 각 가상의 점이 깊이 표면에 의해 가려지는지 결정하는데 이용된다. 샘플링 커널의 예시는 그림 5에 나타나 있으며, 우리의 표면점에 어떻게 적용해야 하는지도 보여준다.

그림 5. 단순화한 샘플링 커널과 깊이 버퍼 내에의 위치

차폐 인수는 차폐가 발생한 샘플링 커널의 합으로 구할 수 있다. 구현 부분에서 살펴보겠지만, 이 개별적인 계산은 카메라부터의 거리, 차폐 지점과 기준점 간의 거리, 아티스가 지정한 비례축소 인수 등의 몇가지 다른 인수들에 따라 더 민감하게, 혹은 덜 민감하게 할 수 있다.

구현

알고리즘이 어떻게 기능하는지 이해했따면, 이제 구현하는 방법에 대해 논의해 보자. 알고리즘 이론 파트에서 논의했듯이, 장면의 깊이 정보가 담긴 소스가 필요하다. 간단하게 하기 위해, 우리는 깊이 정보를 저장하기 위해 서로다른 부동소수 버퍼를 사용할 것이다. 비록 조금 더 복잡할지는 모르겠지만, 더 효율적인 기법은 장면의 깊이 값을 얻기 위해 z-버퍼를 이용할 것이다. The following code snippet shows how to create the floating point buffer, as well as the render target and shader resource views that we will be binding it to the pipeline with: 

01.// 깊이 버퍼 생성
02.D3D10_TEXTURE2D_DESC desc;
03.ZeroMemory( &desc, sizeof( desc ) );
04.desc.Width = pBufferSurfaceDesc->Width;
05.desc.Height = pBufferSurfaceDesc->Height;
06.desc.MipLevels = 1;
07.desc.ArraySize = 1;
08.desc.Format = DXGI_FORMAT_R32_FLOAT;
09.desc.SampleDesc.Count = 1;
10.desc.Usage = D3D10_USAGE_DEFAULT;
11.desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
12. 
13.pd3dDevice->CreateTexture2D( &desc, NULL, &g_pDepthTex2D );
14. 
15.// 렌더 타겟 리소스 뷰 생성
16.D3D10_RENDER_TARGET_VIEW_DESC rtDesc;
17.rtDesc.Format = desc.Format;
18.rtDesc.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2D;
19.rtDesc.Texture2D.MipSlice = 0;
20. 
21.pd3dDevice->CreateRenderTargetView( g_pDepthTex2D, &rtDesc, &g_pDepthRTV );
22. 
23.// 셰이더-리소스 뷰 생성
24.D3D10_SHADER_RESOURCE_VIEW_DESC srDesc;
25.srDesc.Format = desc.Format;
26.srDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
27.srDesc.Texture2D.MostDetailedMip = 0;
28.srDesc.Texture2D.MipLevels = 1;
29. 
30.pd3dDevice->CreateShaderResourceView( g_pDepthTex2D, &srDesc, &g_pDepthSRV );


깊이 정보를 생성한 후, 다음 단계는 최종 장면 내 각 픽셀의 차폐 인수를 계산하는 것이다. 이 정보는 두번째 단일 성분 부동소수 버퍼에 저장할 것이다. 이 버퍼를 생성하기 위한 코드는 부동소수 깊이 버퍼를 생성하기 위해 사용한 코드와 매우 유사하므로, 페이지 길이를 줄이기 위해 생략한다.

이제 두 버퍼가 모두 생성되었으므로, 각 버퍼에 저장할 정보를 생성하는 부분을 상세히 살펴보자. 깊이 버퍼는 뷰 공간의 깊이값을 기본적으로 저장한다. 절단 공간 깊이clip space depth 대신 선형 뷰 공간 깊이linear view space depth를 사용하여 투시 투영perspective projection으로 인한 깊이 범위 왜곡을 방지한다. 뷰 공간 깊이는 입력 버텍스와 월드뷰world-view 행렬을 곱해서 구할 수 있다. 그런뒤 뷰 공간 깊이는 단일 성분 버텍스 속성으로 픽셀 셰이더로 전달된다. 

01.fragment VS( vertex IN )
02.{
03.fragment OUT;
04.// 절단 공간 좌표를 출력
05.OUT.position = mulfloat4(IN.position, 1), WVP );
06.// 뷰 공간 좌표를 계산
07.float3 viewpos = mulfloat4( IN.position, 1 ), WV ).xyz;
08.// 뷰 공간 깊이값을 저장
09.OUT.viewdepth = viewpos.z;
10.return OUT;
11.}


깊이값을 부동소수 버퍼에 저장하기 위해, 픽셀 셰이더에서는 근거리 클리핑 평면과 원거리 클리핑 평면간의 거리에 따라 깊이값을 확대/축소한다. 이것은 범위 [ 0, 1 ]을 가진 선형, 정규화된 깊이 값을 생성한다. 

01.pixel PS( fragment IN )
02.{
03.pixel OUT;
04. 
05.// 뷰 공간 범위에 따라 깊이값을 확대/축소
06.float normDepth = IN.viewdepth / 100.0f;
07. 
08.// 확대/축소된 값을 출력
09.OUT.color = float4( normDepth, normDepth, normDepth, normDepth );
10. 
11.return OUT;
12.}


저장된 정규화된 깊이 정보를 가지고, 각 픽셀의 차폐 인수를 생성하기 위해 깊이 버퍼를 셰이더 리소스로 바인딩하고 각 차폐 버퍼에 저장한다. 차폐 버퍼 생성은 단일 전체 스크린 화면을 렌더링함으로써 초기화한다. 전체 스크린 화면의 버텍스들은 단지 단일 2-성분 속성을 가지고 있으며, 이는 깊이 버퍼 내의 자신의 위치에 대응하는 텍스처 좌표를 나타내고 있다. 버텍스 셰이더는 단순히 이 파라미터들을 픽셀 셰이더에 전달만 한다.

1.fragment VS( vertex IN )
2.{
3.fragment OUT;
4.OUT.position = float4( IN.position.x, IN.position.y, 0.0f, 1.0f );
5.OUT.tex = IN.tex;
6. 
7.return OUT;
8.}


필셀 셰이더는 3D 샘플링 커널의 형태를 3-성분 벡터의 배열로 정의하는 것으로 시작한다. 벡터의 길이는 [ 0, 1 ] 범위 사이에서 다양히 변하며 각 차폐 테스트에서 약간의 변화를 주게 된다.

01.const float3 avKernel[8] ={
02.normalizefloat3( 1, 1, 1 ) ) * 0.125f,
03.normalizefloat3( -1,-1,-1 ) ) * 0.250f,
04.normalizefloat3( -1,-1, 1 ) ) * 0.375f,
05.normalizefloat3( -1, 1,-1 ) ) * 0.500f,
06.normalizefloat3( -1, 1 ,1 ) ) * 0.625f,
07.normalizefloat3( 1,-1,-1 ) ) * 0.750f,
08.normalizefloat3( 1,-1, 1 ) ) * 0.875f,
09.normalizefloat3( 1, 1,-1 ) ) * 1.000f
10.}


다음으로, 픽셀 셰이더는 텍스처 룩업 내에서 샘플링 커널을 반사시키기 위한 렌덤 벡터를 찾는다. 이것은 사용한 샘플링 커널을 이용해 매우 다양한 변화를 줄 수 있으며, 이는 적은 수의 차폐 테스트를 하더라도 높은 수준의 결과를 제공할 수 있게 해준다. 이는 차폐를 계산하기 위한 깊이를 효과적으로 "흐트려jitter" 주어, 우리가 현재 픽셀의 주변 공간을 언더샘플링 한다는 사실을 숨겨준다.

1.float3 random = VectorTexture.Sample( VectorSampler, IN.tex.xy * 10.0f ).xyz;random = random * 2.0f - 1.0f;


이제 픽셀 셰이더가 현제 픽셀의 깊이값을 바탕으로 샘플링 커널에 적용하기 위한 확대/축소값을 계산할 것이다. 이 픽셀의 깊이값은 깊이 버퍼로부터 읽어들여 근거리 평면과 원거리 평면간의 거리를 곱함으로 뷰 공간으로 도로 확장된다. 그런 뒤 샘플링 커널의 x 와 y 성분을 위한 확대/축소값을 계산하는데, 이는 샘플링 커널의 희망 반지름( 미터 단위 )을 픽셀의 깊이값( 미터 단위 )로 나누면 된다. 이는 개별 샘플을 찾기위해 사용되는  텍스처 좌표를 확대/축소한다. z 성분의 확대/축소값은 희망 커널 반지름을 근거리 평면과 원거리 평면간의 거리로 나누어 구할 수 있다. 이는 모든 깊이값의 비교를 우리가 깊이 버퍼에 저장한것과 같은 정규화된 깊이 공간에서 이루어지도록 하게 해준다.

1.float fRadius = vSSAOParams.y;
2.float fPixelDepth = DepthTexture.Sample( DepthSampler, IN.tex.xy ).r;
3.float fDepth = fPixelDepth * vViewDimensions.z;
4.float3 vKernelScale = float3( fRadius / fDepth, fRadius / fDepth, fRadius / vViewDimensions.z );


커널 확대/축소값이 구해지면, 개별 차폐 테스트를 수행할 수 있게 된다. 이것은 for 루프 내에서 샘플링 커널이 가르키는 각 점들을 계속해서 반복하는 것으로 이루어진다. 현재 픽셀의 텍스처 좌표는 렌덤하게 반사된 커널 벡터의 x와 y 성분을 통해 차감 계산되고 새 좌표에서 깊이값을 살펴보기 위해 사용된다. 이 깊이 값은 커널 벡터의 z 성분을 통해 차감 계산되고 현재 픽셀의 깊이와 비교된다. 
 
01.float fOcclusion = 0.0f;
02.for int j = 1; j < 3; j++ )
03.{
04.float3 random = VectorTexture.Sample( VectorSampler, IN.tex.xy * ( 7.0f + (float)j ) ).xyz;
05.random = random * 2.0f - 1.0f;
06. 
07.for int i = 0; i < 8; i++ )
08.{
09.float3 vRotatedKernel = reflect( avKernel[i], random ) * vKernelScale;
10.float fSampleDepth = DepthTexture.Sample( DepthSampler, vRotatedKernel.xy + IN.tex.xy ).r;
11.float fDelta = max( fSampleDepth - fPixelDepth + vRotatedKernel.z, 0 );
12.float fRange = abs( fDelta ) / ( vKernelScale.z * vSSAOParams.z );
13.fOcclusion += lerp( fDelta * vSSAOParams.w, vSSAOParams.x, saturate( fRange ) );
14.}
15.}


깊이값의 델타값( = 차이값 )은 어플리케이션의 선택가능한 범위값으로 정규화된다. 이것은 깊이값 차이의 관계 등급을 결정하기 위한 인수를 생성하기 위함이다. 차례로, 이 정보는 이 특정의 차폐 테스트의 범위를 수정할 수 있다. 예를 들어, 한 물체가 장면의 전경에 위치하고 다른 하나의 물체가 그 뒤에 부분적으로 가려져 있다면, 전경의 물체가 유일한 차폐물인 경우 뒷쪽 물체를 위해 불필요한 차폐 테스트를 계산할 필요가 없다. 반대로 배경의 물체에는 앞 물체의 가장자리를 따라 그림자 같은 후광이 나타날 것이다. The implementation of this scaling is to linearly interpolate between a scaled version of the delta value and a default value, with the interpolation amount based on the range value. 

1.fOcclusion += lerp( ( fDelta * vSSAOParams.w ), vSSAOParams.x, saturate( fRange ) );


최종 픽셀 색상을 내놓기 전의 마지막 단계는 모든 커널 샘플로부터 평균 차폐값을 계산하고, 그 값을 최대/최소 차폐 값 사이를 보간하는데 사용하는 것이다. 이 마지막 보간은 광범위한 차폐값을 압축해주고 보다 부드러운 출력을 제공해준다. 이 장의 데모 프로그램에서 주의할 것은, 사진의 차폐를 계산하는데 단지 16샘플만을 사용했다는 것이다. 만일 더 많은 샘플을 사용했다면, 출력 차폐 버퍼는 더 부드러운 결과를 보여줄 것이다. 이것은 다른 등급의 하드웨어들에서 성능과 품질을 조정하는 좋은 방법이 된다.
 
1.OUT.color = fOcclusion / ( 2.0f * 8.0f );
2. 
3.// 범위 재매핑
4.OUT.color = lerp( 0.1f, 0.6, saturate( OUT.color.x ) );


생성한 차폐 버퍼를 가지고, 최종 렌더링 패스에서 셰이더 자원에 포함해 이를 이용할 수 있다. 렌더된 기하는 단수히 스크린 공간 텍스쳐 좌표를 계산하고, 차폐 버퍼를 샘플링한 뒤, 그 값을 이용하여 ambient 조건을 조정하면 된다. 예시로 제공되는 파일은 단순히 다섯 샘플의 평균을 이용하는 방법을 사용하였지만, 가우시안 브럴와 같은 좀더 세련된 방법을 대신 사용하는 것도 좋다.


SSAO 데모

데모 다운로드 : SSAO_Demo

이번 장을 위해 만든 데모 프로그램은 단순히 다수의 정방면체를 우리의 SSAO 셰이더만을 이용하여 렌더링한 것이다. 이번 기법에서 논의된 조절가능한 파라미터들에 대해서는 화면상의 슬라이더 콘트롤러를 이용하여 실시간으로 바꿀 수 있다. 그림 6 이하는 차폐 버퍼의 모습과 최종 출력 렌더링의 결과를 볼 수 있다. 한가지 알릴 사실은 차폐 효과를 보다 과장하기 위하여 차폐 파라미터들을 조절했다. 

그림 6. 데모 프로그램의 차폐 버퍼의 모습


그림 7. 데모 프로그램의 최종 출력 렌더링의 모습

결론 

In this chapter we developed an efficient, screen space technique for adding realism to the ambient lighting term of the standard phong lighting model. This technique provides one implementation of the SSAO algorithm, but it is certainly not the only one. The current method can be modified for a given type of scene, with more or less occlusion for distant geometry. In addition, the minimum and maximum amounts of occlusion, interpolation techniques, and sampling kernels are all potential areas for improvement or simplification. This chapter has attempted to provide you with an insight into the inner workings of the SSAO technique as well as a sample implementation to get you started.










http://www.eppengine.com/zbxe/programmig/2982



SSAO 는 최근에 많이 이슈가 되고 있는 GI 기법중 하나이다.

 

GI 라고 하면 단순히 모든 오브젝트가 빛을 발산하는 주체가 된다고만 생각하는데, (빛 반사를 통해.. )

 

빛으로인해 생겨지는 그림자 역시 GI중 하나이다.

 

SSAO 는 많은 사람들이 알고 있듯이 환경광 차폐를 화면공간에서 처리하는 기법으로

 

크게 깊이를 이용한 기법, 깊이와 상방벡터를 이용하는 기법 두가지가 있다.

 

환경광 차폐가 일어나는 경우에 대해서는 KGC2009 강연자료중 Lighting In Screen Space 의 ppt 자료를 참고.

 

여하튼.. 위에서 이야기한 두가지 기법 모두 장단이 있기에 적절한 방식을 선택해서 사용하면 되겠다.

 

 

 

uniform sampler2D som;  // Depth texture 

uniform sampler2D rand; // Random texture 
uniform vec2 camerarange = vec2(1.01024.0);
      
   float pw = 1.0/800.0*0.5
   float ph = 1.0/600.0*0.5;  

   float readDepth(in vec2 coord)  
   {  
     if (coord.x<0||coord.y<0return 1.0;
      float nearZ = camerarange.x;  
      float farZ =camerarange.y;  
      float posZ = texture2D(som, coord).x;   
      return (2.0 * nearZ) / (nearZ + farZ - posZ * (farZ - nearZ));  
   }   

   float compareDepths(in float depth1, in float depth2,inout int far)  
   {  

     float diff = (depth1 - depth2)*100//depth difference (0-100)
     float gdisplace = 0.2//gauss bell center
     float garea = 2.0//gauss bell width 2

     //reduce left bell width to avoid self-shadowing
     if (diff<gdisplace){ 
        garea = 0.1;
     }else{
        far = 1;
     }
     float gauss = pow(2.7182,-2*(diff-gdisplace)*(diff-gdisplace)/(garea*garea));

     return gauss;
   }  

   float calAO(float depth,float dw, float dh)  
   {  
     float temp = 0;
     float temp2 = 0;
     float coordw = gl_TexCoord[0].x + dw/depth;
     float coordh = gl_TexCoord[0].y + dh/depth;
     float coordw2 = gl_TexCoord[0].x - dw/depth;
     float coordh2 = gl_TexCoord[0].y - dh/depth;

     if (coordw  < 1.0 && coordw  > 0.0 && coordh < 1.0 && coordh  > 0.0){
     vec2 coord = vec2(coordw , coordh);
        vec2 coord2 = vec2(coordw2, coordh2);
        int far = 0;
     temp = compareDepths(depth, readDepth(coord),far);

        //DEPTH EXTRAPOLATION:
        if (far > 0){
          temp2 = compareDepths(readDepth(coord2),depth,far);
          temp += (1.0-temp)*temp2; 
        }
     }

     return temp;  
   }   
     
   void main(void)  
   {  
     //randomization texture:
     vec2 fres = vec2(20,20);
     vec3 random = texture2D(rand, gl_TexCoord[0].st*fres.xy);
     random = random*2.0-vec3(1.0);

     //initialize stuff:
     float depth = readDepth(gl_TexCoord[0]);  
     float ao = 0.0;

     for(int i=0; i<4; ++i) 
     {  
       //calculate color bleeding and ao:
       ao+=calAO(depth,  pw, ph);  
       ao+=calAO(depth,  pw, -ph);  
       ao+=calAO(depth,  -pw, ph);  
       ao+=calAO(depth,  -pw, -ph);

       ao+=calAO(depth,  pw*1.20);  
       ao+=calAO(depth,  -pw*1.20);  
       ao+=calAO(depth,  0, ph*1.2);  
       ao+=calAO(depth,  0, -ph*1.2);
     
       //sample jittering:
       pw += random.x*0.0007;
       ph += random.y*0.0007;

       //increase sampling area:
       pw *= 1.7;  
       ph *= 1.7;    
     }         

     //final values, some adjusting:
     vec3 finalAO = vec3(1.0-(ao/32.0));


     gl_FragColor = vec4(0.3+finalAO*0.7,1.0);  
   }  

장점 : 따로 blur pass 를 실행할 필요가 없다. ( 랜덤맵 텍스쳐를 활용하기에 가능한 부분)

           시각적 품질이 나쁘지 않다.

           노멀 버퍼없이도 깔끔하다.

 

단점 : 전통적 ssao 보다는 좀 느리다.

           역시 노멀 버퍼를 사용하지 않는 것 으로 인한 약간의 시각적 어색함이 존재.. 약간...








http://ozlael.egloos.com/2963328



SSAO (Screen Space Ambient Occlusion) 링크 모음 Game develop




AO(Ambient Occlusion)는 사실적인 그림자 효과 라이팅의 방법 중 하나로써, 전역 조명 과정에서 한 점의 차폐 양을 계산 하는 것을 나타낸다. 이로써 장면 내의 입체 볼륨감을 더욱 부각시킬 수 있다. SSAO는 이를 Screen Space에서 수행하는 것이다. HBAO, SSDO등도 이와 한 뿌리다. 

실제 적용 해보면 제일 애를 먹는 것이 half-resolution에서 AO 처리를 한 뒤 upscale을 하는 부분인데, 이는 inferred lighting의 DSF필터를 적용 하면 쉽게 해결 될 듯 하다.( DSF 적용 해보진 않음;; 언능 해봐야집)


하지만 지글지글 문제는 해결이 안되지 싶은데.. 이놈때문에 엔진 디폴트로 AO는 꺼트린 상태다. 섬바뤼헬미~

관련 링크 (문서 내 링크 중복도 많이 있다 =ㅈ=):

http://www.gamedev.net/community/forums/topic.asp?topic_id=545825
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
http://www.gamerendering.com/2009/01/14/ssao/
http://www.gamedev.net/community/forums/topic.asp?topic_id=550699
http://www.vizerie3d.net/
http://developer.download.nvidia.com/presentations/2008/SIGGRAPH/HBAO_SIG08b.pdf
http://developer.download.nvidia.com/presentations/2008/GDC/GDC08_Ambient_Occlusion.pdf
http://developer.download.nvidia.com/SDK/10.5/direct3d/Source/ScreenSpaceAO/doc/ScreenSpaceAO.pdf
http://gamepro.tistory.com/539
http://www.gamedev.net/reference/programming/features/simpleSSAO/

반응형

+ Recent posts