이전 포스팅에서는 렌더몽키 환경에서
난반사광, 정반사광 적용을 했었다.
복습할겸, 다이렉트X11 환경에서 적용해보았다.
VS_0.hlsl
cbuffer CBuf
{
matrix g_matWorld : packoffset(c0);
matrix g_matView : packoffset(c4);
matrix g_matProj : packoffset(c8);
matrix g_matNormal : packoffset(c12);
float4 g_lightPos : packoffset(c16); //라이트 방향
float4 g_lightColor : packoffset(c17); //라이트 방향
float4 g_camPos : packoffset(c18); //카메라 방향
float4 g_value : packoffset(c19); //기타 시간 값등
};
struct VS_INPUT
{
float3 mPosition : POSITION;
float3 mNormal : NORMAL;
float4 mColor : COLOR;
float2 mUV : TEXTURE;
};
struct VS_OUTPUT
{
float4 mPosition : SV_POSITION;
float3 mNormal : NORMAL;
float4 mColor : COLOR0;
float2 mUV : TEXCOORD0; //uv
float3 mDiffuse : TEXCOORD1; //디퓨즈
float3 mViewDir : TEXCOORD2; //방향
float3 mReflection : TEXCOORD3; //반사
};
VS_OUTPUT VS(VS_INPUT Input)
{
//난반사광의 계산 동일한 계산을 PS VS 둘다 할 수 있음.
//하지만 픽셀단위 계산보다 정점단위 계산이 더 연산량이 적음
VS_OUTPUT Output = (VS_OUTPUT)0;
Output.mPosition = float4(Input.mPosition, 1.0f);
Output.mPosition = mul(Output.mPosition, g_matWorld);
//월드 행렬 곱함, 월드 공간에서의 위치여서 여기서 광원의 위치를 뺀다.
float3 lightDir = Output.mPosition.xyz - g_lightPos.xyz;
lightDir = normalize(lightDir);
//
float3 viewDir = Output.mPosition.xyz - g_camPos.xyz;
Output.mViewDir = viewDir;
//
Output.mPosition = mul(Output.mPosition, g_matView);
Output.mPosition = mul(Output.mPosition, g_matProj);
float3 worldNormal = mul(Input.mNormal, (float3x3)g_matWorld);
worldNormal = normalize(worldNormal);
//내적함수 dot()사용
Output.mDiffuse = dot(-lightDir, worldNormal);
Output.mReflection = reflect(lightDir, worldNormal);
Output.mNormal = Input.mNormal;
Output.mColor = Input.mColor;
Output.mUV = Input.mUV;
return Output;
}
PS_0.hlsl
Texture2D g_txDiffuse : register(t0);
Texture2D g_txSpecular : register(t1);
Texture2D g_txNormal : register(t2);
SamplerState g_Sample : register(s0);
struct VS_OUTPUT
{
float4 mPosition : SV_POSITION;
float3 mNormal : NORMAL;
float4 mColor : COLOR0;
float2 mUV : TEXCOORD0; //uv
float3 mDiffuse : TEXCOORD1; //디퓨즈
float3 mViewDir : TEXCOORD2; //방향
float3 mReflection : TEXCOORD3; //반사
};
float4 PS(VS_OUTPUT Input) : SV_TARGET
{
float3 diffuse = saturate(Input.mDiffuse);
//보간기를 거치는 동안 값이 흐트러질수도 있음 다시 정규화
float3 reflection = normalize(Input.mReflection);
float3 viewDir = normalize(Input.mViewDir);
float3 specular = 0;
//난사빛(빛이 닿아야)이 있어야 정반사광이 존재함
if (diffuse.x > 0.0f)
{
specular = saturate(dot(reflection, -viewDir));
//20번 거듭제곱
specular = pow(specular,20.0f);
}
float3 ambient = float3(0.1f, 0.1f, 0.1f);
return float4(ambient + diffuse + specular,1);
}
퐁모델 : 반사광과 카메라벡터 각도의 코사인 값을 구하고, 그 결과를 여러번 거듭제곱함.
다만 코사인 연산은 내적 연산보다 무거워서 내적연산으로 대체한다. -1 다른방향 , 0 직각 , 1 같은 방향
내적공식으로 코사인 값은 둘의 내적값에 두 벡터의 길이를 곱한 결과를 나누면 코사인 값이 나온다.