デフォルト値と置き換えでシェーダを柔軟にシェーダを柔軟に自動的に作る方法を考えるシェーダシステム編。鍵となる「柔軟性」を実現するにはどうしたら良いのか?この章ではその辺りの考え方について見ていきましょう。値が無いならデフォルト値で例えばです。あるモデルは頂点座標とマテリアル情報としてディフューズカラー(グローバル値)を持っていたとします。それを頂点シェーダに入れて、ピクセルシェーダに頂点カラーとして出力するとします。それを図で表すと次のようになります:上の頂点シェーダはこの2つの情報を使ってピクセルシェーダに値を渡します。別の見方をするならば、上の頂点シェーダは「この2つの情報が必要」です。所が、別のモデルは頂点情報しか持っていなかったとします。すると、上の図はこうなってしまいます:入力情報のマテリアルDiffuseが欠けてしまっています。固定的な頂点シェーダの場合、グローバル変数に値が入っていない場合は「何らかの」値がそこに入ります。頂点シェーダ側では実はグローバル変数に対して「初期値」は設定できません。柔軟性を確保する第1歩は、上のように頂点シェーダが要求するグローバル変数をモデルが持っていない場合に、代替値を入れてそれを補う仕組みを考える事です。グローバル変数はconstですグローバル変数が与えられなかった場合に初期化するというのは、実は結構面倒なんです。いうのも「シェーダのグローバル変数はconst扱い」なためです。Out;}上の太字のように、グローバル変数にシェーダ内で値を入れようとするとコンパイルエラーになります。const扱いという事は宣言と同時に初期化はできます。Out;}これは合法です。嬉しい事に、もし上のマテリアルDiffuseが外部で初期化されなかった場合は上の値を、外部で初期化された場合はその値が入れ替わって使われます。グローバル変数は「必ず初期化する」。する事で、グローバル変数(一般変数)については書き分けの必要が無くなります。次の図をご覧下さい:今度は頂点シェーダが頂点座標とUVを要求している例です。これらが揃っているモデルであれば上の頂点シェーダは動きます。所が、UVが欠ける事がありえます:この時にどう対処するか?これが難しいところです。先ほどのグローバル変数と違い、UV値は「頂点シェーダ入力セマンティクス」の一員です。悲しいかな「入力セマンティクス」は宣言時初期化が無効化されてしまいます。Out;}上の太文字で示しているような初期化は意味を成しません(コンパイルは通ります)。そこで取るべき道は2つあります。Out;}頂点シェーダの引数はconstでは無いためこれは合法です。シェーダは正常に動きます。Out;}どちらが良いかというと、う〜〜ん、多分前者かなと思います。後者の方はシェーダが複雑になった時に対処箇所が格段に増えてしまいます。「でも前者の方は無駄な計算をする事になるんじゃない?」と思われた方は鋭いです。Out;}入力座標のX成分を0.5だけオフセットしてそれに0.0を掛けています。結局pos.xは常に0.0になります。Out;}と解釈してくれます。いうシェーダの最適化をうまく利用すると、入力セマンティクスを初期化しておく一文をはさむ事によるパフォーマンス低下をある程度低減できるんです。いう事を鑑みると、「欠けている入力セマンティクスがあった場合、代わりに初期値を入れる一文を挿入する」という自動生成が有効そうです。すれば、頂点シェーダの内部自体は特に変更を必要としません。テクスチャとサンプラの欠如セマンティクスについては初期値を入れておく事で何とかなりそうですが、何ともならない厄介者がテクスチャとそれを利用するサンプラです。次の図をご覧下さい:これはテクスチャ(Tex0)から指定UV座標にある色をSampler0に従って貰いそれを利用するピクセルシェーダです。tex0;)とサンプラがあれば、シェーダ自体は動きます。0.0f)が返ってきます。「ならいいじゃん」と言いたい所なのですが、テクスチャの場合はそうともいかない状況があります。