공부중

[Unity Shader]울렁울렁 거리는 굴절을 표현해 보자 본문

Programing/Unity3D

[Unity Shader]울렁울렁 거리는 굴절을 표현해 보자

곤란 2020. 5. 20. 17:20
반응형

유니티 쉐이더 책을 좀 읽어보고 구현해보고 싶은것을 만들어 보려고 한다.

 

 

 

만들어 보고 싶은 효과는 위의 영상에서 Gold/Silver버전의 사이코키네시스의 효과를 만들어보고 싶었다.

 

 

 

일단 다음화면처럼 모델을 배치해 주었다.

 

그리고 그 앞에 굴절효과를 줄 Quad를 생성해 주었다.

이제 이 Quad에다가 쉐이더를 새로 만들어서 적용시켜주려고 한다.

 

Shader "Custom/Refraction"
{
    Properties
    {
        _MainTex("Albedo (RGB)", 2D) = "white" {}
        _RefStrength("Reflection Strength", Range(0,0.1)) = 0.05
    }
    SubShader
    {
    	// 다른 일반 오브젝트들보다 나중에 그려져야 배경캡쳐가 되므로 Transparent 와 zwrite off를 사용한다.
        Tags { "RenderType" = "Transparent" "Queue"="Transparent" }
        zwrite off			

        GrabPass { }        // 화면 캡쳐

        CGPROGRAM
        #pragma surface surf nolight noambient alpha:fade

        sampler2D _GrabTexture;
        sampler2D _MainTex;
        float _RefStrength;

        struct Input
        {
            float4 color:COLOR;
            float4 screenPos;		// 현재 화면의 UV
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o)
        {
            float4 ref = tex2D(_MainTex, float2(IN.uv_MainTex.x, IN.uv_MainTex.y));

            // 카메라의 거리 영향을 제거하기 위함.
            float3 screenUV = IN.screenPos.rgb / IN.screenPos.a;
            o.Emission = tex2D(_GrabTexture, (screenUV.xy + ref.x * _RefStrength)); 
        }

        float4 Lightingnolight(SurfaceOutput s, float3 lightDir, float atten)
        {
            return float4(0, 0, 0, 1);
        }

        ENDCG
    }
    FallBack "Regacy Shaders/Transparent/Vertexlit"
}

작성한 쉐이더는 위와 같다. 

여기까지는 유니티 쉐이더 스타트업 책에있는 코드와 똑같아서 특별한것은 없다.

 

 

그리고 울렁거림을 표현해줄 텍스쳐를 적절하게 만들어준다.

256*256의 크기로 위와같이 만들어 주었다.

 

그러면 아래와 같은 결과가 나올것이다.

굴절된 모습은 보이지만 움직이질 않는다.

여기서 시간을 이용해서 UV를 이동시켜보자

        void surf (Input IN, inout SurfaceOutput o)
        {
            float4 ref = tex2D(_MainTex, float2(IN.uv_MainTex.x, IN.uv_MainTex.y+_Time.y * 0.1));

            // 카메라의 거리 영향을 제거하기 위함.
            float3 screenUV = IN.screenPos.rgb / IN.screenPos.a;
            o.Emission = tex2D(_GrabTexture, (screenUV.xy + ref.x * _RefStrength)); 
        }

surf 함수의 첫째 줄 tex2D에서 uv를 전달시 x는 이동하지 않고 y만 시간값을 더해서 이동시켜주고 있다.

 

만일 위의 스크린샷과 같이 일정 시간이 지난뒤에 울렁거림이 사라졌다면 Texture 설정을 변경해주어야 한다.

위의 스크린샷처럼 Repeat으로 바꾸어서 반복되는 텍스쳐가 나올수 있도록 수정해주면 된다.

 

이제 울렁거리는 효과는 완성되었으니 색반전도 시켜보고 싶었다. 코드는 아래와 같다.

        void surf (Input IN, inout SurfaceOutput o)
        {
            float4 ref = tex2D(_MainTex, float2(IN.uv_MainTex.x, IN.uv_MainTex.y+_Time.y * 0.1));

            // 카메라의 거리 영향을 제거하기 위함.
            float3 screenUV = IN.screenPos.rgb / IN.screenPos.a;
            o.Emission = 1 - tex2D(_GrabTexture, (screenUV.xy + ref.x * _RefStrength));
        }

간단하게 1에서 값을 빼준것 밖에 없다.

결과는 아래와 같이 되어 나온다.

훌륭히 잘 나왔고 울렁거림의 속도를 프로퍼티로 받아 변경할수 있게끔 수정하였다.

최종 코드는 아래와 같다.

Shader "Custom/Refraction"
{
    Properties
    {
        _MainTex("Albedo (RGB)", 2D) = "white" {}
        _RefStrength("Reflection Strength", Range(0,0.1)) = 0.05
        _RefSpeed("Reflection Speed", float) = 0.1
    }
    SubShader
    {
    	// 다른 일반 오브젝트들보다 나중에 그려져야 배경캡쳐가 되므로 Transparent 와 zwrite off를 사용한다.
        Tags { "RenderType" = "Transparent" "Queue"="Transparent" }
        zwrite off			

        GrabPass { }        // 화면 캡쳐

        CGPROGRAM
        #pragma surface surf nolight noambient alpha:fade

        sampler2D _GrabTexture;
        sampler2D _MainTex;
        float _RefStrength;
        float _RefSpeed;

        struct Input
        {
            float4 color:COLOR;
            float4 screenPos;		// 현재 화면의 UV
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o)
        {
            float4 ref = tex2D(_MainTex, float2(IN.uv_MainTex.x, IN.uv_MainTex.y+_Time.y * _RefSpeed));

            // 카메라의 거리 영향을 제거하기 위함.
            float3 screenUV = IN.screenPos.rgb / IN.screenPos.a;
            o.Emission = 1 - tex2D(_GrabTexture, (screenUV.xy + ref.x * _RefStrength));
        }

        float4 Lightingnolight(SurfaceOutput s, float3 lightDir, float atten)
        {
            return float4(0, 0, 0, 1);
        }

        ENDCG
    }
    FallBack "Regacy Shaders/Transparent/Vertexlit"
}

 

이 쉐이더를 적용해서 아래와 같이 사용했다.

 

음 잘되는것 같다!

반응형