2012-03-28 42 views
5

可以說我有2種,如人類和小馬。它們具有不同的骨骼系統,因此對於每個物種而言,統一的骨骼陣列必須是不同的。我是否必須實現兩個獨立的着色器程序,能夠正確渲染每個骨骼數組,或者是否有辦法動態聲明統一數組並反覆遍歷該動態數組?(OpenGL 3.1 - 4.2)動態均勻陣列?

記住性能(有所有的着色器在決策分支四處流竄)。

回答

12

在OpenGL 4.3之前,GLSL中的數組必須是固定的編譯時大小。 4.3允許使用着色器存儲緩衝區對象,這允許它們的最終長度是「無界」的。基本上,你可以這樣做:

buffer BlockName 
{ 
    mat4 manyManyMatrices[]; 
}; 

的OpenGL將計算出有多少矩陣是這個數組在運行時根據您如何使用glBindBufferRange。所以你仍然可以使用manyManyMatrices.length()來獲得長度,但它不會是編譯時常量。

但是,此功能(在編輯時)非常新,只能在beta版本中實現。它還需要GL 4.x級硬件(又名:Direct3D 11級硬件)。最後,由於它使用着色器存儲塊,訪問數據可能比人們希望的要慢。

因此,我建議你只是使用一個統一的塊,並使用最多的矩陣。如果這成爲一個內存問題(不太可能),那麼你可以根據數組大小拆分着色器,或使用着色器存儲塊或其他。

10

您可以使用n-by-1-Textures作爲數組的替代品。紋理尺寸可以在運行時指定。我使用這種方法將任意數量的光傳遞給我的着色器。我很驚訝,儘管有許多循環和分支,它運行得有多快。有關示例,請參閱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)); 

...