본문 바로가기

Unity3D C#/유니티 쉐이더 공부

NormalMap의 함수 적용


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
Shader "Custom/MetallicSmoothness" {
    Properties {
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Metallic("Metallic", Range(0,1)) = 0
        _Smoothness("Smoothness", Range(0,1)) = 0.5
        _BumpMap("NormalMap", 2D) = "bump"{}
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        
        CGPROGRAM
        #pragma surface surf Standard 
 
        sampler2D _MainTex;
        sampler2D _BumpMap;
        float _Metallic;
        float _Smoothness;
 
        struct Input {
            float2 uv_MainTex;
            float2 uv_BumpMap;
        };
 
        void surf (Input IN, inout SurfaceOutputStandard o) {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
            fixed4 d = tex2D (_BumpMap, IN.uv_BumpMap);
            o.Albedo = c.rgb;
            o.Metallic = _Metallic;
            o.Smoothness = _Smoothness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}
 
cs

이렇게 하면 일반 텍스쳐와 동일하게 처리되지만 NormalMap은 일반적인 텍스쳐가 아님. NormalMap은 일반적인 게임용 텍스쳐 포맷인 DXT1 혹은 DXT5가 아니라 DXTnm이라는 파일 포맷임.

이 파일 포맷은 일반적인 텍스쳐의 압축에 의한 NormalMap 품질의 저하를 막기 위해 만든 AG 파일 포맷. 이 포맷은 NormalMap의 R과 G의 퀄리티를 최대한 보전하여 A와 G에 넣어 저장함. (B는 가지고 있지 않음) 이렇게 보전된 R과 G는 NormalMap의 X와 Y로 계산되며, Z는 삼각함수를 이용하여 수학적으로 추출됨

그러므로 이 텍스쳐를 이용해서 NormalMap으로 온전하게 생성해내려면 앞에 설명한 공식이 적용되어 있는 함수를 이용하면 간편함.


float3 y = UnpackNormal ( float4 x ) ;


함수를 적용하여 NormalMap을 적용하는 방법

            fixed4 d = tex2D (_BumpMap, IN.uv_BumpMap);

위 부분을 다음과 같이 수정

            o.Normal = UnpackNormal(tex2D (_BumpMap, IN.uv_BumpMap));


혹은 두 줄로 나누어 써도 동일한 결과를 볼 수 있음

            fixed3 n = UnpackNormal(tex2D (_BumpMap, IN.uv_BumpMap));

            o.Normal = n;

이렇게 두 줄로 나누어 작성하면 x와 y에 특정 숫자를 곱해주면 NormalMap의 감도를 조절해 줄 수 있음. 예를 들어 2를 곱해주면 NormalMap이 2배 강해지고, 0.5를 곱해주면 강도가 절반으로 줄어들게 됨

            fixed3 n = UnpackNormal(tex2D (_BumpMap, IN.uv_BumpMap));

            o.Normal = float3(n.x*2, n.y*2, n.z);


주의사항

UnpackNormal(x) 안의 x는 반드시 float4가 들어가야 함 UnpackNormal 함수의 대소문자 UnpackNormal 함수에 float4 인 데이터를 집어넣으면 결과물로 반드시 float3 데이터로 받아야 함.

fixed4 n = UnpackNormal(tex2D (_BumpMap, IN.uv_BumpMap));라고 쓰면 에러 발생