https://3dtotal.com/tutorials/t/v-ray-30-new-features-and-improved-shaders-paul-hatton-features-render-shader

이전 포스팅에서 커스텀라이트모델로 만든 Specular에 대해 좀 더 자세하게 다룬다.

Specular 공식에는 여러가지가 존재하지만 크게 Phong, Blinn-Phong, GGX로 3가지가 있다.

 

베트남계 미국 컴퓨터 과학자인 Bui Tuong Phong으로 부터 Phong 반사 공식이 탄생이 되었고

이후 Phong공식의 과거 컴퓨터에서의 퍼포먼스 문제를 Jim Blinn이라는 미국 컴퓨터 과학자가 

개량해서 탄생한것이 Blinn-Phong이다.

 

GGX는 Microfacet Models for Refraction through Rough Surfaces 문서에 처음 소개 된것으로 

추측되며 현재 UE4, Unity등 상용엔진에서 사용되는 PBR 쉐이더의 Specular 공식으로 사용되고 

있다. 금속재질까지 쉽게 표현이 가능한것으로 보인다.

 

 

Unity에서 Phong 구현하기

Specular를 표현하는것은 결국 빛방향과 카메라방향에 대한 정반사률에 대한 0~1값을 구하는 것이다.

Phong공식은 빛방향과 노말값을 이용하여 반사(Reflect)방향 값을 구한 후 

반사방향과 카메라 방향의 내적 값으로 정반사률을 구할 수 있다.

 

Phong 공식 

 - float3 fReflectVector = reflect(-lightDir + Normal)

 - float fSpecular = saturate(dot(fReflectVector, viewDir))

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
Shader "Custom/PhongTest"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _BumpMap("Normal Map", 2D) = "bump" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" } 
 
        CGPROGRAM
       
        #pragma surface surf _Cus noambient
 
     
        sampler2D _MainTex;
        sampler2D _BumpMap;
 
        struct Input
        {
            float2 uv_MainTex;
            float2 uv_BumpMap;
        };
 
     
        fixed4 _Color;
 
        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            o.Alpha = c.a;
 
            float3 fNormal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
            o.Normal = fNormal;
        }
 
        float4 Lighting_Cus(SurfaceOutput s, float3 lightDir, float3 viewDir, float atten)
        {
            float3 fSpecular;
            float3 fReflectVector = reflect(-lightDir, s.Normal);
            float fRDotV = saturate(dot(fReflectVector, viewDir));
            fSpecular = pow(fRDotV, 50.0f);
 
            return float4(fSpecular, 1);
        }
 
        ENDCG
    }
    FallBack "Diffuse"
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

 

Unity에서 Blinn-Phong 구현하기

Blinn-Phong과 Phong의 가장큰 차이점은 Reflect Vector를 계산하지 않는 것이다.

Blinn-Phong의 원리는 빛방향과 카메라방향의 중간벡터(Half Vector)를 계산하고

Half Vector와 Normal값의 내적값을 이용하여 Specular 값을 구한다.

 

Blinn-Phong 공식 

 - float3 fHalfVector = normalize(lightDir + viewDir)

 - float fSpecular = saturate(dot(fHalfVector , s.Normal))

 

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
Shader "Custom/BlinnPhongTest"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _BumpMap("Normal Map", 2D) = "bump" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" } 
 
        CGPROGRAM
       
        #pragma surface surf _Cus noambient
 
     
        sampler2D _MainTex;
        sampler2D _BumpMap;
 
        struct Input
        {
            float2 uv_MainTex;
            float2 uv_BumpMap;
        };
 
     
        fixed4 _Color;
 
        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            o.Alpha = c.a;
 
            float3 fNormal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
            o.Normal = fNormal;
        }
 
        float4 Lighting_Cus(SurfaceOutput s, float3 lightDir, float3 viewDir, float atten)
        {
            float3 fSpecular;
            float3 fHalfVector = normalize(lightDir+ viewDir);
            float fHDotN = saturate(dot(fHalfVector, s.Normal));
            fSpecular = pow(fHDotN, 0.0f);
 
            
            return float4(fSpecular, 1);
        }
 
        ENDCG
    }
    FallBack "Diffuse"
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

 


WRITTEN BY
CatDarkGame
Technical Artist dhwlgn12@gmail.com

,