Surface Shader Specular

스펙큘러 라이팅에 대해서 알아본다.
내장 라이팅 모델은 Lambert(디퓨즈 라이팅)과 BlinnPhong(반사 라이팅)이다.

1. 유니티 내장 블린 퐁(BlinnPhong) 스펙큘러 라이팅




Shader "Custom/BlinnPhong"
{
    Properties
    {
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _MainTint ("Diffuse Tint", Color) = (1,1,1,1)
        _SpecColor ("Specular Color", Color) = (1,1,1,1)
        _SpecPower ("Specular Power", Range(0,1)) = 0.5
    }
    
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200
        
        CGPROGRAM
        #pragma surface surf BlinnPhong

        sampler2D _MainTex;
        float _SpecPower;
        float4 _MainTint;

        struct Input
        {
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o)
        {
            half4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint;
            o.Specular = _SpecPower;
            o.Gloss = c.r;
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

프로퍼티에 선언된 _SpecColor를 변수에는 추가하지 않는다. 유니티가 내장 스펙큘러 모델을 위해 이미 만들어둔 변수이다. 커스텀으로 라이팅 모델을 작성할때는 변수에 추가 해야 한다.

블린 퐁 라이팅 모델을 #pragma 문에 추가 한다.

#pragma surface surf BlinnPhong

유니티 라이팅 모델은 유니티 설치 폴더 아래 Data 폴더에서 UnityCG.cginc 파일에 있다.
(Windows 의 경우, {unity install path}/Data/CGIncludes/Lighting.cginc, Mac의 경우, /Applications/Unity/Unity.app/Contents/CGIncludes/Lighting.cginc)


2. 커스텀 퐁 스펙큘러 라이팅

내장 라이팅 함수 대신 자체적으로  라이팅 함수를 직접 만들어 보자.
유니티에서 제공하는 라이팅 함수는 3가지다.

1. 뷰 의존 아님, 포워드 렌더링 패스
half4 Lighting<Name> (SurfaceOutput s, half3 lightDir, half atten)

2. 뷰 의존, 포워드 렌더링 패스
half4 Lighting<Name> (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten)

3. 지연 라이팅 패스
half4 Lighting<Name>_PrePass (SurfaceOutput s, half4 light)

여기서는 스펙큘러를 사용하므로 뷰 의존, 포워드 렌더링 패스를 사용한다.

함수를 다음과 같이 작성한다.

#pragma surface surf Phong
.....
fixed4 LightingPhong (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten)



Shader "Custom/Phong"
{
    Properties
    {
        _MainTint ("Diffuse Tint", Color) = (1,1,1,1)
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _SpecularColor ("Specular Color", Color) = (1,1,1,1)
        _SpecPower ("Specular Power", Range(0.1,30)) = 1        
    }
    
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200
        
        CGPROGRAM
        #pragma surface surf Phong
        
        float4 _SpecularColor;
        sampler2D _MainTex;
        float4 _MainTint;
        float _SpecPower;
        
        inline fixed4 LightingPhong (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten)
        {
            //Calculate diffuse and the reflection vector
            float diff = dot(s.Normal, lightDir);
            float3 reflectionVector = normalize((2.0 * s.Normal * diff) - lightDir);
            
            //Calculate the Phong specular
            float spec = pow(max(0,dot(reflectionVector, viewDir)), _SpecPower);
            float3 finalSpec = _SpecularColor.rgb * spec;
            
            fixed4 c;
            c.rgb = (s.Albedo * _LightColor0.rgb * diff) + (_LightColor0.rgb * finalSpec);
            c.a = 1.0;
            return c;
        }

        struct Input
        {
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o)
        {
            half4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint;
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

LightingPhong (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten)에서

유니티는 lightDir, viewDir 방향이 반대이다. 라이트 함수로 넘어 올때 라이트와 카메라를 향하고 있다는 것을 명심해야 한다.

lightDir은 오브젝트를 소스 라이트를 목적지로 향하 벡터
viewDir은 오브젝트를 소스 카메라를 목적지로 하는 벡터이다.

유니티에서는 아래 그림과 같이 라이트의 방향은 라이트를 향한다.
라이트의 방향이 라이트를 향할때의 반사 벡터식은 다음과 같다.


일반적으로 라이트의 방향은 오브젝트를 향한다. 반사 벡터식은 다음과 같다.


스펙큘러 라이팅을 구하는 식은 다음과 같다.



float spec = pow(max(0,dot(R, V)),  shininess);


참조)
https://docs.unity3d.com/kr/current/Manual/SL-SurfaceShaderLighting.html
유니티 Shader와 Effect제작 99페이지 (에이콘 출판사)
http://mgun.tistory.com/1337

UnityCG.cgin에서 헬퍼 함수 ObjSpaceViewDir, ObjSpaceLightDir 설명
http://docs.unity3d.com/kr/current/Manual/SL-BuiltinIncludes.html

UnityCG.cginc 소스
http://www.flyingcargame.com/Ouya/Alpha2Shadows/UnityCG.cginc