Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
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
Archives
Today
Total
관리 메뉴

게임 프로그래밍

[Unity-Shader] Rim Light 본문

프로그래밍/유니티

[Unity-Shader] Rim Light

Junwe 2020. 4. 30. 19:45

모든 물체는 기울어질수록 반사가 심해집니다. 반사율은 재질에 따라 다르게 나타납니다.

역광이거나, 털이거나 반투명 재질을 가진 물체들은 이 현상이 매우 강렬하게 나타날수 있고, 재질에 따라 잘 안보일 수도 있습니다. 사진 분야에서는 이것을 Rim Light라고 부릅니다.

금속 재질은 비금속 재질보다 확연하게 반사율이 다릅니다. 이러한 반사 공식을 Fresnel(프레넬) 이라 부릅니다.

이 프레넬 공식을 구현해 림 라이트를 만들어 봅시다.

Lambert 라이트에 대해서 잠깐 얘기해보겠습니다. "노멀 벡터와 조명 벡터의 각도가 같으면 밝고, 90도가 되면 어두워진다" 이었습니다.

1
2
3
4
5
struct Input
{
    float2 uv_MainTex;
    float3 viewDir;
};
cs

input에 float viewDir을 추가하였습니다.이것은 "뷰 벡터" 입니다. 이는 버텍스에서 카메라가 바라보는 방향을 나타냅니다.

1
2
3
4
5
6
7
        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex );
            float rim = dot(o.Normal, IN.viewDir);
            o.Emission = rim;
            o.Alpha = c.a;
        }
cs

이를 Lambert 라이트 처럼 버텍스와 내적을 하게 해준다면, 뷰 벡터와 마치 라이팅처럼 연산이 될 것입니다. 카메라가 마치 조명처럼 인식되어 내가 바라보는 방향이 계속 밝아지게 되는것 입니다.

카메라가 보는 방향에 따라 빛 연산이 됩니다.

이 결과를 뒤집어 줍니다.

1
2
3
4
5
6
7
        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex );
            float rim = dot(o.Normal, IN.viewDir);
            o.Emission = 1 - rim;
            o.Alpha = c.a;
        }
cs

 

외각이 점점 밝아지면서 림 라이트처럼 보이게 됩니다.

 

1
2
3
4
5
6
7
        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex );
            float rim = dot(o.Normal, IN.viewDir);
            o.Emission = pow(1 - rim,3);
            o.Alpha = c.a;
        }
cs

 

제곱 계산을 통해 쎄기를 조절할 수 있습니다.

 

1
2
3
4
5
6
7
8
        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex );
            //o.Albedo = c.rgb;
            float rim = dot(o.Normal, IN.viewDir);
            o.Emission = pow(1 - rim,3) * _Color;
            o.Alpha = c.a;
        }
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
35
36
37
38
39
40
41
42
43
44
45
Shader "Custom/Rim"
{
    Properties
    {
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Color("Color",Color) = (1,1,1,1)
    }
    SubShader
    {
        Tags { "RenderType"="Transparent" "Queue"="Transparent" }
        LOD 200
 
        CGPROGRAM
        #pragma surface surf Standard Lambert noambient
 
 
        sampler2D _MainTex;
        float4 _Color;
 
        struct Input
        {
            float2 uv_MainTex;
            float3 viewDir;
        };
 
        // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
        // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
        // #pragma instancing_options assumeuniformscaling
        UNITY_INSTANCING_BUFFER_START(Props)
            // put more per-instance properties here
        UNITY_INSTANCING_BUFFER_END(Props)
 
        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex );
            o.Albedo = c.rgb;
            float rim = dot(o.Normal, IN.viewDir);
            o.Emission = pow(1 - rim,3) * _Color;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}
 
cs

전체소스 코드 입니다.

Comments