프로그래밍 2014.01.13 16:38


깊이 버퍼 그림자 (5) 장의 쉐이더 코드와 연결됩니다.


코드 보기가 용이하게, 스플래팅 관련과 포그 등의
처리 부분을 삭제하였습니다.

 

그림자의 외곽을 좀더 스무드하게 처리하기 위한
픽셀 샘플링 코드가 포함되었습니다.

픽셀 샘플링을 수행하지 않을 경우, 그림자의 퀄리티는 떨어지게 되지만,

드로우 처리가 빨라지게 됩니다.

 


//---------- offset 에 해당하는 픽셀의 색상을 계산합니다.
float Get_Pixel_Depth( sampler2D _tex, float2 _uv, float _w, float2 _offset )
{
 float2 uv = _uv;

 

 //float fW = 8192.f * 4; //이값 사용과 밑 수식 사용 결과가 다르다
 uv.x += ( (_offset.x / 8192.f) ) * 4.f; // 수치 대입에 따라 다양하게 샘플링된다.
 uv.y += ( (_offset.y / 8192.f) ) * 4.f; //앞쪽 수치가 커질수록 적용 픽셀이 미세해진다.
                                                  //뒤쪽 수치가 커질수록 넓은 영역을 커버.

 

 return tex2D( _tex, uv ).r;
}

 

//----------
float4 Ret_Color_Def( VS_OUTPUT _In, float cur_depth )
{
  float4 layer_image = tex2D( Samp_Tex_0, _In.uv ); // one layer
  layer_image.xyz *= cur_depth; // w값은 알파값이기 때문에,

                                            // w값이 반투명하게 되면 배경색과 섞이게 된다! 

  return layer_image;
}

 

//---------- 픽셀 샘플링 함수
//fStep 값을 크게 주면, 좀더 퀄리티 좋은 샘플을 얻을 수 있습니다.
//물론 그만큼 부하가 많이 걸리기는 합니다(^^;;;)
float4 Ret_Color_Sampling( VS_OUTPUT _In, sampler2D _tex, float2 uv, float cur_depth )
{
 float depth = 0;
 float x, y;
 float fCountShadow = 0;
 float fCountSampling = 0;

 

 //컬러 샘플링
 const float fStep = 1.5f;
 for( y = -fStep; y < fStep; y += 1 )
 {
   for( x = -fStep; x < fStep; x += 1 )
  {
     depth = Get_Pixel_Depth( _tex, uv, _In.depth_0.w, float2(x, y) );

     //뎁스값 비교
     if( cur_depth > depth )
     {
        fCountShadow += 1.f;
     }
     fCountSampling += 1;
   }
 }

 

 float fAllCountShadow = fCountShadow / fCountSampling;


 //cur_depth = cur_depth * 0.7f * fAllCountShadow;

 //return float4( fC, fC, fC, 1.0f );

 

 //orthoview
 //에서는 뎁스값이 매우 낮은듯, 시커멓게 나온다
 //임의적으로 조정해준다.
 cur_depth = 1;

 

 //색보정입니다, 수치는 테스트를 통하여 조절하였습니다.

 float fShadowColor = 1.0f - fAllCountShadow + 0.5;
 if( fShadowColor > 1.0f )
    fShadowColor = 1; // 값이 1보다 크면 빛나게 된다

  
 return Ret_Color_Def( _In, cur_depth * fShadowColor ); 
}

 

//샘플링 처리를 뺄때는,

//결과적으로 픽셀의 컬러를 어둡게 처리해주면 됩니다.

float4 Ret_Color_Sampling( VS_OUTPUT _In, sampler2D _tex, float2 uv, float cur_depth )
{

  //모두 삭제

  //그냥 간단하게

  return Ret_Color_Def( _In, 0.7f );

}

 


//static global value
static bool g_bIsColor = false;
static const float4 g_Color_White = float4( 1,1,1,1 );

 

//----------
//자기 픽셀에 그림자가 드리워졌는지를 검사하는 함수
//_iIdx 인수는 근거리, 중거리, 원거리 구분입니다.

 

//코드에는 포함되어 있지 않지만, 몇가지 테스트를 하느라,

//인수로 _iIdx 를 받았습니다만,

//if, else 비교가 세번이나 들어가므로 좋은 처리는 아닙니다.

//_iIdx 인수를 빼고, 인수로 직접 뎁스값과 텍스쳐값을 넣어주고,

//세번의 if 비교를 빼는 것이 보기에도 좋고, 처리 부하가 좀 더 줄어들 것입니다


float4 Is_Shadow( VS_OUTPUT _In, int _iIdx )
{
  float2 uv;
  uv.x = uv.y = 0;
  float fOut = 1.0f;
  float cur_depth = 1;

  float4 color = g_Color_White;
  float shadow_depth;

 
  if( 0 == _iIdx )
  {
    uv = _In.depth_0.xy / _In.depth_0.w; 
    cur_depth = _In.depth_0.z / _In.depth_0.w;
  }
  else if( 1 == _iIdx )
  {
    uv = _In.depth_1.xy / _In.depth_1.w; 
    cur_depth = _In.depth_1.z / _In.depth_1.w;
  }
  else if( 2 == _iIdx )
  {
    uv = _In.depth_2.xy / _In.depth_2.w; 
    cur_depth = _In.depth_2.z / _In.depth_2.w;
  }
 

  //프러스텀 영역안에( -1 ~ 1 ) 들어올때만 그려주어야 한다.
  //체크안하면 그림자가 여기저기에 생김.
  if( uv.x < -fOut || uv.x > fOut
   || uv.y < -fOut || uv.y > fOut
   || cur_depth < -fOut || cur_depth > fOut
   )
  {
    g_bIsColor = false;
    return g_Color_White;
  }

 

  //(-1~1) -> (0~1)
  //프로젝션의 좌표영역을 uv 좌표 영역으로 바꾸어 주어야 합니다.
  uv.y = -uv.y;
  uv = uv * 0.5 + 0.5;


  if( 0 == _iIdx )
  {
   shadow_depth = tex2D( Samp_Depth_0, uv ).r;
  }
  else if( 1 == _iIdx )
  {
   shadow_depth = tex2D( Samp_Depth_1, uv ).r;
  }
  else if( 2 == _iIdx )
  {
   shadow_depth = tex2D( Samp_Depth_2, uv ).r;
  }

 

  //나의 뎁스값이 그림자 뎁스값보다 큰 경우는 내 앞을 가리는 그림자가 있는 것으로 판단합니다.
  //이 부분에 대한 설명은 깊이 버퍼 그림자 (1)장을 참고하시기 바랍니다.
  if( cur_depth > shadow_depth )
  {
    g_bIsColor = true;

    if( 0 == _iIdx )
    {
      return Ret_Color_Sampling( _In, Samp_Depth_0, uv, cur_depth );
    }
    else if( 1 == _iIdx )
    {   
      return Ret_Color_Sampling( _In, Samp_Depth_1, uv, cur_depth );

      //cur_depth = 1.f;
      //return Ret_Color_Def( _In, cur_depth * 0.6f );
    }
    else if( 2 == _iIdx )
    {
     return Ret_Color_Sampling( _In, Samp_Depth_2, uv, cur_depth );

     //cur_depth = 1.f;
     //return Ret_Color_Def( _In, cur_depth * 0.6f );
    }
  }

 

  //
  g_bIsColor = false;
  return g_Color_White;
}

 

 

 

 

저작자 표시 비영리 변경 금지
신고
posted by 게임스타 게임스타

댓글을 달아 주세요