リブラ

グラフィックスプログラミングの勉強や制作の進捗がメイン

【Unity】蝶が羽ばたくエフェクトを作ってみる

www.klab.com
Klab株式会社様が運営されているサイトの
www.klab.com
こちらで紹介されている蝶シェーダーを勉強を兼ねて真似してみました。

meshを用意

元の記事では6頂点の板ポリを使用したましたが、今回はテクスチャを貼り付けないので5頂点で行います。
f:id:printf_Kei:20211227155751p:plain
Blender等で出力しても良いのですが、スクリプトで生成することにします。

var mesh = new Mesh();
        //meshの頂点
        var vertex = new Vector3[]{
            new Vector3(-0.1f,0.0f,-0.1f),//左下
            new Vector3(0.1f,0.0f,-0.1f),//右下
            new Vector3(0.0f,0.0f,0.0f), //中央
            new Vector3(-0.1f,0.0f,0.1f),//左上
            new Vector3(0.1f,0.0f,0.1f),//右上
        };
        //meshの三角形を定義
        var triangles = new int[]{
            0,3,2,
            2,4,1
        };
        mesh.SetVertices(vertex);
        mesh.SetTriangles(triangles, 0);
        //Assetとして出力
        AssetDatabase.CreateAsset(mesh, "Assets/ButterflyMesh.asset");

これを適当なスクリプトのStart関数に記載し実行すればAssetにmeshが出力されます。

頂点シェーダーで羽ばたかせる

f:id:printf_Kei:20211227162227p:plain
rotate関数の中身が記載されていなかったのですが、z軸で回転させる回転行列を生成してるだけだと思います。

half2x2 rotate(half theta) {
                    half angleCos = cos(theta);
                    half angleSin = sin(theta);
                    return half2x2(angleCos, -angleSin, angleSin, angleCos);
                }

f:id:printf_Kei:20211227171650g:plain

パーティクルシステムに適用

f:id:printf_Kei:20211227210255p:plain
ParticleSystemのCustomVertexStreamsを使用して、各パーティクルの中心座標をshaderに送ります。
Custom1.xyはダミーとして入れています。
f:id:printf_Kei:20211227230148p:plain
上の画像のようにCustomVertexSystemはTEXCOORDの使用されていないxyzwから順番に埋めていってしまうので、ダミーを用意し扱い易くしています。
shder側はこのようにして値を受け取ります

struct appdata
            {
                float4 vertex : POSITION;
                float4 uv : TEXCOORD0;   //ダミー受け取り用にfloat4を使用
                float4 color : COLOR;
                float4 center:TEXCOORD1;
            };

元記事にもある通りダイナミックパッチングによるメッシュの結合に対応するために中心座標を受け取って計算しています。
f:id:printf_Kei:20211227232835p:plain

               float3 center = v.center;
               float3 local = v.vertex-center;
               half flap = _FlapIntensity * sin(_Time.y * _FlapSpeed);
               local.xy = mul(rotate(flap * sign(local.x)), local.xy);
               o.vertex = UnityObjectToClipPos(center+local);

これで蝶の仕組みはできたので色々アレンジできそうです。
今回はパーティクルから色を受け取りそれを反映するところで終わりました。

完成
f:id:printf_Kei:20211227154614g:plain
完成図