T.TAO
Back to Blog
/4 min read/Others

Unity Shader #0 基礎

Unity Shader #0 基礎

Unity Shader #0 基礎

このノートでは、Unityで作成するシェーダーのコード基礎について説明します。

Assetウィンドウで右クリック > Shader > Unlit Shaderで、新しいシェーダーファイルを作成できます。

Jetbrains Riderでダブルクリックしてこのシェーダーを開きます(Visual Studioはシェーダーに合わせた自動改行がデフォルトでないため非推奨)。

以下の基本フレームワークがシェーダーコードの最も基本的なテンプレートです。

Plain TextShader "Name"
{
    Properties
    {
    
    }
    
    SubShader 
    {
        Pass{
        
        }
    }
}

Property プロパティ

Properties部分で、コメント内のテンプレートに従って新しいプロパティを宣言できます。このプロパティはシェーダーがアタッチされたマテリアルのマテリアルパネルに表示され、Inspectorから変更できます。

Plain TextProperties
{
    // 変数名 + (Inspectorに表示する名前) + , + 型 + = + デフォルト値
    
    // Float
    _VariableName("Shown Name", Float) = 0.0
    
    // Int
    _SomeProperty("Some Property", Int) = 2
    
    // Range(min, max)
    _Range("Range", Range(0.0, 1.0)) = 0.0
    
    // Vector
    _Vector("Vector", Vector) = (1,1,1,1) 
    
    // Color
    _Color("Color", Color) = (0.5,0.5,0.5,0.5)
    
    // 2D
    _Texture("Texture", 2D) = "white" {}
    
    // 3D
    _Model("Model", 3D) = "black"{}
    
    // Cube
    _Cube("Cube", Cube) = "white"{}
}

SubShader

実際のシェーディング方法のコードはSubShaderに書きます。以下は典型的なSubShaderテンプレートです。

Plain TextSubShader
{
    // オプション
    Tags {}
    
    // オプション
    // [Render Setup]
    
    // SubShader内に複数のPass{}を記述可能
    Pass
    {
        // CGPROGRAM - ENDCG内でコードを実装
        CGPROGRAM
        // #pragma vertexでvertという名前の頂点シェーダーを定義
        #pragma vertex vert
         
        // #pragma fragmentでfragという名前のフラグメントシェーダーを定義
        #pragma fragment frag
        
        // ヘッダーファイルをインクルード
        #include "UnityCG.cginc"
        
        ENDCG
    }
}

TagとRender Setupの詳細はUnity Shader#2.1を参照してください。

Passブロック

レンダリングパイプラインを振り返ります。

SubShader全体はGPUの2つの部分、つまりジオメトリ段階とラスタライゼーション段階に対応します。Passが実際の操作を定義します。

Unityでは、頂点・フラグメントシェーダーの使命に合う最も基本的なシェーダーには以下の特性が必要です:

  1. 頂点シェーダーはfloat4を返し、モデル空間座標をクリップ空間座標に変換する
  2. フラグメントシェーダーはfloat4を返し、そのフラグメントの色を出力する

最もシンプルな頂点・フラグメントシェーダーは以下のように書けます:

Plain TextSubShader {
    Pass {
        CGPROGRAM
        
        // 頂点シェーダーvertとフラグメントシェーダーfragを定義
        #pragma vertex vert
        #pragma fragment frag
        
        // 頂点シェーダーvertは座標値を返すのでfloat4
        // 頂点シェーダーの入力はモデル座標、POSITIONはモデル空間の頂点位置(Unity定義の特殊意味)
        // SV_POSITIONはクリップ空間の頂点位置
        float4 vert(float4 v: POSITION) : SV_POSITION {
            return mul(UNITY_MATRIX_MVP, v);
        }
        
        // フラグメントシェーダーfragは色値を返すのでfloat4
        // フラグメントシェーダーは頂点から情報を取得する必要はなく、このフラグメントがこのピクセルに表示する色を定義すればよい
        float4 frag() : SV_Target {
            return fixed4(1,1,1,1);
        }
        
        ENDCG
    }
}

頂点シェーダー Vertex Shader

入力:頂点シェーダーが受け取るデータには通常、モデル空間の頂点位置、法線情報、テクスチャ座標などが含まれます。これらのデータは通常appdataデータ構造から来ます。このデータ構造はカスタムで必要な特定の情報を取得するように定義できます。