<본 포스팅은 강좌가 아닙니다.>
빛을 흡수하는 성질 : 빨간색 표면은 빨간색의 스펙트럼을
반사하고 나머지는 흡수해서 빨간색으로 보인다.
난반사광에 적용하는 텍스쳐를 Diffuse맵이라고 하고
정반사광에 적용하는 텍스쳐를 Specular맵이라고 한다.
왜 따로 텍스쳐를 사용하는 것이냐면
난반사광이 반사하는 빛과 정반사광이 반사하는 빛의 스펙트럼이 다르고
픽셀이 반사하는 정반사광의 정도를 조절하는 용도로 쓰기 위함이다.
정리하자면
난반사광 = 빛의 색상 X 난반사광의 양 X 디퓨즈맵의 값
정반사광 = 빛의 색상 X 정반사광의 양 X 스페큘러맵의 값
난반사, 정반사를 구현했던 기존 프로젝트를 사용해서
버텍스셰이더에서 해줄것은 별로 없다.
UV값을 받아 Output 픽셀셰이더로 넘겨주는 코드만 있으면 된다.
텍스쳐 tex2D 작업은 픽셀셰이더에서 하기 때문이다.
UV좌표를 받아와서 디퓨즈맵을 샘플링한다.
현재 픽셀이 반사하는 색깔이다.
위에서 난반사광의 양과 빛의 색상을 곱한다했듯이
float3 diffuse = gLightColor * albedo.rgb * saturate(Input.mDiffuse); 곱해준다.
이러한 결과가 나오는데 스페큘러맵을 쓰지않아 정반사광이 심한 모습이다.
스페큘러도 마찬가지로 정반사광의 양과 빛의 색상을 곱해준다.
또한 ambient 주변광에도 알베도를 곱해준다.
임의로 정한 빛의 양이기때문에 여기도 디퓨즈맵을 곱하는 것이다.
틈새에 갈색부분은 갈색이라 갈색 빛을 흡수하는 모습이다.
정반사광이 강하지 않고 어두운 픽셀에서도 디퓨즈 맵을 확인할 수 있다.
포스팅했던거 삭제되어서 다시 적어내렸다...
최종결과
//VS
float4x4 gWorldMatrix;
float4x4 gViewMatrix;
float4x4 gProjMatrix;
float4 gWorldLightPos;
float4 gWorldCamPos;
struct VS_INPUT
{
float4 mPosition : POSITION;
float3 mNormal : NORMAL;
float2 mUV : TEXCOORD0;
};
struct VS_OUTPUT
{
float4 mPosition : POSITION;
float2 mUV : TEXCOORD0;
float3 mDiffuse : TEXCOORD1;
float3 mViewDir : TEXCOORD2;
float3 mReflection : TEXCOORD3;
};
VS_OUTPUT vs_main( VS_INPUT Input )
{
//난반사광의 계산 동일한 계산을 PS VS 둘다 할 수 있음.
//하지만 픽셀단위 계산보다 정점단위 계산이 더 연산량이 적음
VS_OUTPUT Output;
Output.mPosition = mul( Input.mPosition, gWorldMatrix );
//월드 행렬 곱함, 월드 공간에서의 위치여서 여기서 광원의 위치를 뺀다.
float3 lightDir = Output.mPosition.xyz - gWorldLightPos.xyz;
lightDir = normalize(lightDir);
float3 viewDir = Output.mPosition.xyz-gWorldCamPos.xyz;
Output.mViewDir = viewDir;
Output.mPosition = mul( Output.mPosition, gViewMatrix );
Output.mPosition = mul( Output.mPosition, gProjMatrix );
float3 worldNormal = mul(Input.mNormal, (float3x3)gWorldMatrix);
worldNormal = normalize(worldNormal);
//내적함수 dot()사용
Output.mDiffuse = dot(-lightDir, worldNormal);
Output.mReflection=reflect(lightDir,worldNormal);
Output.mUV = Input.mUV;
return Output;
}
//PS
struct PS_INPUT
{
float2 mUV : TEXCOORD0;
float3 mDiffuse : TEXCOORD1;
float3 mViewDir : TEXCOORD2;
float3 mReflection : TEXCOORD3;
};
sampler2D DiffuseSampler;
sampler2D SpecularSampler;
float3 gLightColor;
float4 ps_main( PS_INPUT Input) : COLOR
{
//디퓨즈맵 생플링
float4 albedo = tex2D(DiffuseSampler, Input.mUV);
// 픽셀이 반사하는 색깔
float3 diffuse = gLightColor*albedo.rgb*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);
float4 specularInten=tex2D(SpecularSampler, Input.mUV);
specular*=specularInten.rgb*gLightColor;
}
float3 ambient = float3(0.1f, 0.1f, 0.1f);
return float4(ambient+diffuse+specular,1);
}
'STUDY > Shader Programming' 카테고리의 다른 글
셰이더 프로그래밍 - AMD RenderMonkey 사용해서 쉐이더 공부를 해보자6 (환경 매핑, 입방체 매핑) (0) | 2021.12.20 |
---|---|
셰이더 프로그래밍 - AMD RenderMonkey 사용해서 쉐이더 공부를 해보자5 (법선 매핑) (0) | 2021.12.20 |
셰이더 프로그래밍 - AMD RenderMonkey 사용해서 쉐이더 공부를 해보자4 (툰셰이더) (0) | 2021.12.17 |
셰이더 프로그래밍 - AMD RenderMonkey 사용해서 쉐이더 공부를 해보자2 (기초 조명 셰이더 - 난반사광, 정반사광) (0) | 2021.12.17 |
셰이더 프로그래밍 - AMD RenderMonkey 사용해서 쉐이더 공부를 해보자 (텍스쳐 적용 tex2d()함수) (0) | 2021.12.16 |