【Unity】Shader vs Shader Graph~どっちがいいの?~

Post : 2023/9/24 Update : 2023/9/24

おそらくここに来た人はShaderとShader Graphのどちらでよりビジュアライズなコンテンツを作るか迷っている方かと思います。

ということで以下の3つの項目で比較していきたいと思います。

1.学習コスト

2.可読性

2. パフォーマンス

3.将来性

学習コスト

これはShader Graphの方が入門しやすいです!

よくやる手法一つにUV座標をスクロールさせたい時があります。

ShaderとShader Graphで同様の処理をしたUnityの画面

Shaderで実現するためには下のようなシェーダーになります。


Shader "Unlit/ScrollY" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
    }

    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass {
            CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma target 2.0
                #pragma multi_compile_fog

                #include "UnityCG.cginc"

                struct appdata_t {
                    float4 vertex : POSITION;
                    float2 texcoord : TEXCOORD0;
                    UNITY_VERTEX_INPUT_INSTANCE_ID
                };

                struct v2f {
                    float4 vertex : SV_POSITION;
                    float2 texcoord : TEXCOORD0;
                    UNITY_FOG_COORDS(1)
                    UNITY_VERTEX_OUTPUT_STEREO
                };

                sampler2D _MainTex;
                float4 _MainTex_ST;

                v2f vert (appdata_t v)
                {
                    v2f o;
                    UNITY_SETUP_INSTANCE_ID(v);
                    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
                    UNITY_TRANSFER_FOG(o,o.vertex);
                    return o;
                }

                fixed4 frag(v2f i) : SV_Target
                {
                    float2 uv = i.texcoord;
                    uv.y -= _Time.y;
                
                    fixed4 col = tex2D(_MainTex, uv);
                    UNITY_APPLY_FOG(i.fogCoord, col);
                    UNITY_OPAQUE_ALPHA(col.a);
                    return col;
                }
            ENDCG
        }
    }
}
対してShader Graphではこんな感じ
Shader GraphでUVをスクロールさせるときに追加した部分

実際ShaderはUnity標準のUnlitを3行ほど追記、変更してませんが全体の量をShader Graphはすっきりとしています。

またデバッグする際も標準ではShaderのブレイクポイントには対応していませんが、Shader GraphではNodeにプレビュー機能がついているのでどこで間違っているのかも分かりやすいです。

また、Shader Graphのリリースからかなり経過していることもありGoogleで調べると日本語、英語問わずかなりヒットするので、入門はかなりし易くなっています。

経験則だと、私がUnityを触りだした時にはまだShader Graphはまだリリースされておらず、vertex? fragment? shader?ぐらいの状態から試行錯誤で覚えてきました。仕事で使い物なる状態になるまで1日3時間*1か月 = 90時間程度かかったような気がします。

対してShader Graphは10日程度で手応えがあった気がします。

2. 可読性

こちらは引き分けです。Shaderのメリットはコードなので全体の処理が上から下に流れている初見でも内容が掴みやすいです。

ShaderでUVをスクロールさせるときに処理の流れの説明

対してShader Graphは書き方に結構依存している気がします。適宜グループ化したり左から右へノードを繋げる(慣習的なものがありそう)などのルールを決めておくことで、ノードベースの処理の流れの読みにくさは回避することはできます。

Shader GraphでUVをスクロールさせるときに処理の流れの説明

3.パフォーマンス

こちらは僅かにShader側に軍配が上がります。

Shader Graphではどうしても変換がかかるためShaderにくらべて最適化しにくい部分があります。

しかしShader GraphにHLSLを直接書くノードがある為最適化ができますし、実際にShader Graphを使っていたことがパフォーマンス的にボトルネックになったことは今のところありません。

4. 将来性

将来性については引き分けです。

Shader Graphのようノードベースでマテリアルやエフェクトを作成するノウハウはUnrealやMaya、Blenderなどの他のツールへの展開が期待できます。

Unityだけに関してはHDRPやURPに対応する際もShader Graphをそのまま(少し変更するだけ)で動きますし効率化も期待できます。

対してShaderはWebGL(OpenGL)やQt(OpenGL)などでごりごりシェーダー書く時にかなり重宝します。

実際に私も別のオーサリングツールでシェーダー(OpenGL)を書く時がありましたがかなり役に立ちました。

5.まとめ

ShaderとShader Graphについてまとめてみました。

私自身仕事ではどっちも使いますが、最近はスピード重視でShader Graphの方が使う場面が多いです。

しかしノイズをごにょごにょする時などはShader Graphでは大変だなーって思ったときは、シェーダーを書いたりもしています。

Shader初心者の方はShader Graph → Shaderの順で学習していった方が、Shaderどう描画しているのかがつかみやすいのかなと思います。