Unityでスーパー楕円を表示する

2 min read読了の目安(約2300字

最近、スーパー楕円という図形に興味を持ったので、UnityのShaderで表現できないか試してみました。スーパー楕円に関しては、以下のサイトで詳しく解説されています。

https://spinners.work/posts/kudakurage-superellipse-desgin/

https://en.wikipedia.org/wiki/Superellipse

数式で定義されているなら、Shaderで表現できるはず!
ということでShaderを書いてみました。

Shader "Custom/Superellips"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _A ("Width", Range (0.01,0.5)) = 1
        _B ("Height", Range (0.01,0.5)) = 1
        _N ("N", Range (0.2, 10)) = 2.5
        _Blur ("Blur", Range (0, 1)) = 0
    }
    SubShader
    {
        Blend SrcAlpha OneMinusSrcAlpha

        Tags {
            "Queue" = "Transparent"
            "RenderType" = "Transparent"
        }
        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;
            };

            fixed4 _Color;
            float _A;
            float _B;
            float _N;
            float _Blur;

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

            fixed4 frag (v2f i) : SV_Target
            {
                const float a = pow(abs((i.uv.x - 0.5) / _A), _N) + pow(abs((i.uv.y - 0.5) / _B), _N);

                if(a < 1)
                {
                    return _Color;
                }

                if(_Blur == 0)
                {
                    return fixed4(_Color.rgb, 0);
                }

                return fixed4(_Color.rgb, 1 / pow(a, 10 * (1 - _Blur)));
            }

            ENDCG
        }
    }
}

Quadを作成して、上記のShaderを組み込んだMaterialを割り当てると表示できます。URPで動作確認しています。ついでにぼかし処理も入れてみました。Blur値で調整できます。

nの値を変えると星のような形になるので、ビジュアルエフェクトにも使えそうですね。
なお、pow等の計算は重いので、実際のコンテンツに使う場合は、近似値を使ったりパラメータを固定するのが良さそうです。