glGetUniformIndices未返回正确的索引

glGetUniformIndices not returning correct index

本文关键字:索引 返回 glGetUniformIndices      更新时间:2023-10-16

我正在学习如何使用统一缓冲区对象,阅读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。在此代码段之前或之后都没有激活的错误标志。有什么建议吗?

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

以下是这个定义的含义:

  • 存在一个名为SkeletonBlock的统一块
  • 它包含一个由64个vec3组成的称为position的数组,然后是一个由六十四个vec4组成的名为orientation的数组
  • 其所有成员的名称在GLSL中由标识符Skeleton限定

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

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

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

我相信你想要

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

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

OpenGL文档说,当你给glGetUniformIndices()起一个不好的统一名称时,你会从它得到一个GL_INVALID_INDEX。将每个返回的索引与此进行比较可能是明智的。我敢打赌GL_INVALID_INDEX == -1

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

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