【发布时间】:2011-07-05 04:43:41
【问题描述】:
我在 GLSL 1.5 中使用 OpenGL 3.2 上下文,出于某种原因,整数属性(int、uint、ivecX 或 uvecX 类型)在顶点着色器中总是被读取为 0。我使用以下方式声明它们:
in int name;
我使用 glVertexAttribIPointer 绑定属性(注意 I),而不是 glVertexAttribPointer (但那个也不起作用)。如果我将它们更改为浮点数,它们可以正常工作——唯一的代码区别是顶点结构中的类型、GLSL 中的类型以及 IPointer 函数调用,而不仅仅是指针。我没有得到任何错误或任何东西,它们都只是 0。如果我硬编码整数值,它可以正常工作,整数制服也可以正常工作。此外,像 gl_VertexID 这样的内置整数可以完美运行,而自定义整数则不能。我正在运行 ATI Mobility Radeon HD 5870。我在另一台具有不同 GPU 的计算机上进行了尝试(不幸的是,我不确定是什么 GPU,但它与我的不同),结果相同。任何想法为什么会这样?谢谢。
编辑:实际上它们看起来不是 0,更有可能它们是随机的大型未初始化值......很难说,因为我找不到任何调试 GLSL 着色器的方法。无论如何,一些更多的信息。这是我的顶点结构:
struct TileVertex {
float pos[2];
float uv[2];
float width;
float pad;
int animFrames;
int animFrameLength;
};
animFrames 和 animFrameLength 是我试图发送到着色器的两个整数值。我对 animFrames 的 glVertexAttribIPointer 的调用如下:
glVertexAttribIPointer( attribute.location, attribute.typeSize, attribute.baseType, (GLsizei)stride, bufferOffset( bufOffset + attribOffset ) );
地点:
attribute.location = 1 (as determined by OpenGL)
attribute.typeSize = 1 (since it's a single int, not a vector)
attribute.baseType = 5124, which is GL_INT
stride = 32, which is sizeof( TileVertex )
bufferOffset() converts to a void pointer relative to NULL
bufOffset = 0 (my vertices start at the beginning of the VBO), and
attribOffset = 24, which is the offset of animFrames in the TileVertex struct
编辑:感谢到目前为止的帮助。所以我尝试使用变换反馈,现在事情变得更有意义了。如果我将 int 属性的值设置为 1,在着色器中它是:
1065353216 = 0x3F800000 = 1.0 in floating point
如果我将它设置为 10,在着色器中我会得到:
1092616192 = 0x41200000 = 10.0 in floating point
所以看起来 int 属性被转换为浮点数,然后这些位在着色器中被解释为 int,即使我指定 GL_INT 并使用 IPointer 而不是 Pointer!据我了解,IPointer 应该只是将数据保留为整数形式,而不是将其转换为浮点数。
编辑:
这里还有一些测试。对于每个测试,我都尝试将整数值 1 传递给着色器中的整数输入:
glVertexAttribIPointer with GL_INT: shader values are 0x3F800000, which is 1.0 in floating point
似乎表明整数 1 被转换为浮点 1.0,然后被解释为整数。这意味着 OpenGL 要么认为源数据是浮点形式(实际上是整数形式),要么认为着色器输入是浮点形式(实际上是整数形式)。
glVertexAttribIPointer with GL_FLOAT: shader values are valid but weird floating point values, such as 0.0, 1.0, 4.0, 36.0... what the hell!?
不知道这意味着什么。我传递的唯一值是整数 1,所以我无法弄清楚为什么每个值会不同,或者为什么它们会是有效的浮点数!我尝试这样做的逻辑是,如果 OpenGL 将整数转换为浮点数,也许告诉它它们已经是浮点数会避免这种情况,但显然不是。
glVertexAttribPointer with GL_INT: same result as glVertexAttribIPointer with GL_INT
这是预期的结果。 OpenGL 将整数转换为浮点数,然后将它们传递给着色器。这是应该发生的,因为我没有使用 I 版本。
glVertexAttribPointer with GL_FLOAT: integer values 1 (the correct result)
这是因为 OpenGL 1) 认为源数据是浮点形式,2) 认为着色器输入也是浮点形式(它们实际上是 int 和 int),因此不应用任何转换,留下 int作为 int (或像它认为的那样浮动)。这行得通,但它似乎非常笨拙且不可靠,因为我认为不能保证 CPU 浮点到 GPU 浮点不需要转换(有些 GPU 不是使用 16 位浮点数吗?也许这只是 OpenGL 3 之前的版本,但是仍然) - 它只是不在我的 GPU 上。
【问题讨论】:
-
给我们更多信息。向我们展示对 glVertexAttribIPointer 的调用,并向我们展示您尝试传递的数据。
-
您可以通过使用变换反馈并将目标缓冲区读回主内存来调试顶点 GLSL 着色器。
-
你的属性索引是 0 吗?您传递给 glVertexAttribIPointer 的第一个值?如果您手动将其分配给不同的值会发生什么?另外,如果您更新驱动程序会发生什么?你的卡支持 3.3(ATI 有驱动程序),但你得到的是 3.2,这表明它们已经过时了。
-
我实际上传递了两个整数属性,因此其中至少一个不是索引 0。此外,使用 ATI HD 4870 的人告诉我他们遇到了同样的问题。现在我正在设置一个 3.2 的上下文,但我会在 3.3 中尝试它(无论如何,对于 3.2 没有特别的原因)。在更新驱动程序方面,这很可能是问题所在。不幸的是,每次我尝试更新时都会收到 BSOD 和锁定 - 有时甚至在安装过程中! >:(但这完全是一个不同的问题,我读到我必须先更新 VBIOS(这听起来真的很可怕)。我会再试一次并报告。
-
天啊,我不是唯一一个......看到完全相同的东西:将假定的 int 值表示为浮点数的十六进制数字。
标签: opengl attributes integer glsl