게임 프로그래밍
[Unity-Shader] Blinn-Phong 본문
스펙큘러 표현 공식은 다양하지만 가장 유명하고 전통적인 방식은 Phong반사 입니다.
이 공식의 기본 원리는
"내가 보는 방향으로부터 반사된 방향에 조명이 있으면 그 부분의 하이라이트가 가장 높다" 입니다.

Blinn-Phong의 공식은
"시선 벡터와 조명 벡터의 중간값인 '하프 벡터'를 구하고, 이를 노멀 벡터와 내적한다."
그렇다하면 하프 벡터는 어떻게 구할 수 있을까요?
벡터의 특징중에 하나를 살펴보면 "길이가 같은 두 벡터를 더 하면, 두 벡터 사이의 절반인 각도가 나온다" 라는 특징이 있습니다.
이를 통해 하프 벡터는 "시선 벡터" 와 "조명 벡터" 를 더 하고 이를 normalize 해주면 됩니다.
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
54
55
56
57
58
|
Shader "Custom/CustomBlinnPhong"
{
Properties
{
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_specCol("SpecColor",Color) = (1,1,1,1)
_specPow("SpecPow",Range(10,100)) = 100
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Test
sampler2D _MainTex;
float _specPow;
float4 _specCol;
struct Input
{
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o)
{
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
float4 LightingTest(SurfaceOutput s, float3 lightDir,float3 viewDir, float3 atten)
{
float3 DiffColor;
float ndotl = saturate(dot(s.Normal,lightDir));
float4 final;
float3 SpecColor;
float3 H = normalize(lightDir+viewDir);
float spec = saturate(dot(H,s.Normal));
spec = pow(spec,_specPow);
SpecColor = spec * _specCol.rgb;
DiffColor = ndotl * s.Albedo * _LightColor0.rgb * atten;
final.rgb = DiffColor + SpecColor.rgb;
final.a = s.Alpha;
return final;
}
ENDCG
}
FallBack "Diffuse"
}
|
cs |
전체 소스입니다. 기본 Lamvert 라이트에 Spec을 추가한 연산입니다.
1
2
3
4
5
|
float3 SpecColor;
float3 H = normalize(lightDir+viewDir);
float spec = saturate(dot(H,s.Normal));
spec = pow(spec,_specPow);
SpecColor = spec * _specCol.rgb;
|
cs |
LightingTest에 이 부분을 보시면, H라는 얘는 normalize(lightDir+viewDir) 로 되어 있습니다.
이는 normalize(시선벡터+조명벡터)로 위에 언급했던 "하프 벡터"를 만드는 공식입니다.
이렇게 만든 하프 벡터를 saturate(dot(H,s.Normal)) -> 노멀 벡터와 내적을 합니다.
그 후, pow 함수를 이용해 스펙큘러의 넓이를 지정해주었습니다.
마지막으로 스펙큘러의 컬러 값을 곱합니다.

이러한 형태가 나오게 될 것입니다.
'프로그래밍 > 유니티' 카테고리의 다른 글
[Unity-Shader] Rim Light (0) | 2020.04.30 |
---|---|
[Unity] hierarchy 에서 특정 Scirpt를 가지고 있는 오브젝트를 찾을때 (0) | 2020.04.04 |
[unity] Unity Ads 넣는 방법 (0) | 2020.04.02 |
[Unity3D] Script Templates (0) | 2020.03.19 |
[Unity] Custom TileMap Creator (0) | 2020.03.17 |
Comments