그림자 기법을 평정한 그림자매핑

 

 

-요약 이론-

그림자 생성단계

1. 랜더링 결과 (빛을 가로막은 첫번째 물체의 깊이)를 저장할 랜더 타깃을 정해준다.

2. 카메라를 광원 위치에 두고 물체들을 그린다.

3. 픽셀 셰이더에서 빛으로부터 현재 픽셀까지의 깊이를 반환한다.

 

그림자 적용단계

1. 랜더링 결과(일반 장면랜더링)를 화면(백버퍼)에 저장한다.

2. 카메라를 눈 위치에 두고 물체를 그린다.

3. 빛으로부터 현재 픽셀까지의 깊이를 그림자맵에 담겨있는 결과와 비교한다. 현재 깊이가 그림자맵의 깊이보다 크면 그림자를 씌운다.

 

 

 

 

 

그림자만들기위한 정점 셰이더

 

struct VS_INPUT {
   float4 mPosition : POSITION;
};

struct VS_OUTPUT{
   float4 mPosition : POSITION;
   float4 mClipPosition : TEXCOORD1;
};

 

float4x4 gWorldMatrix;
float4x4 gLightViewMatrix;
float4x4 gLightProjectionMatrix;

float4 gWorldLightPosition;

 

 

VS_OUTPUT vs_main(VS_INPUT Input){
   VS_OUTPUT Output;
  
   float4x4 lightViewMatrix = gLightViewMatrix;
  
   float3 dirZ = -normalize(gWorldLightPosition.xyz);
   float3 up = float3(0,1,0);
   float3 dirX = cross(up, dirZ);
   float3 dirY = cross(dirZ, dirX);
  
   lightViewMatrix = float4x4(
      float4(dirX, -dot(gWorldLightPosition.xyz, dirX)),
      float4(dirY, -dot(gWorldLightPosition.xyz, dirY)),
      float4(dirZ, -dot(gWorldLightPosition.xyz, dirZ)),
      float4(0, 0, 0, 1));
   lightViewMatrix = transpose(lightViewMatrix);
  
   Output.mPosition = mul(Input.mPosition, gWorldMatrix);
   Output.mPosition = mul(Output.mPosition, lightViewMatrix);
   Output.mPosition = mul(Output.mPosition, gLightProjectionMatrix);
  
   Output.mClipPosition = Output.mPosition;
  
   return Output;

  
}
//gLightViewMatrix  = 대입할 시멘틱이 없어서 정점 셰이더에서 구현했다고함.

 

 

 

 

 

그림자만들기위한 픽셀 셰이더

 

struct PS_INPUT{
   float4 mClipPosition : TEXCOORD1;
};

 

 

float4 ps_main(PS_INPUT Input) : COLOR
{
  
   float Depth = Input.mClipPosition.z / Input.mClipPosition.w;
   return float4(Depth.xxx,1);
  
}

float4x4 gWorldMatrix;
float4x4 gLightViewMatrix;
float4x4 gLightProjectionMatrix;

float4 gWorldLightPosition;
//동차좌표에 있는 값을 화면상의 좌표값으로 사용하려면 w 값을 1로 바꿔 줘야한다.

 

 

 

 

 

 

 

 

 

그림자 입히기 위한 셰이더-원환체

 

정점 셰이더 코드

 


struct VS_INPUT{
   float4 mPosition : POSITION;
   float3 mNormal : NORMAL;
};

struct VS_OUTPUT{
   float4 mPosition : POSITION;
   float4 mClipPosition : TEXCOORD1;
   float mDiffuse : TEXCOORD2;
};

float4x4 gWorldMatrix;
float4x4 gLightProjectionMatrix;
float4x4 gLightViewMatrix;

float4 gWorldLightPosition;

float4x4 gViewProjectionMatrix;

 

VS_OUTPUT vs_main( VS_INPUT Input )
{
   VS_OUTPUT Output;
 
   float4x4 lightViewMatrix = gLightViewMatrix;

   float3 dirZ = -normalize(gWorldLightPosition.xyz);
   float3 up = float3(0,1,0);
   float3 dirX = cross(up, dirZ);
   float3 dirY = cross(dirZ, dirX);
  
   lightViewMatrix = float4x4(
      float4(dirX, -dot(gWorldLightPosition.xyz, dirX)),
      float4(dirY, -dot(gWorldLightPosition.xyz, dirY)),
      float4(dirZ, -dot(gWorldLightPosition.xyz, dirZ)),
      float4(0, 0, 0, 1));
   lightViewMatrix = transpose(lightViewMatrix);

 

 

   float4 worldPosition = mul(Input.mPosition, gWorldMatrix);
   Output.mPosition = mul(worldPosition, gViewProjectionMatrix);

   Output.mClipPosition = mul(worldPosition, lightViewMatrix);
   Output.mClipPosition = mul(Output.mClipPosition, gLightProjectionMatrix);
  
   float3 lightDir = normalize(worldPosition.xyz - gWorldLightPosition.xyz);
   float3 worldNormal = normalize(mul(Input.mNormal, (float3x3)gWorldMatrix));
   Output.mDiffuse = dot(-lightDir, worldNormal);
  
   return Output;
  
}

 

 

 

픽셀 셰이더 코드

 

sampler2D ShadowSampler;
float4 gObjectColor;

struct PS_INPUT{
   float4 mClipPosition : TEXCOORD1;
   float mDiffuse : TEXCOORD2;
};

float4 ps_main(PS_INPUT Input):COLOR
{
   float3 rgb = saturate(Input.mDiffuse ) * gObjectColor;
   float currentDepth = Input.mClipPosition.z / Input.mClipPosition.w;
  
   float2 uv = Input.mClipPosition.xy /Input.mClipPosition.w;
   uv.y = -uv.y;
   uv = uv * 0.5 +0.5;
  
   float shadowDepth = tex2D(ShadowSampler, uv).r;
  
   if(currentDepth > shadowDepth + 0.0000125f){
      rgb *= 0.5f;
   }
  
   return float4(rgb,1.0f);
}

 

 

 

 

 

 

 

 

 

 

다음은...영상처리 기법.. 거의다 했구먼....입문편도.....

 

 

Posted by 프리랜서 디자이너