【Unity】【シェーダテクニック】テクスチャを回転させる

シェーダでテクスチャを回転させてみます。

回転させる

まずは普通に回転させます。

Shader "Example"
{
    Properties
    {
        [NoScaleOffset] _MainTex ("Texture", 2D) = "white" {}
        _RotateSpeed ("Rotate Speed", float) = 1.0
        _Tiling ("Tiling", float) = 1.0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }

        Pass
        {
            CGPROGRAM
           #pragma vertex vert
           #pragma fragment frag
           #include "UnityCG.cginc"

           #define PI 3.141592

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

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D   _MainTex;
            float4      _MainTex_ST;
            float      _RotateSpeed;
            float      _Tiling;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex    = UnityObjectToClipPos(v.vertex);
                o.uv        = v.uv;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // Timeを入力として現在の回転角度を作る
                half angle              = frac(_Time.x) * PI * 2;
                // 回転行列を作る
                half angleCos           = cos(angle * _RotateSpeed);
                half angleSin           = sin(angle * _RotateSpeed);
                half2x2 rotateMatrix    = half2x2(angleCos, -angleSin, angleSin, angleCos);
                // タイリング処理
                i.uv                    = frac(i.uv * _Tiling);
                // 中心を起点にUVを回転させる
                i.uv                    = mul(i.uv - 0.5, rotateMatrix) + 0.5;

                fixed4 col              = tex2D(_MainTex, i.uv);
                return col;
            }
            ENDCG
        }
    }
}

コメントに書いた通りですが、まず回転行列を掛けてUVを回転させています。

結果は次のようになります。

f:id:halya_11:20181015225139g:plain

タイリングを設定するとこんな感じになります。

f:id:halya_11:20181015225300g:plain

タイリングしたセルごとに回転をずらす

次にタイリングしたセルごとに回転をずらしてみます。

Shader "Example"
{
    Properties
    {
        [NoScaleOffset] _MainTex ("Texture", 2D) = "white" {}
        _RotateSpeed ("Rotate Speed", float) = 1.0
        _Tiling ("Tiling", float) = 1.0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }

        Pass
        {
            CGPROGRAM
           #pragma vertex vert
           #pragma fragment frag
           #include "UnityCG.cginc"

           #define PI 3.141592

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

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D   _MainTex;
            float4      _MainTex_ST;
            float      _RotateSpeed;
            float      _Tiling;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex    = UnityObjectToClipPos(v.vertex);
                o.uv        = v.uv;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // セルを計算する
                int2 cell   = i.uv * _Tiling;
                // セルを回転角度の計算に依存させる
                half angle              = frac(_Time.x + (cell.x + cell.y) * 0.01) * PI * 2;
                half angleCos           = cos(angle * _RotateSpeed);
                half angleSin           = sin(angle * _RotateSpeed);
                half2x2 rotateMatrix    = half2x2(angleCos, -angleSin, angleSin, angleCos);
                i.uv                    = frac(i.uv * _Tiling);
                i.uv                    = mul(i.uv - 0.5, rotateMatrix) + 0.5;

                fixed4 col              = tex2D(_MainTex, i.uv);
                return col;
            }
            ENDCG
        }
    }
}

結果は次のようになります。

f:id:halya_11:20181015225501g:plain

角度にディストーションを適用する

さらに、回転角度にディストーションテクスチャを設定できるようにします。

Shader "Example"
{
    Properties
    {
        [NoScaleOffset] _MainTex ("Texture", 2D) = "white" {}
        [NoScaleOffset] _DistTex ("Distortion Texture", 2D) = "white" {}
        _RotateSpeed ("Rotate Speed", float) = 1.0
        _Tiling ("Tiling", float) = 1.0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }

        Pass
        {
            CGPROGRAM
           #pragma vertex vert
           #pragma fragment frag
           #include "UnityCG.cginc"

           #define PI 3.141592

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

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float2 uv2 : TEXCOORD1;
                float4 vertex : SV_POSITION;
            };
            
            sampler2D   _MainTex;
            float4      _MainTex_ST;
            sampler2D   _DistTex;
            float4      _DistTex_ST;
            float      _RotateSpeed;
            float      _Tiling;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex    = UnityObjectToClipPos(v.vertex);
                o.uv        = v.uv;
                o.uv2       = TRANSFORM_TEX(v.uv, _DistTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // Distortionの値をangleに反映する 
                half dist               = tex2D(_DistTex, i.uv2).r;
                half angle              = (frac(_Time.x) + dist) * PI * 2;
                half angleCos           = cos(angle * _RotateSpeed);
                half angleSin           = sin(angle * _RotateSpeed);
                half2x2 rotateMatrix    = half2x2(angleCos, -angleSin, angleSin, angleCos);
                i.uv                    = frac(i.uv * _Tiling);
                i.uv                    = mul(i.uv - 0.5, rotateMatrix) + 0.5;

                fixed4 col              = tex2D(_MainTex, i.uv);
                return col;
            }
            ENDCG
        }
    }
}

試しにパーリンノイズテクスチャを適用すると結果はこんな感じになりました。

f:id:halya_11:20181015230426g:plain