플랫 셰이딩

면의 법선벡터와 조명벡터로 면의 밝기를 계산한다

 

공간 변환 후 넘겨주기만 하면 된다. 월드공간 좌표는 따로 빼고

ddx / ddy 함수는 변화량을 구하는 함수, hlsl ddx 검색


고로 셰이딩

정점의 법선벡터와 조명벡터로 정점의 밝기를 계산한다.

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
50
51
52
53
float4x4 matViewProjection;
 
float4 gWorldLightPosition;
float4 gWorldCameraPosition;
 
struct VS_INPUT 
{
   float4 mPosition : POSITION0;  
   float3 mNormal : NORMAL; 
};
 
struct VS_OUTPUT 
{
   float4 mPosition : POSITION0;   
   float3 mColor : COLOR1;
};
 
VS_OUTPUT vs_main( VS_INPUT Input )
{
   VS_OUTPUT Output;
 
   Output.mPosition = mul( Input.mPosition, matViewProjection );
   
   float4 projectionLightPosition = mul(gWorldLightPosition, matViewProjection);
   float4 projectionCameraPosition = mul(gWorldCameraPosition, matViewProjection);
   float3 projectionNormal = mul(Input.mNormal, (float3x3)matViewProjection);
   
   float3 lightDir = Output.mPosition.xyz - projectionLightPosition.xyz;
   lightDir = normalize(lightDir);
   
   float3 viewDir = Output.mPosition.xyz - projectionCameraPosition.xyz;
   viewDir = normalize(viewDir);
   
   float3 reflection = reflect(lightDir, projectionNormal);
   reflection = normalize(reflection);
   
   float3 diffuse = dot(-lightDir, projectionNormal);
   diffuse = saturate(diffuse);
   
   float3 specular = 0;
   
   if(diffuse.x > 0)
   {
      specular = saturate(dot(reflection, -viewDir));
      specular = pow(specular, 20.0f);
   }
   
   float3 ambient = float3(0.1f, 0.1f, 0.1f);
   
   Output.mColor = float4(ambient + diffuse + specular, 1);
   
   return( Output );
}
cs

투영 공간에서 연산을 수행했다

1
2
3
4
5
6
7
8
9
10
struct PS_INPUT
   float3 mColor : COLOR1;
};
 
float4 ps_main(PS_INPUT Input) : COLOR0
{   
   return float4(Input.mColor, 1);
   
}
cs

ambient가 이렇게 간단하게 계산이 될 것 같지는 않지만,

고로 셰이딩은 간단히 말해 밝기 계산을 정점 셰이더에서 처리하는 것을 의미한다.

보간의 힘을 빌리기 때문에 굳이 어떻게든 퀄리티를 떨어트린다면 이정도로 떨어트릴 수 있다.

 

예전 게임들에서 자주 보인 빛의 형태가 보인다.


퐁 셰이딩

픽셀의 법선벡터와 조명벡터로 픽셀의 밝기를 계산

 

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
float4x4 matViewProjection;
 
float4 gWorldLightPosition;
float4 gWorldCameraPosition;
 
struct VS_INPUT 
{
   float4 mPosition : POSITION0;  
   float3 mNormal : NORMAL; 
};
 
struct VS_OUTPUT 
{
   float4 mPosition : POSITION0;   
   float3 mLightDir : TEXCOORD0;
   float3 mViewDir : TEXCOORD1;
   float3 mNormal : TEXCOORD2;
};
 
VS_OUTPUT vs_main( VS_INPUT Input )
{
   VS_OUTPUT Output;
 
   Output.mPosition = mul( Input.mPosition, matViewProjection );
   
   float4 projectionLightPosition = mul(gWorldLightPosition, matViewProjection);
   float4 projectionCameraPosition = mul(gWorldCameraPosition, matViewProjection);
   
   float3 projectionNormal = mul(Input.mNormal, (float3x3)matViewProjection);
   Output.mNormal = projectionNormal;
   
   float3 lightDir = Output.mPosition.xyz - projectionLightPosition.xyz;
   lightDir = normalize(lightDir);
   Output.mLightDir = lightDir;
   
   float3 viewDir = Output.mPosition.xyz - projectionCameraPosition.xyz;
   viewDir = normalize(viewDir);
   Output.mViewDir = viewDir;
   
   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
struct PS_INPUT
   float3 mLightDir : TEXCOORD0;
   float3 mViewDir : TEXCOORD1;
   float3 mNormal : TEXCOORD2;
};
 
float4 ps_main(PS_INPUT Input) : COLOR0
{  
   Input.mLightDir = normalize(Input.mLightDir);
   Input.mViewDir = normalize(Input.mViewDir);
   Input.mNormal = normalize(Input.mNormal);
 
   float3 diffuse = dot(-Input.mLightDir, Input.mNormal);
   diffuse = saturate(diffuse);
   
   float3 reflection = reflect(Input.mLightDir, Input.mNormal);
   reflection = normalize(reflection);
   
   float3 specular = 0;
   
   if(diffuse.x > 0)
   {
      specular = saturate(dot(reflection, -Input.mViewDir));
      specular = pow(specular, 20.0f);
   }
   
   float3 ambient = float3(0.1f, 0.1f, 0.1f);
   
   return float4(diffuse + ambient + specular, 1);
   
}
cs

실제 밝기의 계산은 픽셀 셰이더에서 해줘야 한다.

 

아니 근데 이게 맞나...?

 

 

결과물만 보자면 맞긴 한데... 이 방식이 맞나

 

보다시피, 둘이 대놓고 비교하면 큰 차이가 나긴 한다.

 

아무튼, 고로 셰이딩과 퐁 셰이딩은 위와 같다.

 

androgameprgm.tistory.com/entry/RenderMonkey-Tutorial-03?category=217339

 

RenderMonkey Tutorial - 03

간단한 Phong Reflect 를 이용한 Specular 예제입니다. ---- Vertex Shader ---- 퍼 픽셀 셰이더로 구현 ( 픽셀 단위당 라이트 계산을 하므로 위 그림과 같이 매우 견고한 라이트가 나옵니다. ) float4x4 matView..

androgameprgm.tistory.com

 

'그래픽스' 카테고리의 다른 글

유니티 셰이더, 셰이더  (0) 2020.09.08
Volumetric Light  (0) 2020.09.08
상수 버퍼, constant buffer  (0) 2020.09.08
Assimp  (0) 2020.09.08
God Ray  (0) 2020.09.07

+ Recent posts