Shader, VRChat, 備忘録

Shaderを理解したい。書き方編

ChatGPTから出力したWireFrameShaderをもとにShaderの基礎を学習する試みです。

Shader "Practice/Wireframe_Min"
{
    Properties
    {
        _WireColor ("Wire Color", Color) = (0, 1, 1, 1)
        _BaseColor ("Base Color", Color) = (0, 0, 0, 1)
        _WireWidth ("Wire Width", Range(0.001, 0.1)) = 0.02
    }

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

        Pass
        {
            CGPROGRAM

            #pragma target 4.0
            #pragma vertex vert
            #pragma geometry geom
            #pragma fragment frag

            #include "UnityCG.cginc"

            float4 _WireColor;
            float4 _BaseColor;
            float _WireWidth;

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2g
            {
                float4 pos : SV_POSITION;
            };

            struct g2f
            {
                float4 pos : SV_POSITION;
                float3 bary : TEXCOORD0;
            };

            v2g vert(appdata v)
            {
                v2g o;
                o.pos = UnityObjectToClipPos(v.vertex);
                return o;
            }

            [maxvertexcount(3)]
            void geom(triangle v2g input[3], inout TriangleStream<g2f> stream)
            {
                g2f o;

                o.pos = input[0].pos;
                o.bary = float3(1, 0, 0);
                stream.Append(o);

                o.pos = input[1].pos;
                o.bary = float3(0, 1, 0);
                stream.Append(o);

                o.pos = input[2].pos;
                o.bary = float3(0, 0, 1);
                stream.Append(o);
            }

            fixed4 frag(g2f i) : SV_Target
            {
                float edge = min(min(i.bary.x, i.bary.y), i.bary.z);

                float wire = smoothstep(_WireWidth, _WireWidth * 0.5, edge);

                float3 color = lerp(_BaseColor.rgb, _WireColor.rgb, wire);

                return fixed4(color, 1);
            }

            ENDCG
        }
    }
}
ブロックについて

・Shader 一番外側のブロックでシェーダーを定義する ・Properties Material Inspectorに表示する項目 ・SubShader 実際の描画方法を書く 複数のSubShaderブロックを書けるが基本的に一つで問題ない ・FallBack 対応できない環境だった場合に代わりに使用するShader 例1:FallBack "Diffuse" (このシェーダーが使えない場合は、Unity標準のDiffuseシェーダーを使う) 例2:FallBack Off (設定不要) ・CustomEditor Inspectorの表示を独自に作るときに使う。 ・Dependency 別のシェーダーへの依存関係を書く ・Category SubShaderの古い書き方?

Shader "Practice/Wireframe_Min"

Unity上でマテリアルから選ぶときに表示されるシェーダー名 ファイル名とは関係ないが同じ名前のがほうがわかりやすい。

Properties { _WireColor ("Wire Color", Color) = (0, 1, 1, 1) _BaseColor ("Base Color", Color) = (0, 0, 0, 1) _WireWidth ("Wire Width", Range(0.001, 0.1)) = 0.02 }

MaterialのInspectorに表示する内容 大体4つに分けられる。 ・WireColor: 内部で扱う変数名を記載(宣言はしていない) ・"Wire Color": UnityのInspectorに表示される名前 ・Color: Color型として表示する ・(0, 1, 1, 1): 初期値

SubShader

マテリアルをどう描画するかを設定する箇所

SubShaderの代表的な要素

・Tags Unityに描画分類を伝える ・LOD シェーダーの詳細度 ・Cull 裏面を描くかどうか ・ZWrite 深度を書き込むか ・ZTest 奥行判定 ・Blend 透明・加算合成 ・Pass 一回分の描画処理

Passの中にも要素がある
CGPROGRAM

#pragma target 4.0
#pragma vertex vert
#pragma geometry geom
#pragma fragment frag

#include "UnityCG.cginc"

ENDCG

・CGPROGRAM HLSL/CGコード開始 ・ENDCG HLSL/CGコード終了 ・#pragma vertex vert vertを頂点シェーダーとして使う ・#pragma geometry geom geomをジオメトリシェーダーとして使う ・#pragma fragment frag fragをピクセル処理ととして使う ・#include Unityの便利変数を読み込む

https://rin0700.com/blog/8c441c12-f232-4d5b-8c7e-d0d413e23076