yu00’s blog

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

Unity FragmentShader 図形に色を付ける

Unity Shader Lab入門

UnityのFragment Shaderで
図形に色を付ける方法を説明します。

色を付けるにはlerp関数を使います。
引数には黒に対応する色と、白に対応する色と、白黒の図形を渡します。

Properties
{
    _Color1 ("Color1", Color) = (1,1,1,1) // 黒の色
    _Color2 ("Color2", Color) = (1,1,1,1) // 白の色
}
...
fixed4 frag (v2f i) : SV_Target
{
    float mask;
    Ellipse(i.uv, 1, 1, mask); // 白黒の図形を描画
    return lerp(_Color1, _Color2, mask);
}

バージョン

  • Unity : 2022.3.22f1

Unity FragmentShader 図形を合成する

Unity Shader Lab入門

UnityのFragment Shaderで
図形を合成する方法を説明します。

以下が基本Shaderとし、このシェーダを改変していきます。

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

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            void Ellipse(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 col1;
                float col2;
                Ellipse(i.uv * 2 - 0.5 + float2(-0.3, 0), 1, 1, col1);
                Ellipse(i.uv * 2 - 0.5 + float2( 0.3, 0), 1, 1, col2);
                return col1; // ここに改変コードを追加
            }
            ENDCG
        }
    }
}

反転

return 1 - col1;

結合

return saturate(col1 + col2);

差分

return saturate(col1 - col2);

交差

return 1 - saturate((1 - col1) + (1 - col2));

排他

float intersect = 1 - saturate((1 - col1) + (1 - col2));
float _union = saturate(col1 + col2);
return saturate(_union - intersect);

バージョン

  • Unity : 2022.3.22f1

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.

Unity FragmentShaderの基本

Unity Shader Lab入門

Fragmentシェーダの基本を説明します。

frag関数

Fragmentシェーダはfrag関数に処理を記述します。

fixed4 frag (v2f i) : SV_Target
{
    // ここに処理を記述
    return col;
}

frag関数は各ピクセルに描画する色を決定する関数です。
ピクセル毎にfrag関数が実行されるイメージです。
引数のv2fに各ピクセルのUV座標の情報が渡されます。
ここでは単色を付ける例を紹介します。

単色を付ける

プロパティで指定した色を付けます。

Properties
{
    _Color ("Color", Color) = (1,1,1,1)
}
...
float4 _Color;
fixed4 frag (v2f i) : SV_Target
{
    return _Color;
}

UVとは

UVとはオブジェクトの展開図のようなものです。

UnityではUV座標はxとyがあり、それぞれ0から1までの座標になります。

開発の流れ

Fragment Shaderの開発の流れは基本的に以下のようになります。

  1. 基本図形の描画
    • 丸や四角などの基本的な図形を描画します
    • この段階では白黒で描画します
  2. 基本図形の合成
    • 基本図形を複数合成して複雑な図形を描画します
  3. 色を付ける
    • できた図形に色を付けます
  4. 組み合わせる
    • 1から3を繰り返して複雑な図形を描画します

バージョン

  • Unity : 2022.3.22f1

Unity Shaderプロパティをインスペクタから設定する

Unity Shader Lab入門

Unity ShaderLabでShaderのプロパティ(パラメータ)をインスペクタから設定
できるようにします。今回はInteger型のプロパティを追加します。

手順

まずはShaderのProperties欄に設定したいプロパティを記述します。

Properties
{
    _MyParameter ("MyParameter", Integer) = 0
}

構文は以下です。
「プロパティ名」 ("「表示名」", 「型」) = 「初期値」
プロパティ名はアンダースコアで始まるのが一般的です。

次にCGPROGRAM\~ENDCGの間にプロパティの宣言を記述します。

CGPROGRAM
...
int _MyParameter;
...
ENDCG

マテリアルのインスペクタを確認すると、
追加したプロパティが設定できるようになっています。

コード全文

Shader "Unlit/Property"
{
    Properties
    {
        _MyParameter ("MyParameter", Integer) = 0
    }
    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;
            };

            int _MyParameter;

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

            fixed4 frag (v2f i) : SV_Target
            {
                return fixed4(0, 0, 0, 0);
            }
            ENDCG
        }
    }
}

リンク

バージョン

  • Unity : 2022.3.22f1

Unity ShaderLabとは

Unity Shader Lab入門

ShaderLabとは

ShaderLabとは動くグラフィックを作成できるプログラムです。
動く図形を描いたり陰影を変えたりできます。

Shaderの種類

Standard Surface Shader

陰影処理を書かなくても陰影を生成してくれるシェーダです。

Unlit Shader

陰影処理は自前で書かないといけないが、
自由に記述できるシェーダです。
陰影が必要ない場合もこちらを使用します。

Vertex Shader

モデルの頂点の座標をスクリーン座標に変換するプログラムです。

Fragment Shader

各ドットに描画する色を決定するプログラムです。

Compute Shader

C#で記述するGPUを使うシェーダです。

Image Effect Shader

ポストエフェクトのためのシェーダです。

初めてのShader作成

Unlit Shaderを作成し適用する方法を説明します。

  • Create>Shader>Unlit Shader でShaderを作成
    • ここではNewUnlitShaderという名前で作成
  • Create>Material で適用するMaterialを作成
  • GameObject>3D Object>Quad で適用するオブジェクトを作成
  • MaterialのインスペクタからでNewUnlitShaderを選択
  • Quad>Mesh Renderer>Materialsに作成したMaterialを適用

Unity ShaderLab入門

Unity ShaderLabの使い方を説明していきます.

注意

  • C#などプログラミングの基礎が理解できている前提です
  • 詳細な説明は省いてできる限り簡素になるようにしているため、必要に応じて別サイトなどをご覧ください
  • 情報,プログラムには細心の注意を払っていますが,独学のためそれらの正確性は保証できません.間違いがありましたら指摘してくださるとありがたいです

リンク・参考資料

(以下作成中です)

ShaderLabの基本

Fragment Shader

Vertex Shader

Shader共通事項

  • C#からパラメータを設定する
  • 関数を定義する

プログラミング