グラフィックスチュートリアル
シェーダー: 頂点とフラグメントプログラム

シェーダー: ShaderLab と固定関数シェーダー

このチュートリアルでは、独自のシェーダーを作成するための最初のステップを学習します。ゲームの見た目を制御し、グラフィックスのパフォーマンスを最適化するためです。

Unity は強力なシェーディングとマテリアルの言語、 ShaderLab を装備しています。 形式的には、Direct3D Effects (.FX) 言語に似ていて、 マテリアル を表示するために必要なものすべてを表現します。

Shaders describe properties that are exposed in Unity’s Material Inspector and multiple shader implementations (SubShaders) targeted at different graphics hardware capabilities, each describing complete graphics hardware rendering state, and vertex/fragment programs to use. Shader programs are written in the high-level Cg/HLSL programming language.

In this tutorial we’ll describe how to write very simple shaders using so-called “fixed function” notation. In the next chapter we’ll introduce vertex and fragment shader programs. We assume that the reader has a basic understanding of OpenGL or Direct3D render states, and has some knowledge of HLSL, Cg, GLSL or Metal shader programming languages.

初めに

シェーダーを新規作成するには、メニューバーから Assets > Create > Shader > Unlit Shader を選択するか、既存のシェーダーをコピーし、そこから作業します。新しいシェーダーは、プロジェクトウィンドウ をダブルクリックすることで編集できます。

Unity では、 非常に単純な シェーダーをいわゆる「固定関数」表記で作成する方法があります。簡単に説明するために、まず、これから始めましょう。 内部では、シェーダーのインポート時に、固定関数シェーダーは標準的な頂点とフラグメントのプログラム に変換されます。

非常に基本的なシェーダーから始めましょう。

Shader "Tutorial/Basic" {
    Properties {
        _Color ("Main Color", Color) = (1,0.5,0.5,1)
    }
    SubShader {
        Pass {
            Material {
                Diffuse [_Color]
            }
            Lighting On
        }
    }
}

この簡単なシェーダーは、もっとも基本的なシェーダーの 1 つを例示します。これは Main Color という色プロパティーを定義し、これにピンク色 (赤=100% 緑=50% 青=50% アルファ=100%) のデフォルト値を割り当てます。次に Pass を呼び出してオブジェクトをレンダリングし、このパスで、デフューズマテリアルコンポーネントをプロパティー _Color に設定し、頂点ごとのライティングをオンにします。

このシェーダーをテストするには、ドロップダウンメニューからシェーダーを選択し (Tutorial->Basic)、そのマテリアルをオブジェクトに割り当てます。マテリアルインスペクターで色を微調整し、変更を確認します。次は、もっと複雑なことに挑戦しましょう。

基本的な頂点ライティング

既存の複雑なシェーダーを開く場合、よい概要を得るのは若干難しい場合があります。最初に、Unity に同胞の組み込み VertexLit シェーダーを分解してみましょう。このシェーダーは、固定関数パイプラインを使用して、標準の頂点ごとのライティングを実行します。

Shader "VertexLit" {
    Properties {
        _Color ("Main Color", Color) = (1,1,1,0.5)
        _SpecColor ("Spec Color", Color) = (1,1,1,1)
        _Emission ("Emmisive Color", Color) = (0,0,0,0)
        _Shininess ("Shininess", Range (0.01, 1)) = 0.7
        _MainTex ("Base (RGB)", 2D) = "white" { }
    }

    SubShader {
        Pass {
            Material {
                Diffuse [_Color]
                Ambient [_Color]
                Shininess [_Shininess]
                Specular [_SpecColor]
                Emission [_Emission]
            }
            Lighting On
            SeparateSpecular On
            SetTexture [_MainTex] {
                constantColor [_Color]
                Combine texture * primary DOUBLE, texture * constant
            }
        }
    }
}

すべてのシェーダーは、キーワード Shader で始まり、その後にシェーダーの名前を表す文字列が続きます。これは Inspector に表示される名前です。このシェーダーのすべてのコードは、その後の波括弧内に入れる必要があるということです。{ } (ブロックと呼ばれます)。

  • この名前は短く、説明的である必要があります。これは .shader ファイル名に一致する必要はありません。
  • Unity のサブメニューにシェーダーを置くには、スラッシュを使用します (例えば、 MyShaders/TestMyShaders または MyShaders->Test サブメニュー内で、 Test と表示されます)。

このシェーダーは、 SubShader ブロックが後にくる Properties ブロックで構成されます。これらについては各自後述します。

プロパティー

シェーダーブロックの最初で、マテリアル インスペクター でアーティストが編集できるプロパティーを定義できます。 VertexLit の例では、このプロパティーは次のように見えます。

プロパティーは、Properties ブロック内の個々の行に一覧表示されます。各プロパティーは、内部名 (ColorMainTex) で始まります。この後の括弧内には、インスペクターで表示される名前とプロパティーの型がきます。その後、このプロパティーのデフォルト値が一覧表示されます。

型のリストは、ShaderLab :プロパティー にあります。デフォルト値は、プロパティーのタイプによって決まります。色の例では、デフォルト値は、4 つの成分のベクトルになるはずです。

プロパティーを定義したので、実際のシェーダーを記述する準備ができました。

