【问题标题】:glGetUniformIndices not returning correct indexglGetUniformIndices 没有返回正确的索引
【发布时间】:2012-01-09 20:37:31
【问题描述】:

我正在尝试学习如何使用统一缓冲区对象,阅读 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 个。在这部分代码之前或之后也没有错误标志处于活动状态。有什么建议可能会出错吗?

【问题讨论】:

  • glGetError() 返回什么?那个非常高的索引是-1 的代名词,这让我觉得 OpenGL 试图告诉你一些事情。
  • 在调用 glGetUniformIndices() 前后,glGetError() 没有返回错误。
  • 位置 -1 表示着色器中不存在制服。您是否在实际着色器中的任何地方使用这些制服? GLSL 编译器可能正在优化它们。
  • 是的,它们用于计算顶点的最终位置。感谢您的澄清,但不知道这一点。 :)

标签: c++ opengl opengl-3


【解决方案1】:
layout(std140) uniform SkeletonBlock  
{  
    vec3 position[64];  
    vec4 orientation[64];  
} Skeleton;

这个定义是这样写的:

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

注意最后一部分。在 GLSL 中,仅在 GLSL 中position 数组由 Skeleton.position 标识。在 C++ 中,数组由SkeletonBlock.positionSkeletonBlock.position[0] 标识。这里的重点是from C++ code you use the block nameSkeletonBlock作为前缀,而不是实例名称Skeleton

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

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

【讨论】:

  • 根据ARB_uniform_buffer_object,uniform 块的成员具有索引:“每个活动的uniform,无论是在命名的uniform 块中还是在默认块中,都会在链接程序时分配一个索引。”例如,我相信这些索引是您将传递给 glGetActiveUniformsiv 以确定成员的缓冲区偏移量的索引。当然,如果使用 std140 布局,则没有必要。
  • @tgnottingham:统一块成员具有统一索引,但没有位置
【解决方案2】:

我相信你想要

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(二进制补码)的无符号解释。

【讨论】:

  • -1:这个答案是错误的。我不知道它是如何被接受的。前 2 个句子有 3 种不同的错误。
  • Nicol Bolas,请解释一下这个答案是怎么错的,以便我进行适当的编辑。
  • 我的回答几乎解释了它的所有问题。还有the UBO page on the wiki covers it too.
  • 我提供的代码 sn-p 是基于描述如何创建和使用 UBO 的 OpenGL Superbible 章节。使用 glGetUniformBlockIndex 但稍后发生;在用数据填充 UBO 之后。 scpayson 的回答解决了我没有检索正确信息以便用信息填充缓冲区的问题。 Superbible 章节是否存在我不知道的已知问题?我想知道使用这些的正确方法。
  • 如果这解决了您的问题,则表明实施中存在错误。解释GLSL specification(旧版本为 4.3.7)的第 4.3.9 节:在 GLSL 中,如果存在实例名称,则在块内声明的名称必须由实例名称限定,但在 GLSL 之外,它们必须由如果存在实例名称,则为块名称。如果没有实例名称,则成员名称在 GLSL 内外都足够。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 2017-07-31
    • 1970-01-01
    • 2020-10-02
    • 1970-01-01
    • 1970-01-01
    • 2021-07-05
    • 1970-01-01
    • 2019-06-26
    • 1970-01-01
    相关资源
    最近更新 更多