均一な変数を持ついくつかのシェーダーがあり、すべてのシェーダーで同じ名前が付けられています。すべてのシェーダーで同じ名前のユニフォームを一度に更新するための最良の方法は何ですか?私は次のアプローチを検討します。
1)各プログラムのユニフォームの場所を保存し、プログラムが「使用済み」プログラムとして割り当てられた直後に更新します(glUseProgram
)。
短所:すべての「共有」ユニフォーム変数は、glUseProgram
呼び出しのたびに更新されます。さらに、現在のフレーム中にプログラムが初めて使用されていない場合、すべてのglUniform*
呼び出しが冗長になります。または、プログラムを初めて使用するかどうかを示す一連のフラグが必要です。「未使用」フラグは、フレームごとにリセットする必要があります。
2)均一なバッファとshared
(またはstd140
)レイアウトを使用します。このアプローチでは、一度にユニフォームを設定してから、バッファーを更新せずにシェーダープログラムを変更できます。しかし、共有変数が変換行列のみである単純なシェーダーがたくさんある場合はどうなるでしょうか。このような少量のメモリに均一なバッファを使用しても大丈夫ですか?いくつかのフォーラムの議論で私はそれを読みました
glBindBuffer(GL_UNIFORM_BUFFER,buf);
glBufferSubData(/*just 16 floats*/);
glBindBuffer(GL_UNIFORM_BUFFER,0);
glUniform*
呼び出しよりもはるかに遅いです。ここで、最初のアプローチと2番目のアプローチのどちらを選択するかは、次の条件に依存することがわかります。
- シェーダーはフレームごとにどのくらいの頻度で変更され、どのくらいの頻度で繰り返されますか?
- 「共有」ユニフォームはいくつありますか?
- 各フレームでどのくらいの量のデータをシェーダープログラムに渡す必要がありますか?
これらの3つの質問に対する回答に関係なく、優れたパフォーマンスを発揮する妥協的なデザインパターンはありますか?
3) ubershaderを使用します。ここで2番目の段落で言及されています:GLSLマルチシェーダープログラムVSユニフォームスイッチ。私はそれについて2つの質問があります:
パフォーマンスが優れているのは何ですか。1回glUseProgram
の呼び出しまたは複数の均一なスイッチで、ubershaderの機能が変更されますか?
言及されたその質問の作者
ユニフォームはフレームごとに何度も変更する必要があります
ubershaderの欠点の1つとして。しかし、なぜそれは悪いのですか?パフォーマンスが悪いですか?もしそうなら、変換行列やその他の小さなサイズのものを均一変数として渡し、フレームごとに更新しても大丈夫ですか?
そして、上記のすべてを要約する主な質問:いくつかの異なるシェーダープログラムで同じ名前の均一変数を更新するための他の手法やデザインパターンを提案できますか?
UPD:答えは受け入れられますが、重要な高レベルの設計手法(C ++または言語に依存しない)を提案できる場合は、ここに残してください。