2012-03-28 10 views
5

私は人間や小鳥のような2つの種があると言います。それらは異なる骨格系を有するので、均一な骨配列は各種ごとに異なっていなければならない。各ボーン配列を適切にレンダリングできる2つの別々のシェーダプログラムを実装する必要がありますか、またはユニフォーム配列を動的に宣言し、そのダイナミック配列を反復処理する方法がありますか?(OpenGL 3.1 - 4.2)ダイナミックユニフォームアレイ?

パフォーマンスを念頭に置いて(決定分岐ではシェーダーのすべてが吸う)。

答えて

12

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

buffer BlockName 
{ 
    mat4 manyManyMatrices[]; 
}; 

OpenGLはあなたがglBindBufferRangeを使用する方法に基づいて実行時に、この配列内にあるどのように多くの行列を把握します。したがって、長さを取得するのにまだmanyManyMatrices.length()を使用できますが、コンパイル時定数ではありません。

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

このように、使用する行列の数が最も多い均一ブロックを使用することをお勧めします。それがメモリの問題になる場合は、アレイサイズに基づいてシェーダを分割したり、シェーダストレージブロックなどを使用することができます。

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)); 

...

関連する問題