知識0からのUnityShader勉強

知識0からのUnityShader勉強

UnityのShaderをメインとして、0から学んでいくブログです。

【UnityShader】図形の移動 #58

前回の成果

図形を描画した。

soramamenatan.hatenablog.com


今回やること

前回制作した図形を活かして移動処理を行っていこうと思います。

karanokan.info


ソースコード

Shader "Unlit/MoveFigure" {
    Properties {
        _MainTex ("Texture", 2D) = "white" {}
    }
    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;
            float4 _MainTex_ST;

            float square(float2 uv, float2 r) {
                return max(abs(uv.x) - r.x, abs(uv.y) - r.y);
            }

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

            fixed4 frag (v2f i) : SV_Target {
                float2 uv = frac(i.uv) * 2 - 1;
                float2 pos = (0, 0);
                uv += pos;
                float rect = square(uv, float2(-0.38, -0.38));
                fixed4 col = smoothstep(0.5, 0.51, rect);
                return col;
            }
            ENDCG
        }
    }
}

前回制作した四角形を描画するsquare関数を使用しています。


図形を移動させる

まずは図形を移動させてみます。
上記のソースコードのposの値を変化させることにより位置を変更することが出来ます。

posが0.8の場合

f:id:soramamenatan:20200621134655p:plain

posが-0.8の場合

f:id:soramamenatan:20200621134652p:plain

更にこれをサインカーブを使用し、(-1~1)の間に収めることによって往復することが出来ます。

ソースコード
fixed4 frag (v2f i) : SV_Target {
    float2 uv = frac(i.uv) * 2 - 1;
    float2 pos = sin(_Time.y);
    uv += pos;
    float rect = square(uv, float2(-0.38, -0.38));
    fixed4 col = smoothstep(0.5, 0.51, rect);
    return col;
}
結果

f:id:soramamenatan:20200621135028g:plain


図形の回転

次に図形を回転させます。
図形の回転行例は以下となります。

回転行列の公式  \displaystyle
R(\theta) = \begin{pmatrix} cos\theta&-sin\theta \\ sin\theta&cos\theta \end{pmatrix}

この行列にUV値を乗算することによって回転後の座標が取れます。
なぜ回転後の座標が取れるかは以下を参照してください。

soramamenatan.hatenablog.com

ソースコード
float2 rotation(float2 uv, float theta){
    half2x2 rotate = half2x2(cos(theta), -sin(theta), sin(theta), cos(theta));
    return mul(rotate, uv);
}

fixed4 frag (v2f i) : SV_Target {
    float2 uv = frac(i.uv) * 2 - 1;
    float theta = _Time.y * 5;
    uv = rotation(uv, theta);
    float rect = square(uv, float2(-0.38, -0.38));
    fixed4 col = smoothstep(0.5, 0.51, rect);
    return col;
}
結果

f:id:soramamenatan:20200621140701g:plain

原点を中心に回転

次に原点を中心に回転させます。
三角関数より角度と半径を利用して座標を求めます。

座標を求める  \displaystyle
x = rcos\theta \\
y = rsin\theta

f:id:soramamenatan:20200621143644p:plain

三角関数で角度から座標を導くふたつの式の使い途 - Qiita:より引用

ソースコード
// 原点を中心に回転
fixed4 frag (v2f i) : SV_Target {
    float2 uv = frac(i.uv) * 2 - 1;
    float2 radius = float2(0.4, 0.4);
    uv += float2(radius.x * cos(_Time.y * 2), radius.y * sin(_Time.y * 2));
    float rect = square(uv, float2(-0.38, -0.38));
    fixed4 col = smoothstep(0.5, 0.51, rect);
    return col;
}
結果

f:id:soramamenatan:20200621144316g:plain

余談ですが、原点を中心に回転しながら自身を回転させることもできます。

ソースコード
fixed4 frag (v2f i) : SV_Target {
    float2 uv = frac(i.uv) * 2 - 1;
    float theta = _Time.y * 2;
    uv = rotation(uv + rotation(0.5, theta), theta);
    float rect = square(uv, float2(-0.38, -0.38));
    fixed4 col = smoothstep(0.5, 0.51, rect);
    return col;
}
結果

f:id:soramamenatan:20200621145247g:plain


モーフィング

最後にモーフィングを行います。

コンピューター━グラフィックスで、ある物体が別の物体に変形してゆくさまを表す一連の効果・手法。

モーフィングとは何? Weblio辞書:より引用

2つの図形を用意し、それを線形補間することによって実装します。

ソースコード
float circle(float2 uv, float r) {
    return length(uv) - r;
}

fixed4 frag (v2f i) : SV_Target {
    float2 uv = frac(i.uv) * 2 - 1;
    float ci = circle(uv, 0);
    float rect = square(uv, 0);
    float time = (sin(_Time.y * 1.5) + 1) * 0.5;
    float morph = lerp(ci, rect, time);
    fixed4 col = smoothstep(0.5, 0.51, morph);
    return col;
}
(sin(_Time.y * 1.5) + 1) * 0.5のグラフ

f:id:soramamenatan:20200621145945p:plain

結果

f:id:soramamenatan:20200621150132g:plain

今回は以上となります。
ここまでご視聴ありがとうございました。