본문 바로가기
Develop Story/Game Engine

Unity - 2D Shader - 폭포 만들기

by 늘상의 하루 2020. 10. 15.

목적으로는 이미지 한장으로 움직이는 폭포를 만드는 것이었습니다.

원래 3D 에서 쓰는 쉐이더를 그대로 사용하려 했으나

2D 쉐이더 작성법도 비슷하다고 하여 도전해 보았습니다.

 

먼저 유니티에 있는 2D Sprite 쉐이더를 열어 보았습니다.

 

뭐가 엄청 많네요

저같은 초보에게는 무리이니 닫았습니다.

구글님에게 물어보면서 적당한 쉐이더를 하나 가져왔습니다.

Shader "Unlit/NewUnlitShader 1"
{

	Properties
	{
		_MainTex("Base (RGB) Trans (A)", 2D) = "white" {}
	}

		SubShader
	{
		Tags {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}
		ZWrite Off Lighting Off Cull Off Fog { Mode Off } Blend SrcAlpha OneMinusSrcAlpha
		LOD 110

		Pass
		{
			CGPROGRAM
			#pragma vertex vert_vct
			#pragma fragment frag_mult 
			#pragma fragmentoption ARB_precision_hint_fastest
			#include "UnityCG.cginc"

			sampler2D _MainTex;
			float4 _MainTex_ST;

			struct vin_vct
			{
				float4 vertex : POSITION;
				float4 color : COLOR;
				float2 texcoord : TEXCOORD0;
			};

			struct v2f_vct
			{
				float4 vertex : POSITION;
				fixed4 color : COLOR;
				float2 texcoord : TEXCOORD0;
			};

			v2f_vct vert_vct(vin_vct v)
			{
				v2f_vct o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.color = v.color;
				o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);;
				return o;
			}

			fixed4 frag_mult(v2f_vct i) : COLOR
			{
				fixed4 col = tex2D(_MainTex, i.texcoord) * i.color;
				return col;
			}

			ENDCG
		}
	}

		SubShader
			{
				Tags {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}
				ZWrite Off Blend SrcAlpha OneMinusSrcAlpha Cull Off Fog { Mode Off }
				LOD 100

				BindChannels
				{
					Bind "Vertex", vertex
					Bind "TexCoord", texcoord
					Bind "Color", color
				}

				Pass
				{
					Lighting Off
					SetTexture[_MainTex] { combine texture * primary }
				}
			}
}

 

그나마 제가 만지작거리기 좋은 분량이네요.

천천히 내용들을 까 보던 와중 저는 엄청난 것을 깨달았습니다.

2D 스프라이트 쉐이더에서는 오프셋 기능이 없다는 사실을...

 

그저 소소하게 오프셋을 움직여서 물이 흐르는 듯한 효과를 주려던 제게는 너무나 충격적인 사실이었습니다.

 

검색을 해 보니 스프라이트 자체가 유니티에서는 고정 영역을 정의한다는 가정으로 설계된 물건이라

오프셋 기능이 제거되었다고 나옵니다.

-지금은 어떨지 모르겠네요-

 

아무튼 안된다고는 하지만 무슨 결과가 나오나 싶어 직접 해보기로 했습니다.

대충 아무 이미지나 집어 넣었습니다.

 

그 다음으로 쉐이더의 오프셋을 움직일 코드를 작성했습니다.

 

using UnityEngine;

public class WaterFallUVScript : MonoBehaviour
{
    public Material textureToAnimate;

    protected Vector2 uvOffset = Vector2.zero;
    public Vector2 uvAnimationRate = new Vector2(0.3f, 0.3f);

    protected MeshRenderer backgroundMeshRenderer;

    [SerializeField]
    protected bool resetPositionToZero = true;

    protected void Start()
    {
        backgroundMeshRenderer = GetComponent<MeshRenderer>();

        if (backgroundMeshRenderer != null)
        {
            if (resetPositionToZero)
                backgroundMeshRenderer.transform.position = Vector3.zero;

            textureToAnimate = backgroundMeshRenderer.material;
        }
    }

    protected void Update()
    {
        if (textureToAnimate != null)
        {
            if (uvOffset.x >= 1.0f)
            {
                uvOffset.x = 0.0f;
            }

            if (uvOffset.y >= 1.0f)
            {
                uvOffset.y = 0.0f;
            }

            uvOffset += uvAnimationRate * Time.deltaTime;
            textureToAnimate.mainTextureOffset = uvOffset;
        }
    }
}

이제 실행시키면...

 

 

 

오...

 

다른 방법을 찾아봐야겠네요.