8

假设我有 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-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));

...

于 2013-04-12T14:02:31.253 回答