본문 바로가기

Unity3D/shader_스터디

[Unity 쉐이더] Custom Light2 - Normal, Rim Light

이어서 커스텀 라이트

sunsimu1018.tistory.com/16?category=919389

 

[Unity 쉐이더] vector, Custom Light

Vector 연산 Dot 연산 커스텀 라이트 (렘버트) 벡터의 덧셈 뺄셈 친절하게 설명해주시는 영상 (앞부분에서 덧셈 참고) www.youtube.com/watch?v=0Ho616gAijQ&t=380s A+B 시점이 일치하는 벡터는 A벡터와 B벡터를..

sunsimu1018.tistory.com

 

 

커스텀 라이트를 이어서 하기 전 Lambert, Custom Light를 준비하고 갑시다.

 

Lambert
Custom Light

 

Normal

 

우선 저번에 진행한 라이트에 노말을 추가합니다. 노말 추가는 간단합니다.

기존에 노말을 불러오는 방식과 똑같습니다. NdotL연산 전에만 불러오면 됩니다.

 

 

노말을 가져왔지만 아직 스페큘러도 없는 상태이기 때문에 부족해 보입니다. 

 


Rim Light

노말 다음으로는 림라이트를 적용해보고자 합니다.

 

그 전에 이번 림 라이트에 사용할 viewDir를 보고 갑시다. 

uv나 vertexcolor를 가져오던 Input내에서 불러 올 수 있습니다.

지금까지는 버텍스에 담겨있는 정보를 가져오는 용도로 사용했지만 Input에서는 노말 벡터나 공간 정보등도 취급하고 있습니다.

 

 

이번에는 두가지만 간략히

대소문자에 주의

 

worldNormal- 말 그대로 월드 노말 벡터를 뜻합니다.  오브젝트가 이동해도 월드 기준으로 노말값이 들어가는 것을 볼 수있습니다.

viewDir- 뷰 방향(카메라)을 기준으로 나타냅니다. 시차 효과, 림라이트 등을 구현하는데 주로 사용됩니다.

 

worldNormal
viewDir

 

 

램버트 라이트를 준비합니다. 엠비언트를 꺼서 더 보기 편하게 하고 진행합니다.

 

 

 

림라이트는 기존의 라이트 방향을 이용하던 라이팅과 달리 뷰 뱡향을 기준으로 합니다.

아래와 같이 NdotL값을 구하면 카메라 플래시를 이용한 것 같은 결과가 나옵니다.

float rim = dot(o.Normal,IN.viewDir);

 

 

현재 상태에서 뒷면은 어떻게 생겼을까요? rim값을 1- 해봅시다.

 

마주보지 않는 뒷면에 음영이 지고, 그것을 뒤집으면 림라이트와 같은 결과가 나오게 됩니다.

그러나 cull off를 통해 뒷면을 보면 밝게 나타나게 됩니다. 한 면으로 제작된 깃발이나 머리카락 같은 오브젝트의 뒷면이 번쩍거리게 되겠죠. 이 현상은 어떻게 해결해야 할까요.

 

 

 


 

절대값(ABS)

 

아래 사진과 같이 절대값을 이용해 음수도 양수로 표현하는 겁니다.

현재의 라이팅의 연산 값이 1~-1 내에서 이루어지기 때문에 절대값을 적용할 경우 뒷면도 앞과 같은 결과가 나오게 됩니다. 

 

갑자기 노드

 

 

뒷면의 문제도 해결했으니 보기 좋게 림라이트의 강도도 조절합니다.

 

 

추가로 엠비언트를 키고 노말, 텍스쳐를 추가해 봅니다.

전체 코드

더보기
Shader "Custom/rim"
{
    Properties
    {
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _BumpMap ("Normal", 2D) = "bump" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        cull off

        CGPROGRAM
        #pragma surface surf Lambert //noambient
        #pragma target 3.0

        sampler2D _MainTex;
        sampler2D _BumpMap;

        struct Input
        {
            float2 uv_MainTex;
            float2 uv_BumpMap;
            float3 viewDir;
        };

        void surf (Input IN, inout SurfaceOutput o)
        {
            //텍스쳐와 노말맵
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
            float3 n = UnpackNormal(tex2D (_BumpMap,IN.uv_BumpMap));
            o.Normal = n;

            //기존에 라이트 방향(lightDir)을 이용하던 것과 달리 뷰 뱡향(viewDir)을 이용합니다.
            //abs를 통해 뒷면이 밝아지는 것을 방지
            float rim = abs(dot(o.Normal,IN.viewDir));
            //강도 조절
            rim = 1-pow(rim,0.3);

            o.Emission = rim;
            o.Albedo = c.rgb;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

 

+

림라이트를 알파값으로 내보내고 노말을 추가해 여러 가지 방법으로 응용할 수도 있습니다.

 

 

 

안사라지는 사진