シェーダーを使用するOpenGLアプリケーションのソースを調べています。 1つの特定のシェーダーは次のようになります。
uniform float someConstantValue;
void main()
{
// Use someConstantValue
}
ユニフォームはコードから一度設定され、アプリケーションの実行時に変更されることはありません。
someConstantValue
をconst float
としてではなく、uniform
として宣言したいのはどのような場合ですか?
編集:明確にするために、定数値は物理定数です。
まず、ユニフォームと定数の使用によるパフォーマンスの違いはおそらく無視できます。第二に、値が本質的に常に一定であるからといって、プログラム内で常に一定である必要があるとは限りません。プログラマーは、実際と一致しない場合でも、物理的な値を微調整して見栄えの良い結果を生成することがよくあります。たとえば、特定の種類のゲームでは、重力による加速度を増やしてペースを速くすることがよくあります。
コードでユニフォームを設定する必要がない場合は、GLSLでデフォルト値を指定できます。
uniform float someConstantValue = 12.5;
とは言うものの、それを変更する価値がほとんどないpiのようなものにconstを使用しない理由はありません。
大きな理由:
エラー:ループインデックスを非定数式と比較できません。
使用する場合:
uniform float myfloat;
...
for (float i = 0.0; i < myfloat; i++)
エラーが発生しますmyfloat
はconstant expression
ではないため。
ただしこれは完全に有効です:
const float myfloat = 10.0;
...
for (float i = 0.0; i < myfloat; i++)
なぜ?
GLSL(およびそのことについてはHLSL)がGPUアセンブリ命令にコンパイルされると、ループは非常に冗長な方法で展開されます(ただし、ジャンプなどを使用して最適化されます)。
myfloat
値は、コンパイル時にループを展開するために使用されます。その値がuniform
の場合(つまり、各レンダリング呼び出しを変更できる場合)、そのループは実行時まで展開できません(GPUは少なくともWebGLではそのようなJustInTimeコンパイルを実行しません)。
私は2つの理由を考えることができます:
開発者は、いくつかのアプリケーションでシェーダーのライブラリを再利用します。そのため、開発者は、アプリごとに各シェーダーをカスタマイズするのではなく、それらを一般的にしようとします。
開発者は、この変数が後でユーザー制御の設定になると予想しています。したがって、それを均一であると宣言することは、その次の機能の準備です。
私が開発者であり、上記のいずれにも当てはまらない場合は、パフォーマンス上の利点があり、コードからユニフォームを設定する必要がないため、代わりに「const」として宣言します。