입방체 텍스쳐면 있다면

코드 2줄만으로도 만들 수 있는 환경맵핑

 

 

정점 셰이더

 

float4x4 gWorldMatrix;
float4x4 gWorldViewProjectionMatrix;

float4 gWorldLightPosition;
float4 gWorldCameraPosition;

struct VS_INPUT
{
   float4 mPosition : POSITION;
   float3 mNormal: NORMAL;
   float3 mTangent: TANGENT;
   float3 mBinormal: BINORMAL;
   float2 mUV: TEXCOORD0;
};

struct VS_OUTPUT
{
   float4 mPosition : POSITION;
   float2 mUV: TEXCOORD0;
   float3 mLightDir : TEXCOORD1;
   float3 mViewDir: TEXCOORD2;
   float3 T : TEXCOORD3;
   float3 B : TEXCOORD4;
   float3 N : TEXCOORD5;
};

VS_OUTPUT vs_main( VS_INPUT Input )
{
   VS_OUTPUT Output;

   Output.mPosition = mul( Input.mPosition, gWorldViewProjectionMatrix );
   Output.mUV = Input.mUV;

   float4 worldPosition = mul( Input.mPosition, gWorldMatrix );
   float3 lightDir = worldPosition.xyz - gWorldLightPosition.xyz;
   Output.mLightDir = normalize(lightDir);
  
   float3 viewDir = normalize(worldPosition.xyz - gWorldCameraPosition.xyz);
   Output.mViewDir = viewDir;
  
   float3 worldNormal = mul( Input.mNormal, (float3x3)gWorldMatrix );
   Output.N = normalize(worldNormal);
  
   float3 worldTangent = mul(Input.mTangent, (float3x3)gWorldMatrix );
   Output.T = normalize(worldTangent);
  
   float3 worldBinormal = mul(Input.mBinormal, (float3x3)gWorldMatrix );
   Output.B = normalize(worldBinormal);
  
   return Output;
}

 

 

픽셸 셰이더

 

struct PS_INPUT
{
   float2 mUV : TEXCOORD0;
   float3 mLightDir : TEXCOORD1;
   float3 mViewDir: TEXCOORD2;
   float3 T : TEXCOORD3;
   float3 B : TEXCOORD4;
   float3 N : TEXCOORD5;
};

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

float3 gLightColor;

float4 ps_main(PS_INPUT Input) : COLOR
{
   float3 tangentNormal = tex2D(NormalSampler, Input.mUV).xyz;
   tangentNormal = normalize(tangentNormal * 2 - 1)*float3(0,0,1);
//노멀값이 너무 쎄서 float3 값을 곱해줘서 환경맵핑이 잘보이게만들어 준다.

   
   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.mUV);
   float3 lightDir = normalize(Input.mLightDir);
   float3 diffuse = saturate(dot(worldNormal, -lightDir));
   diffuse = gLightColor * albedo.rgb * diffuse;
  
   float3 viewDir = normalize(Input.mViewDir);

//환경맵에도 카메라벡터를 사용하기위해 if문 밖으로 빼주었다.


   float3 specular = 0;
  
   if ( diffuse.x > 0 )
   {
      float3 reflection = reflect(lightDir, worldNormal);

      specular = saturate(dot(reflection, -viewDir ));
      specular = pow(specular, 20.0f);
     
      float4 specularIntensity  = tex2D(SpecularSampler, Input.mUV);
      specular *= specularIntensity.rgb * gLightColor;
     
   }

 

   float3 viewReflect = reflect(viewDir, worldNormal);

//reflect()함수를 사용해 반사벡터를 구한다.


   float3 environment = texCUBE(EnvironmentSampler, viewReflect).rgb;
//   texCUBE()함수를 이용해 환경맵을 구현한다.


   float3 ambient = float3(0.1f, 0.1f, 0.1f) * albedo;
  
   return float4(ambient + diffuse + specular+environment * 0.5f, 1);

//return에 환경맵을 더해주고 강도를 조절을 위해 *0.5f를 해준다.
}

 

 

#HLSL#

texCUBE() : 입방체 텍스쳐를 샘플링하는 함수

reflect() : 카메라의 반사 벡터를 구하는 함수

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Posted by 프리랜서 디자이너