드디어 제대로 뷰 벡터를 구해서 블린-퐁 (Blinn-Phong) 반영 반사를 구하다.
앗싸.
덤으로 Gloss 맵도 추가.
점점 할 수 있는게 늘어나서 기쁘다.
float4x4 World : WORLD ;
float4x4 View : VIEW ;
float4x4 Projection : PROJECTION ;
float4x4 WorldViewProj : WORLDVIEWPROJ ;
float4x4 WorldView : WORLDVIEW ;
float4x4 ViewInv : ViewI;
//ViewI 에 대한 정의는 확실하지 않으나, 지금으로 짐작할 수 있는 것은
//월드 좌표계에서의 카메라 메트릭스라고 짐작된다. 걍 외우자.
float4 I_a = {1.0f, 1.0f, 1.0f, 1.0f};//엠비언트
float4 I_d = {1.0f, 1.0f, 1.0f, 1.0f};//디퓨즈
float4 I_s = {1.0f, 1.0f, 1.0f, 1.0f};//스페큘러
//라이트의 단순한 가중치 값이다.
float3 lightDir : Direction
<
string UIName = “라이트 디렉션”;
string Object = “DirectionalLight”;
string Space = “WORLD”;
int refID = 0;
;
// 재질 반사색
float4 k_a
<
string UIName = “엠비언트”;
;
float4 k_d
<
string UIName = “디퓨즈”;
;
float4 k_s
<
string UIName = “스페큘러”;
;
float n
<
string UIName = “스페큘러 파워”;
string UItype = “IntSpinner”;
float UIMin = 0.0f;
float UIMax = 100.0f;
;
texture Glossmap : GLOSSMAP
<
string UIName = “글로스맵”;
int Texcoord = 0;
;
sampler2D GlossSampler = sampler_state
{
texture = ;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
};
void VS
(
in float4 iPos : POSITION ,
in float3 iNormal : NORMAL,
in float2 itex : TEXCOORD0,
out float4 oPos : POSITION,
out float3 oDiffuse : COLOR0,
out float3 oSpecular : COLOR1,
out float2 otex : TEXCOORD0
)
//본래 TEXCOORD 는 필요 없으나, 글로스맵을 퍼픽셀 단위에서 계산해 주기위해 추가했습니다.
{
oPos = mul( iPos, WorldViewProj );
//이건 이제 보기만 해도 뭔지 알겠고.
float3 EyeDirection = normalize( ViewInv[3].xyz - mul( iPos, World ).xyz );
/*
뷰 쪽으로 향하는 벡터를 구하기 위한 가장 중요한 부분.
원리를 보자. 뷰 메트릭스에서 3열의 XYZ 부분의 데이터는, 카메라의 위치 벡터를 의미한다.
여기서의 카메라 벡터는, 월드 좌표계라고 외우도록 하자. 확실하진 않지만.
거기서 포지션을 월드 좌표계로 변환시켰다.
그렇게 해서, 카메라 월드 위치벡터 - 버텍스의 월드 위치벡터 공식이 되었는데,
여기서 외워둬야 할 것은 벡터A - 벡터B는 Head-Tail 이라는 것이다. 즉, A가 머리이고, B가 꼬리가 되는 화살표가 나온다.
이렇게 해서, 버텍스에서 카메라에 달하는 뷰 벡터를 구할 수 있었다.
이것을 노말라이즈 해서, 단위 벡터로 구했다.
*/
float3 LightDirection = lightDir;
float3 HalfVector = normalize( EyeDirection + LightDirection );
//블린 공식에서 가장 중요한 하프벡터 구하기,
//이것은 아까 구한 뷰 벡터와 라이트 벡터를 더해서 나온 값을 노말라이즈 시켜주면 간단하다.
float3 SurfaceNormal = normalize( mul( iNormal, (float3x3)World ) );
oDiffuse = I_a * k_a + I_d * k_d * max( 0, dot( SurfaceNormal, LightDirection ) );
oSpecular = I_s * k_s * pow( max( 0, dot( SurfaceNormal, HalfVector ) ), n );
//블린 스페큘러 공식의 핵심이다. 당연하게도, 하프벡터와 서페이스 노말의 내적연산을 하면 간단하다.
//곱하기 n으로 크기를 조절할 수 있게 되었다.
otex = itex;
};
void PS
(
in float4 iDiffuse : COLOR0,
in float4 iSpecular : COLOR1,
in float2 iTex : TEXCOORD0,
out float4 oColor : COLOR
)
{
oColor = iDiffuse + iSpecular * tex2D( GlossSampler, iTex );
//스페큘러에다가 글로스 맵을 단순하게 곱해만 주는 것으로 글로스 맵 완성.
};
technique jp10
{
pass p0
{
CullMode = None;
VertexShader = compile vs_2_0 VS();
PixelShader = compile ps_2_0 PS();
}
}