Unity로 1 다각형 파문 만들기

이 기사에 대하여



Unity에서 아래 이미지와 같은 파문 (움직임)과 같은 것을
주로 ShaderLab을 사용하여 만들었으므로 소개합니다.



64bit Windows에 설치
Unity2017.4.28f1, MonoDevelop5.9.6, Metasequoia4Ver4.7.0을 사용하고 있습니다.

1 다각형 객체를 만듭니다.



우선 3D 모델링 소프트웨어로
UV 전개가 이루어진 정삼각형판 폴리곤을
이런 식으로 만들어 갑니다.



셰이더



Hamon.shader
Shader "Unlit/Hamon"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Power ("Power",Range(0,100)) = 0
        _Period("Period",Range(0,100))=0
        _Speed("Speed",Range(0,1000))=0
        _Detail("Detail",Range(0,100))=0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque"
                "Queue"="Transparent" }
        LOD 100
        GrabPass
        {
            "_BackTexture"
        }
        Cull off
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            static const float2 center = float2(0.5,0.5);
            static const float PI = 3.14159265f;

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
                float4 screenPos : TEXCOORD1;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            sampler2D _BackTexture;
            float _Power;
            float _Period;
            float _Speed;
            float _Detail;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                o.screenPos = ComputeGrabScreenPos(o.vertex);
                return o;
            }

            half2 ReturnUV(half2 uv,half2 screenUV)
            {
                //中心座標から現在処理中のuv座標へのベクトル
                float2 c2n = uv - center;
                //c2nの長さ
                float length_of_c2n = sqrt(c2n.x*c2n.x + c2n.y*c2n.y);
                //c2nと平行な単位ベクトル
                float c2n_unit = c2n / length_of_c2n;

                //波
                float nami = (sin(((length_of_c2n * 10 *_Period - _Time*_Speed)%(2*PI))/(length_of_c2n*_Detail))/100 * _Power) * (0.2 - length_of_c2n);

                if(length_of_c2n < 0.2){
                screenUV += c2n_unit * nami;
                screenUV += c2n_unit * nami;
                }
                return screenUV;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                half2 grabUV = i.screenPos.xy / i.screenPos.w;
                // sample the texture
                half2 mainUV = ReturnUV(i.uv,grabUV);
                fixed4 col = tex2D(_BackTexture, mainUV);
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}

Unity의 UnlitShader를 기반으로 만들고 있습니다.
초보자이므로 지우고 좋은 것을 모르기 때문에 낭비가 많습니다.

하는 일은
중심의 UV 좌표(0.5,0.5)에서
처리중인 점의 UV 좌표
벡터를 사용하여 계산하고,
그것을 사용하여 화면의 UV 좌표에 영향을
GrabPass 텍스처를 파도처럼 표시합니다.

파의 상태를 변화시키기 위해
실수 속성을 몇 개 만들었습니다.
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Power ("Power",Range(0,100)) = 0
        _Period("Period",Range(0,100))=0
        _Speed("Speed",Range(0,1000))=0
        _Detail("Detail",Range(0,100))=0
    }

처리중의 점의 UV 좌표와 스크린의 UV 좌표를 인수에 있어서,
tex2D용 UV를 반환하는 함수입니다.

주로 nami 변수가 작동합니다.
UV 좌표의 어긋남 정도를,
중심에서 처리중인 점까지의 벡터와 평행 한 단위 벡터
에 걸어 파도로 합니다.

또한, 중심으로부터의 거리가 0.2 미만인 경우에만 파로 하여,
중심으로부터의 거리가 0.2 이상이면 파도가 아닌
1 다각형에서도 원이 되도록 합니다.
            half2 ReturnUV(half2 uv,half2 screenUV)
            {
                //中心座標から現在処理中のuv座標へのベクトル
                float2 c2n = uv - center;
                //c2nの長さ
                float length_of_c2n = sqrt(c2n.x*c2n.x + c2n.y*c2n.y);
                //c2nと平行な単位ベクトル
                float c2n_unit = c2n / length_of_c2n;

                //波
                float nami = (sin(((length_of_c2n * 10 *_Period - _Time*_Speed)%(2*PI))/(length_of_c2n*_Detail))/100 * _Power) * (0.2 - length_of_c2n);

                if(length_of_c2n < 0.2){
                screenUV += c2n_unit * nami;
                screenUV += c2n_unit * nami;
                }
                return screenUV;
            }

우선 기능은 합니다만,
더 코드는 깨끗하게 할 수 있습니다.

좋은 웹페이지 즐겨찾기