아래에서 퍼옴
http://eppengine.com/zbxe/programmig/2982


SSAO (Screen Space Ambient Occlusion) 처리 기법(소스포함)

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.0, 1024.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<0) return 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.2, 0); 
       ao+=calAO(depth,  -pw*1.2, 0); 
       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 보다는 좀 느리다.
         역시 노멀 버퍼를 사용하지 않는 것 으로 인한 약간의 시각적 어색함이 존재.. 약간...


'게임 개발 > 3D 게임 플밍' 카테고리의 다른 글

3d max plugin wizard 생성하기  (0) 2010.03.17
Light Shaft  (0) 2010.03.17
SSGI 관련 정리 (소스 포함)  (0) 2010.03.17
언리얼 엔진 3 ( Unreal Engine 3 )  (0) 2009.12.03
BSP를 이용한 3D Game Programming  (0) 2005.11.16
Posted by 노을삼킨별
,