シェーダー本体

次に進む前に、シェーダーファイルの基本的な構造を定義しましょう。

グラフィックハードウェアによって、機能が異なります。例えば、グラフィックカードによって断片プログラムをサポートしているものとしていないものがあります。パスごとに 4 つのテクスチャを置くものもあれば、2 つまたは 1 つしかおかないものもあります。ユーザーの持っているハードウェアが何であろうと最大限に活用できるようにするため、シェーダーは、複数の SubShaders を含むことができます。Unity がシェーダーをレンダリングすると、すべてのサブシェーダーに展開し、ハードウェアがサポートする最初のサブシェーダーを使用します。

Shader "Structure Example" {
    Properties { /* ...shader properties... }
    SubShader {
        // ...subshader that requires fancy DX11 / GLES3.1 hardware...
    }
    SubShader {
        // ...subshader that requires DX9 SM3 / GLES3 hardware...
    }
    SubShader {
        // ...subshader that might look ugly but runs on anything :)
    }
}

このシステムにより、Unity はすべての既存のハードウェアをサポートし、それぞれでの質を最大化できます。しかし、シェーダーは多少長くなります。

各サブシェーダーブロック内で、すべてのパスが共有するレンダリング状態を設定し、レンダリングパス自体を定義します。使用できるコマンドの完全なリストは、ShaderLab :サブシェーダー にあります。

パス

各サブシェーダーは、パスの集合です。各パスに対して、オブジェクトジオメトリがレンダリングされるため、少なくとも 1 つのパスが必要です。ここでの VertexLit シェーダーは、次の 1 つのパスがあります。

// ...snip...
Pass {
    Material {
        Diffuse [_Color]
        Ambient [_Color]
        Shininess [_Shininess]
        Specular [_SpecColor]
        Emission [_Emission]
    }
    Lighting On
    SeparateSpecular On
    SetTexture [_MainTex] {
        constantColor [_Color]
        Combine texture * primary DOUBLE, texture * constant
    }
}
// ...snip...

パスで定義されたコマンドは、グラフィックハードウェアを設定し、特定の方法でジオメトリをレンダリングします。

上記の例では、 Material ブロックは、固定関数ライティングマテリアル設定にプロパティー値を結合します。コマンド Lighting On は、標準の頂点ライティングをオンにし、 SeparateSpecular On は、スペキュラハイライトに対して、個々の色の使用を有効にします。

これまでのコマンドはすべて、固定関数 OpenGL/Direct3D ハードウェアモデルに対して、直接マッピングします。詳細については、OpenGL red book を参照してください。

次のコマンド SetTexture は非常に重要です。これらのコマンドは、使用したいテクスチャと混合方法を定義し、結合し、レンダリングで適用します。 SetTexture コマンドの後には、使用したいテクスチャのプロパティー名がきます (ここでは _MainTex)。この後には、テクスチャの適用方法を定義する combiner block がきます。コンバイナブロック内のコマンドは、画面上でレンダリングされる各ピクセルに対して実行されます。

このブロック内で、一定の色値、つまり、マテリアルの色である _Color を設定します。この一定の色はを以下で使用します。

次のコマンドでは、テクスチャと色値の混合方法を指定します。これを、テクスチャを色や他のテクスチャとブレンドする方法を指定する Combine コマンドで行います。一般に以下のような感じになります。 Combine ColorPart、AlphaPart

ここでは、 ColorPartAlphaPart が、色 (RGB) とアルファ (A) 成分のブレンディングをそれぞれ定義します。 AlphaPart が省略されると、 ColorPart と同じブレンディングを使用します。

頂点リットの例で、 Combine texture * primary DOUBLE、texture * constant

ここでは、 texture は、現在のテクスチャ (ここでは _MainTex) から来ている色です。これは primary 頂点色で乗算 (*) されます。最初の色は、頂点ライティング色で、上記マテリアル色から計算されます。最後に、結果が 2 で乗算され、ライティング強度が増します ( DOUBLE )。アルファ値 (コンマの後) は、 constant 値で乗算された texture になります (上記の constantColor で設定)。もう 1 つのよく使用されるコンバイナモードは previous と呼ばれます (このシェーダーでは使用されません)。これは、前の SetTexture 手順の結果であり、複数のテクスチャおよび/または色を相互に結合するのに使用できます。

要約

頂点リットシェーダーは、レンダリングされたライティング強度が 2 倍になるよう、標準の頂点ライティングを設定し、テクスチャコンバイナを設定します。

シェーダーにより多くのパスを入れることができ、これらのパスは次々とレンダリングされます。しかし、現在、必要な効果があるため、これは不要です。高度な機能を使用しないため、必要なサブシェーダーは 1 つだけです。この特定のシェーダーは、Unity がサポートしているグラフィックカードで機能します。

頂点リットシェーダーは、考えられる中でもっとも基本的なシェーダーです。ハードウェア固有の操作を使用せず、また ShaderLab や Cg/HLSL が提供する特殊でクールなコマンドも使用しませんでした。

次のチャプター では、Cg/HLSL 言語を使用したカスタムの頂点や断片プログラムの記述法の説明から始めます。

グラフィックスチュートリアル
シェーダー: 頂点とフラグメントプログラム