그래픽스 스터디 (6)

4138 단어 graphicsgraphics

여기에서는 알파가 있는 텍스처를 다뤄보려고 한다

  • 알파는 다른 것과 달리 상당히 무거운 연산이다

1. 알파채널 .tga 파일 구하기

이미지는 알파채널이 있는 .tga 파일을 사용했다
알파채널이 있는 이미지 찾기가 어려워서 포토샵에서 알파채널을 만들어주었다

텍스처만 넣어주는 기본 쉐이더에서는 아래와 같이 나타난다

2. 알파 채널이 적용되도록 만들기

알파 채널이 적용되도록 만들면 다음과 같이 된다
쉐이더 코드에서 특별히 바뀌는 부분은 Tags와 #pragma 부분이다

Shader "Custom/AlphaTest"
{
    Properties
    {
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
    }

    SubShader
    {
        
        // Tags { "RenderType"="Opaque"} // NO ALPHA
        Tags { "RenderType"="Transparent" "Queue"="Transparent" } // ALPHA
        LOD 200

        CGPROGRAM
        
        // #pragma surface surf Standard fullforwardshadows // NO ALPHA
        #pragma surface surf Standard alpha:fade // ALPHA
        sampler2D _MainTex;

        struct Input
        {
            float2 uv_MainTex;
        };

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

3. 곱하기 연산자를 사용하여 두 이미지 합치기


그 다음 실습은
책에서는 위와 같이 불 모양 그림 위에 타오르는 듯한 이미지를 합쳐서 불을 만들었는데,
나는 어색하긴 하지만 구름에 하늘 사진을 합쳐보고, 흐르는 방향도 바꾸었다

그리고 두 이미지를 합칠 때 곱하기 연산자를 사용하는데, 그 이유를 생각해보라고 한다

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
            fixed4 d = tex2D (_MainTex2, float2(IN.uv_MainTex2.x - _Time.y, IN.uv_MainTex2.y));
            o.Emission = c.rgb * d.rgb; 
            o.Alpha = c.a * d.a;
        }

색깔을 곱하는 경우는 두 이미지의 색상이 자연스럽게 합쳐지도록 하기 위해서 인 것 같고,
알파를 곱하는 경우는 둘 중 한 이미지의 알파값이 0이면 그 부분에 아무 이미지도 출력되면 안되기 때문인 것 같다
(그래야 구름 모양 안에 새로운 이미지를 가둘 수 있으니까..!?)

결론적으로 이 코드는 무거운 standard 라이팅이 돌아가고 있는 불완전한 이펙트라고 한다..!

4. 이미지를 구겨지게 만들고, 흐르게 하기

다음은 다른 방식을 사용하여 이펙트를 더 자연스럽게 바꾸는 과정이다

1) 이미지 구겨지게 만들기

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            fixed4 d = tex2D (_MainTex2, IN.uv_MainTex2);
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex + d.r);
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }

위 코드를 보면 c 이미지의 UV에 d.r을 더하고 있다
아래 사진처럼 d는 검정색 이미지이므로 (0, 0, 0, 1)이다.
따라서 아무 반응 없이 그냥 Unity 로고 이미지가 잘 출력된다

그런데 만약 다음 밤하늘 사진같이 r의 컬러값이 일정하지 않은 사진으로 바꾸면 신기하게 변한다

이 실습은 '컬러를 숫자처럼' 사용하는 중요한 개념을 가지고 있다고 한다
이미지에 분포된 컬러값을 이용하여, 또 다른 이미지의 UV 좌표값 바꾸어서 이펙트처럼(?) 사용하기 때문인 것 같다

2) 이미지 흐르게 하기

다음으로 밤하늘 이미지를 흐르게 만들면 아래 gif와 같이 된다
fixed4 d = tex2D (_MainTex2, float2(IN.uv_MainTex2.x, IN.uv_MainTex2.y - _Time.y));

보고 있으면 얼음 같기도 하고, 물 같기도 하고 신기한 느낌이다
멀미날 거 같기도 하고


위 방식을 이용해서 책에서 배포한 리소스를 사용하여 만들어보면 위 gif와 같이 된다
아직 어색한 부분이 있지만 신기하ㄷㅏ..!

#pragma surface surf Standard alpha:fade
위 구문 때문에 이 방식은 실무에서 쓰기에 적합하지 않다고 한다

  • Standard(Standard Shader)를 사용하여, 물리 기반 라이팅이 작동되고 있기 때문
  • 심지어 이 쉐이더에서는 물리 기반 라이팅 공식이 사용되고 있지 않음에도 무거운 연산이 이루어지고 있어서 비효율적

다음에는 PART 7 버텍스 컬러 이용하는 법을 배운다

참고

  • 테크니컬 아티스트를 위한 유니티 쉐이더 스타트업 (정종필 저)

좋은 웹페이지 즐겨찾기