私のゲームでシェーダを整理するのに助けが必要です。HLSL - シェーダとテクニックを整理し、紛失しないようにする
テクスチャリングとライティングには、頂点シェーダとピクセルシェーダが使用されます。いくつかのオブジェクトにはテクスチャが施されていますが、他に色付けされているものもあります。ライトマップ、拡散照明、鏡面照明、一部のオブジェクトだけのシャドウ生成などがあります。
私の最初のアイデアは、それはパラメータに基づいてすべてを扱うことができます。これは維持するのが賢明でした(考えを与える擬似コード)。
float4 PixelShaderFunction(input)
{
if (UseTexture)
objectColor = tex2D(...)
else
objectColor = ObjectColor;
if (UseAmbient)
...
if (UseDiffuseLight)
...
// etc...
}
パフォーマンスは低かったです。
次に、if
の分岐を避けるために、複数の手法を作成しました。すべての手法では、特定のオブジェクトに必要なものだけが使用されます。オブジェクトが影を受け入れない場合、そこにコードはありません。鏡面光を出さない場合、コードはありません。プラス私は機能に共通の機能をグループ化した。このように(実際のコードは現在):
float4 Textured_PixelShader(Textured_VsOut input) : COLOR0
{
float4 lightLevel = 0;
float4 objectColor = GetObjColorTex(input.TexUV);
// calculate main table lighting
PsAddTableLight(input.WorldPosition, input.Normal, lightLevel);
// calculate cloth lighting
PsAddClothLight(input.WorldPosition, input.Normal, lightLevel);
// calculate fill light - do we need it?
PsAddFillLight(input.Normal, lightLevel);
// add ambient light
PsAddAmbientLight(lightLevel);
// apply light
PsApplyDiffuseLight(lightLevel, objectColor);
// add speculars
PsAddSpecularBlurred(input.WorldPosition, input.Normal, objectColor);
// final work
return PsFinalize(objectColor);
}
パフォーマンスの向上は大きかった。
しかし、私はこのシェーダの維持に迷っています。 2日おきにtexture + lightmap + this_kind_of_shadow + specular
のような組み合わせがまだないので、私は新しい技術を追加する必要があります。それらの名前の中にはこのような名前が付いているものもあれば、そのような組み合わせを持つオブジェクトが1つしかないため、他の名前は使用されているオブジェクトによって名前が付けられます。そしてそれは混乱になっています。
私は、2つの質問があります:私はそれらのif
ステートメントを持つことができないのはなぜ
- を?条件付き実行がGPUにどのような影響を与えるかについて多くのことを読んでいますが、ifはすべてのレンダリングされたピクセル(またはverts)の値が同じシェーダパラメータにのみ依存します。なぜ彼らは速くないのですか?私は本当にそれらが恋しいです。
- このコードを異なるシェーダ/技術/ファイルに分割する最も良い方法は何ですか?良い基準やルールはありますか?
残念ながら、あなたの方法(動的コンパイル)に従うことができないようです。モノゲームはそれをサポートしていないので、たとえそれが一部のプラットフォームのみに限定されているとしてもです。しかし、これは私が受け入れられたと印を付ける偉大で価値ある答えです - ありがとう。 – Arek
なぜ、 'if'が遅いのか - 私はまだ分かりませんが、すぐにパフォーマンスの低下を確認するためにいくつかの再テストを行います。すべての情報源によれば、 'if'条件はレンダリングされるすべてのものに対して同じであるため、速くなければなりません。 – Arek