Featured image of post 셰이더 프로그래밍 기본공부 20_노말맵

셰이더 프로그래밍 기본공부 20_노말맵

일단 노말맵 완성입니다.
그것도 일단 렌더타겟을 생성하여 거기다 렌더링했어요.
왜냐면 최종적으로 블룸 효과를 낼 거라서 말이죠 (이힛)

노말맵의 핵심은 , 노말맵 이미지를 받아와서 .

버텍스 셰이더 단계에서 탄젠트와 바이노말, 노말을 생성해서 각각 X,Y,Z 에 대입한 다음
뷰 디렉션 (노말이 보여야 하니까) 와
라이트 디렉션(그림자가 생겨야 하니까) 로 계산을 각각 한 다음에
이 두 가지를 픽셀 셰이더로 넘기고,

그걸 받은 픽셀 셰이더님은
각종 라이트 계산할때 쓰이는 픽셀 수준의 노말값을 다시 노말 범프로 tex 연산을 때린 다음에
이렇게 노말맵에 중독된 노말값과 라이트 디렉션과 뷰 디렉션들로 일반 연산을 때려서 사람 눈을 속이는 짓을 하는 거군요.
약았어요 약았어.

그러므로 핵심 공식은 다음과 같습니다.
버텍스 셰이더 단계에서
 
   float3 fvNormal = mul(matView, Input.Normal );
   float3 fvBinormal = mul(matView, Input.Binormal);
   float3 fvTangent = mul(matView, Input.Tangent );
  
   Output.ViewDirection.x = dot(fvTangent,fvViewDirection);
   Output.ViewDirection.y = dot(fvBinormal,fvViewDirection);
   Output.ViewDirection.z = dot(fvNormal,fvViewDirection);
 
   Output.LightDirection.x = dot(fvTangent,fvLightDirection);
   Output.LightDirection.y = dot(fvBinormal,fvLightDirection);
   Output.LightDirection.z = dot(fvNormal,fvLightDirection);

를 계산한 다음에 
    float3 ViewDirection : TEXCOORD1;
    float3 LightDirection : TEXCOORD2;
를 픽셀 셰이더로 넘기고

픽셀 셰이더에서는
float3 fvNormal         = normalize ((tex2D(bumpMap,Input.Texcoord).xyz *2.0f)-1.0f);
 로 노말을 ‘만들어서’ , (노말값이 -1부터 1까지인 것을 0에서 1까지로 수정)

받아온 ViewDirection 과 LightDirection 을 이용해서 각종 연산을 때려버리면 된다.

공식은 다음과 같음.

//버텍스 셰이더

float3 fvLightPosition;
float3 fvEyePosition;
float4x4 matView;
float4x4 matViewProjection;

struct VS_INPUT
{
   float4 Position : POSITION0;
   float2 Texcoord : TEXCOORD0;
   float3 Normal : NORMAL0;
   float3 Binormal : BINORMAL0;
   float3 Tangent : TANGENT0;
  
};

struct VS_OUTPUT
{
   float4 Position : POSITION0;
   float2 Texcoord : TEXCOORD0;
   float3 ViewDirection : TEXCOORD1;
   float3 LightDirection : TEXCOORD2;
  
};

VS_OUTPUT vs_main( VS_INPUT Input )
{
   VS_OUTPUT Output;

   Output.Position = mul( Input.Position, matViewProjection );
   Output.Texcoord = Input.Texcoord;
  
   float3 fvObjectPosition = mul (matView,Input.Position);
  
   float3 fvViewDirection = fvEyePosition - fvObjectPosition;
   float3 fvLightDirection = fvLightPosition - fvObjectPosition;
  
   float3 fvNormal = mul(matView, Input.Normal );
   float3 fvBinormal = mul(matView, Input.Binormal);
   float3 fvTangent = mul(matView, Input.Tangent );
  
   Output.ViewDirection.x = dot(fvTangent,fvViewDirection);
   Output.ViewDirection.y = dot(fvBinormal,fvViewDirection);
   Output.ViewDirection.z = dot(fvNormal,fvViewDirection);
 
   Output.LightDirection.x = dot(fvTangent,fvLightDirection);
   Output.LightDirection.y = dot(fvBinormal,fvLightDirection);
   Output.LightDirection.z = dot(fvNormal,fvLightDirection);
     
  
   return( Output );
  
}

//픽셀 셰이더

float4 fvAmbient;
float4 fvSpecular;
float4 fvDiffuse;
float fSpecularPower;

sampler2D baseMap;
sampler2D bumpMap;

struct PS_INPUT
{

   float2 Texcoord       : TEXCOORD0;
   float3 ViewDirection  : TEXCOORD1;
   float3 LightDirection : TEXCOORD2;

};

float4 ps_main(PS_INPUT Input) : COLOR0
{  
  
   float3 fvLightDirection = normalize (Input.LightDirection);
   float3 fvNormal         = normalize ((tex2D(bumpMap,Input.Texcoord).xyz *2.0f)-1.0f);
   float fNDotL            = dot (fvNormal, fvLightDirection);
  
   float3 fvReflection     = normalize (((2.0*fvNormal)*(fNDotL))-fvLightDirection);
   float3 fvViewDirection  = normalize (Input.ViewDirection );
   float fRDotV            = max(0.0f,dot(fvReflection,fvViewDirection));
  
   float4 fvBaseColor      = tex2D (baseMap,Input.Texcoord);
  
   float4 fvTotalAmbient   = fvAmbient * fvBaseColor;
   float4 fvTotalDiffuse   = fvDiffuse * fNDotL * fvBaseColor;
   float4 fvTotalSpecular  = fvSpecular * pow(fRDotV,fSpecularPower);
  
    
  
   return saturate (fvTotalAmbient + fvTotalDiffuse + fvTotalSpecular);
  
}

Hugo로 만듦
JimmyStack 테마 사용 중