8

人間とポニーの2種があるとしましょう。それらは異なる骨格系を持っているので、均一な骨の配列は種ごとに異なっている必要があります。各ボーン配列を適切にレンダリングできる2つの別々のシェーダープログラムを実装する必要がありますか、それとも均一な配列を動的に宣言し、代わりにその動的配列を反復処理する方法がありますか?

パフォーマンスを念頭に置いてください(すべてのシェーダーは、意思決定の分岐を回避するのに苦労しています)。

4

2 に答える 2

17

OpenGL 4.3 までは、GLSL の配列はコンパイル時の固定サイズでなければなりませんでした。4.3 では、シェーダー ストレージ バッファー オブジェクトを使用できます。これにより、最終的な長さを「無制限」にすることができます。基本的に、これを行うことができます:

buffer BlockName
{
  mat4 manyManyMatrices[];
};

OpenGL は、使用方法に基づいて、実行時にこの配列に含まれる行列の数を計算しますglBindBufferRange。したがってmanyManyMatrices.length()、長さを取得するために引き続き使用できますが、コンパイル時の定数にはなりません。

ただし、この機能は (この編集の時点では) 非常に新しく、ベータ版でのみ実装されています。また、GL 4.x クラスのハードウェア (別名: Direct3D 11 クラスのハードウェア) も必要です。最後に、シェーダー ストレージ ブロックを使用するため、データへのアクセスが予想よりも遅くなる可能性があります。

そのため、使用するマトリックス数が最大の均一ブロックを使用することをお勧めします。それがメモリの問題になる場合 (ほとんどありません)、配列のサイズに基づいてシェーダーを分割するか、シェーダー ストレージ ブロックなどを使用できます。

于 2012-03-28T23:33:46.127 に答える
10

配列の代わりに n 行 1 列のテクスチャを使用できます。テクスチャのサイズは実行時に指定できます。このアプローチを使用して、任意の数のライトをシェーダーに渡します。ループや分岐が多いにも関わらず、その実行速度には驚かされます。例については、jReality ソースの jogl3.glsl.nontransp にある polygon.f シェーダー ファイルを参照してください。

uniform sampler2D sys_globalLights;
uniform int sys_numGlobalDirLights;
uniform int sys_numGlobalPointLights;
uniform int sys_numGlobalSpotLights;

...

int lightTexSize = sys_numGlobalDirLights*3+sys_numGlobalPointLights*3+sys_numGlobalSpotLights*5;

    for(int i = 0; i < numDir; i++){
        vec4 dir = texture(sys_globalLights, vec2((3*i+1+0.5)/lightTexSize, 0));

...

于 2013-04-12T14:02:31.253 に答える