yu00’s blog

プログラミングに関する備忘録です

Unity FragmentShader基本図形を描く

Unity Shader Lab入門

UnityのFragment Shaderで丸や四角など
基本図形を描く方法を説明します。

図形の調べ方

基本的に2つの調べ方があります

  • Unity Shader Graphで図形を検索してShaderLabで記述したコードを使う
  • 数式で図形を描く方法を検索してShaderLabに変換する

Unity Shader Graphで検索

Shader Graphには丸ならEllipse、四角ならRectangleといった
基本図形のノードが存在します。そして公式マニュアルには
「生成されるコードの例」の項があり、ShaderLabにそのままコピーして
使うことができます。

以下は円の例です。

Rectangle ノード | Shader Graph | 10.0.0-preview.27
を見るとShaderLabのコードが載っているのでそのままコピーして、
「CGPROGRAM」から「ENDCG」の間にペーストします。
次に、出力「Out」が色指定の「float4」になっているため、
単色(白黒)の「float」に変えます。

CGPROGRAM
...
void Unity_Ellipse_float(float2 UV, float Width, float Height, out float Out)
{
    float d = length((UV * 2 - 1) / float2(Width, Height));
    Out = saturate((1 - d) / fwidth(d));
}
...
ENDCG

次にfragで円を描画します。floatの出力colorを定義して、
Unity_Ellipse_floatのOutに渡します。

fixed4 frag (v2f i) : SV_Target
{
    float color;
    Unity_Ellipse_float(i.uv, 1, 1, color);
    return color;
}

コード全文です。

Shader "Unlit/Fragment_Color"
{
    Properties
    {
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            void Unity_Ellipse_float(float2 UV, float Width, float Height, out float Out)
            {
                float d = length((UV * 2 - 1) / float2(Width, Height));
                Out = saturate((1 - d) / fwidth(d));
            }

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

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

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

            fixed4 frag (v2f i) : SV_Target
            {
                float color;
                Unity_Ellipse_float(i.uv, 1, 1, color);
                return color;
            }
            ENDCG
        }
    }
}

数式で図形を描く

基本的に極座標になっていれば簡単に描画できます。
花びらを描く例で説明します。
まず、「花びら 数式 描画」などでネット検索すると以下のような数式が出てきます。

花の曲線を描く

この式をShaderで記述します。

void Flower(float2 UV, int n, int k, out float Out)
{
    UV = UV * 2 - 1; // 中心をそろえる
    float theta = atan2(UV.x, UV.y);
    float r = length(UV);
    float r1 = sin(n*theta/k);
    Out = step(r, r1);
}
...
fixed4 frag (v2f i) : SV_Target
{
    float color;
    Flower(i.uv, _n, _k, color);
    return color;
}

step関数を使いr1の範囲内かどうかで塗り分けをしています。

バージョン

  • Unity : 2022.3.22f1


Powered by MathJax

This page is based on MathJax technology.