일단 노말맵 완성입니다.
그것도 일단 렌더타겟을 생성하여 거기다 렌더링했어요.
왜냐면 최종적으로 블룸 효과를 낼 거라서 말이죠 (이힛)
노말맵의 핵심은 , 노말맵 이미지를 받아와서 .
버텍스 셰이더 단계에서 탄젠트와 바이노말, 노말을 생성해서 각각 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);
}