본문 바로가기
셰이더 (Shader)/셰이더 프로그래밍 입문 - Pope Kim (완)

[HLSL] 챕터5 - 디퓨즈 / 스페큘러매핑

by Minkyu Lee 2023. 3. 18.

// 디퓨즈맵 vs 스페큘러맵

난반사광에 적용하는 텍스쳐 디퓨즈맵

정반사광에 적용하는 텍스쳐 스페큘러맵

 

디퓨즈맵은 색상 표현에 사용한다.

각 픽셀이 반사하는 정도를 조절하는 용도로 스페큘러맵을 사용한다.

따라서 두 텍스쳐의 생김새가 많이 다르다. (스페큘러맵은 흑백으로 표현 가능)

 

// 물체의 색에 영향을 미치는 또 다른 요소

조명의 색이다.

조명의 색은 전역변수로 쉽게 지정 가능하다.

 

// 정리

난반사광 = 빛의 색상 X 난반사광의 양 X 디퓨즈맵의 값

정반사광 = 빛의 색상 X 정반사광의 양 X 스페큘러맵의 값

 

// 스페큘러맵에 대하여

스페큘러맵을 보라.

텍스쳐는 언제나 색상정보만을 가지지는 않는다.

각 픽셀이 반사하는 정반사광의 양을 담고 있다.

픽셀 수준에서 제어하고 싶은 변수가 있다면 텍스쳐 사용하는 것이 일반적이다.

 

정점셰이더

float4x4 gWorldMatrix;
float4x4 gViewMatrix;
float4x4 gProjectionMatrix;
float4 gWorldLightPosition;
float4 gWorldCameraPosition;

struct VS_INPUT
{
   float4 mPosition : POSITION;
   float3 mNormal : NORMAL;
   float2 mUV : TEXCOORD0;
   float3 mDiffuse : TEXCOORD1;
   float3 mViewDir : TEXCOORD2;
   float3 mReflection : TEXCOORD3;
};

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)
{
   VS_OUTPUT Output;
   Output.mPosition = mul(Input.mPosition, gWorldMatrix);
   float3 lightDir = normalize(Output.mPosition.xyz-gWorldLightPosition.xyz);
   
   // viewDir
   float3 viewDir = normalize(Output.mPosition.xyz-gWorldCameraPosition.xyz);
   Output.mViewDir = viewDir;
   
   // Position
   Output.mPosition = mul(Output.mPosition, gViewMatrix);
   Output.mPosition = mul(Output.mPosition, gProjectionMatrix);
   
   // Diffuse & Reflection
   float3 worldNormal = mul(Input.mNormal, gWorldMatrix);
   Output.mDiffuse = dot(-lightDir, worldNormal);
   float3 reflection = reflect(lightDir, worldNormal);
   Output.mReflection = reflection;
   Output.mUV = Input.mUV;
   
   return Output;
}

텍스쳐 샘플러는 픽셀셰이더에서 사용한다.

여기서 선언하지 않는다.

빛의 색상도 픽셀셰이더에서 곱한다.

 

픽셀셰이더

float3 gLightColor;
sampler2D DiffuseSampler;
sampler2D SpecularSampler;

struct PS_INPUT
{
   float2 mUV : TEXCOORD0;
   float3 mDiffuse : TEXCOORD1;
   float3 mViewDir : TEXCOORD2;
   float3 mReflection : TEXCOORD3;
};

float4 ps_main(PS_INPUT Input) : COLOR
{
   float4 albedo = tex2D(DiffuseSampler, Input.mUV);

   float3 diffuse = gLightColor * albedo.rgb * saturate(Input.mDiffuse);
   
   float3 viewDir = normalize(Input.mViewDir);
   float3 reflection = normalize(Input.mReflection);
   float3 specular = 0;
   if(diffuse.x > 0)
   {
      specular = saturate(dot(reflection, -viewDir));
      specular = pow(specular, 20.0);
      
      float4 specularIntensity = tex2D(SpecularSampler, Input.mUV);
      specular *= specularIntensity.rgb * gLightColor;
   }
   float3 ambient = float3(0.1, 0.1, 0.1) * albedo.rgb;
   return float4(diffuse + specular + ambient, 1.0);
}

// 디퓨즈맵을 샘플링

여기에 난반사광의 양과 빛의 색상을 곱한다.

 

// 스페큘러맵을 샘플링

정반사광의 양과 빛의 색상을 곱한다.

 

// ambient에도 디퓨즈맵 적용

난반사광이 없는 곳에도 환경광으로 인해 물체가 보인다.

그런데 0.1만 주었기 때문에 디테일이 표현되지 않는다.

그래서 디퓨즈맵을 곱해준다.

댓글