今回はShader学習枠です。
MRGTのプロジェクトリーダーであり、筆者の尊敬しているエンジニアでもあるCameronさんによるShaderに関する講座がYoutube上で公開されていました。
全編が英語なのと、若干読み解きにくいところもあったため今回から読み解いていきます。
公開されている動画はこちらになります。
〇セッションの内容
セッションは次の8つのセクションで区切られています。
§1Shaderとは何か?
§ 2 Shaderの実行
§3 マテリアルとレンダーモード
§4 MixedReality における注意点
§5 パフォーマンスと最適化ツール
§6 デバッグ
§7 その他のリファレンス
§8 Q&A
昨日は§2を見てShaderLabの構造を理解しました。
今回は引き続き続きを見てShaderの処理と実行を見ていきます。
〇HLSL文
ShaderLabではSubShader内のCGPROGRAM~ENDCGの間でHLSL文を使用してシェーダーを記述します。
CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" ... ENDCG
なお最近のプロジェクトなどではHLSLPROGRAM~ENDHLSLが使用されることも多いですが、基本的には同一です。
〇pragma
#paragmaはコンパイラ指令です。
グラフィックスパイプラインの各プログラマブルなブロック内でのエントリーポイントを指定する分です。
#pragma vertex vert #pragma fragment frag
通常最低2つ定義されており、デフォルトでは頂点シェーダーでのエントリーポイントをvert、フラグメントシェーダーでのエントリーポイントをfragと定義しています。
vart,fragの文字はその後で記述される関数名を表しているので別の名前が使用される場合もあります。
〇シェーダーバリアント
もう一つ#pragmaが定義されています。
#pragma multi_compile_fog
こちらはフォグ(霧)に関するコンパイルを行うシェーダーバリアントです。
AR系のアプリケーションではフォグは必要ない場合が多いですがシェーダーバリアントという意味では非常に重要なブロックです。
シェーダーバリアントは数多くの機能を持ったシェーダーを使用する際におおく使用されるものです。
まず前提としてShaderではIf文を避けるべきとされています。
理由はShaderがGPU上で実行されるプログラムということですが、分岐処理を行う場合すべてのピクセルで処理が行われます。これが場合によって非常に重い処理となっています。
詳しい理由はLIGHT11さんの記事で紹介されています。
If文を使用せずに安価に分岐処理を行うためには、使用しないコードは決して実行させない仕組みであることです。
シェーダーバリアントを使用するとシェーダーのコンパイル時にある機能を含むor含まないシェーダーをそれぞれ作成し、管理することができます。 手動でこれを行う場合非常に大変な作業になり、パフォーマンスという意味で非常に強力な機能になっています。
これはコンパイル時に機能に応じてシェーダーのバリエーションを書き出すという意味にもなるかもしれません。
筆者もそこまで使いこなしているわけではありませんが、多くの機能を持つシェーダーのパフォーマンスを向上させる目的で使用される機能になります。
〇include
関数を含む実際のコードが始まる前に最後に次の分があります。
#include "UnityCG.cginc"
これはシェーダーファイルのヘッダー#include ○○で記述したファイルを読み込むことを意味します。
C#で例えると継承のような使い方になります。
今回は以上です。
次回からやっと実際の頂点シェーダーやフラグメントシェーダーの説明になります。