4

我正在尝试学习如何使用统一缓冲区对象,阅读 OpenGL Superbible 5。我的着色器中有一个统一块:

layout(std140) uniform SkeletonBlock  
{  
    vec3 position[64];  
    vec4 orientation[64];  
} Skeleton;

现在我获取索引的代码是:

const GLchar* uniformNames[2] =
{
    "SkeletonBlock.position",
    "SkeletonBlock.orientation"
};

GLuint uniformIndex[2];
glGetUniformIndices(shaderProgram, 2, uniformNames, uniformIndex);

出于某种原因,这个电话给了我一个非常高的指数(4294967295,始终如一),我不知道为什么。我觉得我错过了一些明显的东西。OpenGL 正在报告一个活动的统一块,这是正确的,最多允许 15 个。在这部分代码之前或之后也没有错误标志处于活动状态。有什么建议可能会出错吗?

4

3 回答 3

2
layout(std140) uniform SkeletonBlock  
{  
    vec3 position[64];  
    vec4 orientation[64];  
} Skeleton;

以下是该定义的内容:

  • 有一个名为 的统一块SkeletonBlock
  • 它包含一个 64 vec3sposition的数组,后跟一个 64 vec4s 的数组,称为orientation
  • 它所有成员的名称在 GLSL 中由标识符限定Skeleton

注意最后一部分。在 GLSL 中,并且仅在 GLSL中,position数组由 标识Skeleton.position。在 C++ 中,数组由SkeletonBlock.position或标识SkeletonBlock.position[0]。这里的要点是,在 C++ 代码中,您使用块名称 SkeletonBlock作为前缀,而不是实例名称Skeleton

SkeletonBlock块有一个可以查询的索引glGetUniformBlockIndex(注意“块”一词的使用和“索引”上缺少复数)。各个制服成员也有索引,但它们是制服列表中的索引。并且这些变量必须正确命名。如果统一块具有实例名称,则统一块成员必须以块名称为前缀,而不是实例名称。

如果您将这些名称传递给 OpenGL 函数并且没有获得有效的索引,那么您可能有一个驱动程序错误。

于 2012-01-20T07:00:43.667 回答
1

我相信你想要

const GLchar* uniformNames[2] =
{
    "Skeleton.position",
    "Skeleton.orientation"
};

正如 C 风格语言(例如 GLSL)的语义所具有的那样,您声明了一个uniform SkeletonBlock名为Skeleton. 因此,"SkeletonBlock.position"<typename>.<member>您想要的形式<variable>.<member>

OpenGL 文档说,当你给它一个不好的统一名称时,你会得到一个GL_INVALID_INDEXfrom 。glGetUniformIndices()对照此检查每个返回的索引可能是明智的。我敢打赌GL_INVALID_INDEX == -1

此外,这个数字 4294967295 是 32 位 -1(二进制补码)的无符号解释。

于 2012-01-10T17:06:23.310 回答
0

如果在着色器的 GLSL 源代码中没有引用(即使用)统一块变量,您可能会遇到这种情况。着色器源代码编译器将从着色器中完全删除变量作为优化。然后,当您调用时glGetUniformIndices,将返回 GL_INVALID_INDEX。

于 2015-12-21T10:56:49.777 回答