유니티 셰이더 기초 - 텍스쳐 합치기 / lerp 보간하기 !! / 그레이 스케일

코드멍멍이(Joonieboy)·2022년 9월 20일
1
post-thumbnail

Texture Mixing !!


lerp로 텍스쳐를 합쳐보자 !!

텍스쳐를 합치는 방법은 어렵지 않아 !! 생각보다 간단하니까 천천히 글을 읽어봐~ 일단 텍스쳐를 합치기 전에 유니티에서 셰이더를 만들고, 이 안에 있는 쓸모 없는 것들을 다 지워주자 !! 예를 들면, 그런거 있자나~ Smoothness, Metal 등 텍스쳐에 관련 없는 것들!!

그리고 텍스쳐를 2개 넣을 수 있도록 만들어줄거야~ MainTex2를 하나 더 만들어주는거지, 그러면 유니티 인스펙터에서 텍스쳐를 하나 더 넣을 수 있으니까, 여기까지 오면 텍스쳐를 2개 넣을 수 있어 !! 그리고 여기에 lerp 보간을 사용할거야. 하지만, 뭔가 이상하다는 걸 느낄걸~

Shader "Custom/textureMixing"
{
    Properties
    {
        //텍스쳐 2개를 넣을 수 있도록 만든다
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _MainTex2 ("Albedo (RGB)", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }

        CGPROGRAM
        #pragma surface surf Standard

        sampler2D _MainTex;
        sampler2D _MainTex2;

        struct Input
        {
            float2 uv_MainTex;
            float2 uv_MainTex2;
        };

        fixed4 _Color;

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
            fixed4 d = tex2D (_MainTex2, IN.uv_MainTex2);
            
            //주목 !!!!!!!!!!!!!!!!
            o.Albedo = lerp(c.rgb, d.rgb, 0);


            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

셰이더 코드에 있는 "//주목!!!!!!!!!!!"에 주목해주길 바래!! 여기에 있는 코드중에 o.Albedo = lerp(c.rgb, d.rgb, 0); 이 부분이 있어!! 여기에 가장 마지막에 있는 float 값이 1이 되면, MainTex2가 보이고, 0이면, MainTex1이 보일거야!

그러면, 이 사이를 보여주면 어떨까? 0.5를 하면, 텍스쳐는 섞이게 되 !! 왜 이럴까?? 우리가 보간하는 것들 중 흔하게 예를 들만한 것은 그라데이션이야!! 검은색과 흰색이 있는 그라데이션이 있어. 검은색은 0이고 흰색은 1이라고 보자. 그러면 가운데 회색은 무슨 색일까? 검은색과 흰색이 섞여서 회색이 되지? 텍스쳐도 똑같다고 보면 되!! A와 B의 사이는? 둘이 섞여서 나오겠지~

lerp를 인터페이스로 연결하기 !!

lerp를 인터페이스로 연결하면, 편하게 텍스쳐 2개를 왔다리 갔다리 쉽게 변경이 가능해! 그리고 합치기도 가능해서 텍스쳐를 섞을 경우에 이 방법을 사용하는 것을 추천해!! 인터페이스로 연결하는건 쉬워서 금방 따라할 수 있을거야~ 일단, 바로 코드를 보자 !!

Shader "Custom/textureMixing"
{
    Properties
    {
        //텍스쳐 2개를 넣을 수 있도록 만든다
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _MainTex2 ("Albedo (RGB)", 2D) = "white" {}

        //인터페이스와 연결하여 Range로 어떤 텍스쳐가 나오게 할지 혹은 섞이게 할지 조정할 수 있게 만든다
        _lerpTest ("lerp 기능 테스트", Range(0, 1)) = 0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }

        CGPROGRAM
        #pragma surface surf Standard

        sampler2D _MainTex;
        sampler2D _MainTex2;
        float _lerpTest;

        struct Input
        {
            float2 uv_MainTex;
            float2 uv_MainTex2;
        };

        fixed4 _Color;

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
            fixed4 d = tex2D (_MainTex2, IN.uv_MainTex2);

            //lerp를 사용하여 텍스쳐 2개를 보간한다 lerp(A, B, 0 ~ 1 float값);
            o.Albedo = lerp(c.rgb, d.rgb, _lerpTest);

            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

코드에도 적혀있다시피 내가 쉽게 구현이 가능하도록 다 적어놨어 !! 일단, 프로퍼티에서 Range로 조절이 가능하도록 lerpTest를 만들어주고, 당연히 CGPROGRAM 밑에 float 값으로 초기화를 해줘 !! 마지막으로 아까 만들어 주었던 o.Albedo = lerp(c.rgb, d.rgb, 0); 이 코드의 0에 lerpTest를 넣어주기만 하면 되!! 그러면, 유니티 인스펙터에서 조절이 가능하다는거!

풀 배경을 없애서 흙과 자연스럽게!!

사실 이 텍스쳐 2개를 보면 하고 싶은게 보이지 않아? 풀 배경을 없애서 흙이랑 풀이랑 어떻게 자연스럽게 합칠 수 있을까 !! 사실 이거는 아주 약간 고민해야 할 문제일 수도 있어~ 풀 텍스쳐의 알파 채널은 일단 한 번 볼까?

아까 말했듯이 알파 채널의 검은색은 0이고, 흰색은 1이야. 그러면 이 알파채널에서 검은색을 빼기만 하면 되겠지? 사실 검은색만 빼는 방법은 너무나도 쉬워. 텍스처 인스펙터를 보면 "Alpha Is Transparency"를 체크를 해주기만 하면 되. 그러면 검은 색이 사라져서 풀만 보이게 되겠지?

하지만 이렇게 한다고 해서, 흙 텍스쳐와 풀 텍스쳐가 자연스럽게 합쳐지는건 아니야. 그러면 이 둘을 명확히 보이게 하면서 풀만 흙 위에 덮어 씌우기만 하면 되는거지. 즉, 돌 텍스쳐 위에 풀 텍스쳐가 있으면서 풀의 배경색만 없애면 되는거야 !! 일단 코드부터 보자~

Shader "Custom/textureMixing"
{
    Properties
    {
        //텍스쳐 2개를 넣을 수 있도록 만든다
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _MainTex2 ("Albedo (RGB)", 2D) = "white" {}

        //인터페이스와 연결하여 Range로 어떤 텍스쳐가 나오게 할지 혹은 섞이게 할지 조정할 수 있게 만든다
        _lerpTest ("lerp 기능 테스트", Range(0, 1)) = 0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }

        CGPROGRAM
        #pragma surface surf Standard

        sampler2D _MainTex;
        sampler2D _MainTex2;
        float _lerpTest;

        struct Input
        {
            float2 uv_MainTex;
            float2 uv_MainTex2;
        };

        fixed4 _Color;

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
            fixed4 d = tex2D (_MainTex2, IN.uv_MainTex2);

            //lerp를 사용하여 텍스쳐 2개를 보간한다 lerp(A, B, 0 ~ 1 float값);
            //o.Albedo = lerp(c.rgb, d.rgb, _lerpTest);
            
            //풀의 알파채널을 보면, 흰색과 검은색 두 가지가 있다. 흰색은 1이고, 검은색은 0이다
            //풀의 알파값은 0이기 때문에 c.a를 넣으면, 풀만 없어지게 나온다
            //o.Albedo = lerp(c.rgb, d.rgb, c.a);
            
            //반대로 풀만 나오게하고 배경이 없어지게 하려면, 2 가지 방법이 있다
            //1. c.a를 리버스 시킨다 -> 1-c.a
            o.Albedo = lerp(c.rgb, d.rgb, 1-c.a);

            //2. c와 d의 위치를 바꾸어 준다
            //o.Albedo = lerp(d.rgb, c.rgb, c.a);

            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

코드에 나와있는 대로 배경만 없애는 방법은 2가지 방법이 있어 ! 일단, 그 위에 있는 코드인 o.Albedo = lerp(c.rgb, d.rgb, c.a); 로 하게 되면, 풀만 사라지게 보일거야. 그러면 우리가 드는 생각은 이를 리버스 시키면 된다고 생각하겠지? 바로 그거야! 그 방법이 풀만 나오게 하는 첫 번째 방법이지. 1-c.a만 해주면, 리버스를 시킬 수 있어. 그리고 두 번째 방법은 c.rgb와 d.rgb의 위치를 바꾸어 주는거지.

그레이 스케일 !! 흑백으로 만들자 !!

마지막으로 그레이 스케일에 대해서 알려줄게 !! 가장 쉽게 그레이 스케일로 바꾸는 방법은 (c.r + c.g + c.b) / 3; 를 하는 방법이야!! 사실 정확하게 하는 방법은 따로 있지만, 이 방법은 너무 복잡하기 때문에 보통 저 방법을 가장 많이 이용해 !!

그러면 재밌게도 풀만 회색이 되는 마법!! 이 이루어지지~ 이렇게 간단한 방법으로 새로운 느낌을 줄 수 있으니, 여러가지 시도를 하는 것도 좋다고 생각해~ 오늘도 끝까지 읽어줘서 너무 고마워~

공부한 책: 유니티 쉐이더 스타트업

profile
#유니티개발자 #게임 #인플루언서 #ENFJ

0개의 댓글