오다기리 박의 알고리즘 노트

[셰이더 프로그래밍 입문] 5.디퓨즈/스페큘러 매핑 본문

컴퓨터 그래픽스/쉐이더

[셰이더 프로그래밍 입문] 5.디퓨즈/스페큘러 매핑

오다기리 박 2018. 7. 1. 23:31

5.디퓨즈/스페큘러 매핑

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

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

  • 스페큘러맵은 각 픽셀의 정반사광을 조절하는 것이 목적



▶렌더몽키 코드 

- 버텍스 셰이더
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
float4x4 gWorldMatrix;
float4x4 gViewMatrix;
float4x4 gProjectionMatrix;
 
float4 gWorldLightPosition;
float4 gWorldCameraPosition;
 
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)
{
   VS_OUTPUT Output;
   
   Output.mPosition=mul(Input.mPosition,gWorldMatrix);
   
   float3 lightDir=Output.mPosition.xyz-gWorldLightPosition.xyz;
   lightDir=normalize(lightDir);
   
   float3 viewDir=normalize(Output.mPosition.xyz-gWorldCameraPosition.xyz);
   Output.mViewDir=viewDir;
   
   Output.mPosition=mul(Output.mPosition,gViewMatrix);
   Output.mPosition=mul(Output.mPosition,gProjectionMatrix);
   
   float3 worldNormal=mul(Input.mNormal,(float3x3)gWorldMatrix);
   worldNormal=normalize(worldNormal);
   
   Output.mDiffuse=dot(-lightDir,worldNormal);
   Output.mReflection=reflect(lightDir,worldNormal);
   
   Output.mUV=Input.mUV;
   
   return Output;
}
cs

- 픽셀 셰이더
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
sampler2D DiffuseSampler;
sampler2D SpecularSampler;
 
float3 gLightColor;
 
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 reflection=normalize(Input.mReflection);
   float3 viewdir=normalize(Input.mViewDir);
   float3 specular=0;
   
   if(diffuse.x>0)
   {
      specular=saturate(dot(reflection,-viewdir));
      specular=pow(specular,10.0f);
      
      float4 specularIntensity=tex2D(SpecularSampler,Input.mUV);
      specular*=specularIntensity.rgb*gLightColor;
   }
   float3 ambient=float3(0.1f,0.1f,0.1f)*albedo.rgb;
   
   return float4(diffuse+ambient+specular,1);
}
cs

- 결과

난반사광과 정반사광에 텍스처를 적용한 디퓨즈/스페큘러 매핑입니다.

img