셰이더 입문1

툰 셰이더

shader_basic.html 장에 나온 simpleLighting2.rfx 셰이더에 툰 효과를 추가한다.
별도의 텍스쳐 없이  칼라값을 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 단우리로 계산 할 것이다.
외곽라인은 없다.

계산은 픽셀 셰이더에 다음 한줄만 추가한다.

diffuse = ceil( diffuse * 5) / 5.0f

ceill 명령은 무조건 올림 명령어이다.

0.2 단위로 증가가 필요하기 때문에 1/0.2 = 5 이다.
곱과 올림후에 나눠주면 간격 만큼 수치는 증가 한다.

0.4 단위로 증가가 필요하다면 1/0.4 = 2.5 이다.

Toon Shader
struct VS_INPUT
{
   float4 pos : POSITION;
   float3 normal : NORMAL;
};

float4x4 gWorldViewProjMat;
float4x4 gInvWorldMat;

float4 gWorldLightPos;


struct VS_OUTPUT
{
   float4 pos : POSITION;
   float3 diffuse : TEXCOORD1;
};

VS_OUTPUT vs_main( VS_INPUT input )
{
   VS_OUTPUT output;

   output.pos = mul( input.pos, gWorldViewProjMat);
   
   float3 objectLightPos = mul( gWorldLightPos, gInvWorldMat);
   float3 lightDir = normalize(input.pos.xyz - objectLightPos);
   
   output.diffuse = dot( -lightDir, input.normal);
   
   return( output );
   
}

//--------------------------------------------------------------------

struct PS_INPUT
{
   float3 diffuse : TEXCOORD1;
};

float4 ps_main( PS_INPUT input) : COLOR
{   
   float3 diffuse = saturate( input.diffuse);
   
   diffuse = ceil( diffuse * 5) / 5.0f;
      
   return float4( diffuse, 1.0f);
}

다운로드 : Toon.rfx

 

EnvironmentMap

아래 그림은 환경맵에서 텍셀을 구하는 원리이다.
카메라 벡터의 반사벡터를 texCube에 넘겨준다.

NormalMapping.rfx에 기능을 추가한다.

환경맵을 텍스쳐를 렌더몽키 샘플에서 추가한다.
Add Texture > Add Cubemap > Snow.dds

환경맵 텍스쳐 오브젝트를 더블 클릭해서 D3DSAMP_MAGFILTER, D3DSAMP_MINFILTER를 D3DTEXF_LINEAR로 변경한다.

정점 셰이더는 추가 할 코드가 없고 픽셀셰이더에만 코드를 추가 할 것이다.

입방체이므로 다음과 같이 추가한다.

픽셀셰이더 코드는 다음과 같이 진행한다.

  • 환경맵 선언 samplerCUBE EnvironmentSampler;
  • 카메라 디렉션을 이용하여 환경맵을 구한다. if문 안에 있는 viewDir을 조건문 밖으로 뺀다.
  • 카메라의 반사 벡터 구하기 float3 viewReflect = reflect( viewDir, worldNormal)
  • 환경맵의 텍셀 구하기 float3 environment = texCUBE( EnvironmentSampler, viewReflect).rgb
  • 환경맵 텍셀 결과에 더하기 return float4( ambient + specular + diffuse + environment*0.5f, 1.0f)

환경맵 값에 0.5를 곱한 것은 강도를 조정하는 것이다. 어떤값을 대입하더라도 상관없다.
노멀맵 때문에 환경맵이 잘 안보이므로 평평하게 보이도록 하기 위해 tangentNormal = float3( 0, 0, 1)으로 설정하였다.

Environment
float4x4 gWorldMat;
float4x4 gWorldViewProjMat;

float4 gLightPos;
float4 gViewPos;

struct VS_INPUT
{
   float4 pos : POSITION;
   float3 normal : NORMAL;
   float2 uv : TEXCOORD0;
   float3 tangent : TANGENT;
   float3 binoraml : BINORMAL;
};

struct VS_OUTPUT
{
   float4 pos : POSITION;
   float2 uv : TEXCOORD0;
   float3 lightDir : TEXCOORD1;
   float3 viewDir : TEXCOORD2;
   float3 T : TEXCOORD3;
   float3 B : TEXCOORD4;
   float3 N : TEXCOORD5;
};

VS_OUTPUT vs_main( VS_INPUT input )
{
   VS_OUTPUT output;

   output.pos = mul( input.pos, gWorldViewProjMat);
   
   output.uv = input.uv;
   
   float4 worldPos = mul( input.pos, gWorldMat);
   
   float3 lightDir = worldPos - gLightPos.xyz;
   output.lightDir = normalize( lightDir);
   
   float3 viewDir = worldPos - gViewPos.xyz;
   output.viewDir = normalize( viewDir);
   
   float3 worldNormal = mul( input.normal, (float3x3)gWorldMat);
   output.N = normalize( worldNormal);
   
   float3 worldTangent = mul( input.tangent, (float3x3)gWorldMat);
   output.T = normalize( worldTangent);
   
   float3 worldBinormal = mul( input.binoraml, (float3x3)gWorldMat);
   output.B = normalize( worldBinormal);
   
   return output;   
}

//--------------------------------------------------------------------------------

sampler2D DiffuseSampler;
sampler2D SpecularSampler;
sampler2D NormalSampler;
samplerCUBE EnvironmentSampler;

struct PS_INPUT
{
   float2 uv : TEXCOORD0;
   float3 lightDir : TEXCOORD1;
   float3 viewDir : TEXCOORD2;
   float3 T : TEXCOORD3;
   float3 B : TEXCOORD4;
   float3 N : TEXCOORD5;
};

float3 gLightColor;

float4 ps_main( PS_INPUT input) : COLOR
{
   float3 tangentNormal = tex2D( NormalSampler, input.uv).xyz;
   tangentNormal = normalize( tangentNormal * 2 - 1);
   
   //for test environment map
   tangentNormal = float3( 0, 0, 1);  
   
   float3x3 TBN = float3x3( normalize( input.T),
                            normalize( input.B),
                            normalize( input.N));

   TBN = transpose( TBN);
   float3 worldNormal = mul( TBN, tangentNormal);
     
   float4 albedo = tex2D(DiffuseSampler, input.uv);
   float3 lightDir = normalize( input.lightDir);
   float3 diffuse = saturate( dot( worldNormal, -lightDir));
   diffuse = gLightColor * albedo.rgb * diffuse;
      
   float3 specular = 0;
   
   float3 viewDir = normalize( input.viewDir);
   
   if( diffuse.x > 0)
   {
      float3 reflection = reflect( lightDir, worldNormal);
            
      specular = dot( reflection, -viewDir);
      specular = saturate( specular);
      
      specular = pow( specular, 20);
      
      float4 specularIntensity = tex2D(SpecularSampler, input.uv);
      specular = gLightColor * specularIntensity.rgb * specular;
   }
   float3 viewReflect = reflect( viewDir, worldNormal);
   float3 environment = texCUBE( EnvironmentSampler, viewReflect).rgb;
   
   float3 ambient = float3( 0.1f, 0.1f, 0.1f) * albedo;
   
   return float4( ambient + specular + diffuse + environment*0.5f, 1.0f);
}

다운로드 : EnvironmentMapping.rfx