📖

Unityシェーダー超入門④UVで画像を回転させる

2023/04/10に公開

今回はUVを使って画像を回転させます

今回はちょっと時間がなかったので少し短いです
この三角形を回転させるシェーダーをやっていこうと思います。
画像は私が作成したものですので、今回やっていくコーディングを
実践する上で使う場合であればダウンロードを許可致します。

ではやっていきましょう。
コードは以下のようになっています。

02_UV_Rotation
Shader "Custom/02_UV_Rotation"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _RotationSpeed("Rotation Speed", Range(0, 10)) = 10
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

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

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

            sampler2D _MainTex;
            float _RotationSpeed;

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

            fixed4 frag (v2f i) : SV_Target
            {
                half angleCos = cos(_Time * _RotationSpeed);
                half angleSin = sin(_Time * _RotationSpeed);
                half2x2 rotateMatrix = half2x2(angleCos, -angleSin, angleSin, angleCos);
                half2 uv = i.uv - 0.5;

                i.uv = mul(uv, rotateMatrix) + 0.5;

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

実態としては、下記のコードで回転をさせています。
そう、正確に言うと画像を回転させているのではなくてUVを回転させています。

02_UV_Rotation
            fixed4 frag (v2f i) : SV_Target
            {
                half angleCos = cos(_Time * _RotationSpeed);
                half angleSin = sin(_Time * _RotationSpeed);
                half2x2 rotateMatrix = half2x2(angleCos, -angleSin, angleSin, angleCos);
                half2 uv = i.uv - 0.5;

                i.uv = mul(uv, rotateMatrix) + 0.5;

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

2次元回転行列

ここの記述で回転をさせています。
この際使われているのが、2次元の回転行列とのことです。
https://w3e.kanazawa-it.ac.jp/math/category/gyouretu/senkeidaisu/henkan-tex.cgi?target=/math/category/gyouretu/senkeidaisu/rotation_matrix.html
half angleCos = cos(_Time * _RotationSpeed);
half angleSin = sin(_Time * _RotationSpeed);
half2x2 rotateMatrix = half2x2(angleCos, -angleSin, angleSin, angleCos);
申し訳ないことに、まだ自分が数学の復習をしているのでまだしっかりと理屈が説明出来るレベルじゃありません…。でも、わかることはリンク先の数式に当てはめた数式をコーディングで行うということです。

_Timeとは

Unity内で定義されている値の一つです。
経過時間の値を持っています。
その経過時間=角度として値を入れて、早さとして_RotationSpeedを掛けると回転する速度が上がるということです。
また、回転の軸となる点もしっかりと指定しなければいけません。
何も手を加えなければUV座標の原点は0,0となり、左下を軸に回転をしてしまいます。
中心に回転を加えたいので、0.5ずらせばいい…と思ったら、-0.5になります。
angleSinが負の値で原点から距離が離れていくためと思われます。
その後、 i.uv = mul(uv, rotateMatrix) + 0.5;で0.5を足して戻す。
これで画像の中心軸で回転がされるということです。

今回はちょっと短めですがこの辺で!
また次回!

Discussion