(OpenGL 3.1 - 4.2) 动态统一数组?

8
假设我有两个物种,例如人类和小马。它们具有不同的骨骼系统,因此统一的骨骼数组对于每个物种都必须不同。我是否需要实现两个分别能够正确渲染每个骨骼数组的着色器程序,还是有一种方法可以动态声明统一数组并遍历该动态数组呢?
请注意性能(这里有很多着色器在决策分支方面表现不佳)。
2个回答

17

在OpenGL 4.3之前,GLSL中的数组必须具有固定的编译时大小。4.3允许使用着色器存储缓冲区对象,可以使它们的长度“无限制”。基本上你可以这样做:

buffer BlockName
{
  mat4 manyManyMatrices[];
};

OpenGL会根据您使用的glBindBufferRange来在运行时确定这个数组中有多少个矩阵。因此,您仍然可以使用manyManyMatrices.length()来获取长度,但它不会是编译时常量。

然而,这个功能(截至本次编辑)非常新,并且仅在beta版中实现。它还需要GL 4.x级别的硬件(也称为Direct3D 11级别的硬件)。最后,由于它使用着色器存储块,访问数据可能比人们期望的要慢。

因此,我建议您只使用一个包含您将使用的最大矩阵数量的uniform块。如果出现内存问题(不太可能),则可以根据数组大小拆分着色器或使用着色器存储块等方法。


10

你可以使用n-by-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));

...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接