无法获取在GLSL 1.5中工作的整数顶点属性

Gum*_*mgo 16 opengl attributes integer glsl

我正在使用带有GLSL 1.5的OpenGL 3.2上下文,并且由于某种原因,整数属性(类型为int,uint,ivecX或uvecX)在顶点着色器中始终被读取为0.我宣布他们使用:

in int name;
Run Code Online (Sandbox Code Playgroud)

我使用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;
};
Run Code Online (Sandbox Code Playgroud)

animFrames和animFrameLength是我试图发送到着色器的两个整数值.我对animFrames的glVertexAttribIPointer的调用如下:

glVertexAttribIPointer( attribute.location, attribute.typeSize, attribute.baseType, (GLsizei)stride, bufferOffset( bufOffset + attribOffset ) );
Run Code Online (Sandbox Code Playgroud)

哪里:

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
Run Code Online (Sandbox Code Playgroud)

编辑:感谢你们的帮助到目前为止.所以我尝试使用变换反馈,现在事情变得更有意义了.如果我将int attrib的值设置为1,则在着色器中它是:

1065353216 = 0x3F800000 = 1.0 in floating point
Run Code Online (Sandbox Code Playgroud)

如果我将其设置为10,则在着色器中我得到:

1092616192 = 0x41200000 = 10.0 in floating point
Run Code Online (Sandbox Code Playgroud)

因此看起来int attrib被转换为float,然后这些位在着色器中被解释为int,即使我指定GL_INT并使用IPointer而不是Pointer!据我了解,IPointer应该只是以整数形式保留数据而不是将其转换为浮点数.

编辑:

这是一些更多的测试.对于每个测试,我试图将整数值1传递给着色器中的整数输入:

glVertexAttribIPointer with GL_INT: shader values are 0x3F800000, which is 1.0 in floating point
Run Code Online (Sandbox Code Playgroud)

似乎表明整数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!?
Run Code Online (Sandbox Code Playgroud)

不知道这意味着什么.我传递的唯一值是整数1,所以我无法弄清楚为什么每个值都不同,或者为什么它们是有效的浮点数!我的逻辑尝试这个是,如果OpenGL将整数转换为浮点数,也许告诉它它们已经浮动会避免这种情况,但显然不是.

glVertexAttribPointer with GL_INT: same result as glVertexAttribIPointer with GL_INT
Run Code Online (Sandbox Code Playgroud)

这是预期的结果.OpenGL将int转换为浮点数,然后将它们传递给着色器.这是我应该发生的事情,因为我没有使用I版本.

glVertexAttribPointer with GL_FLOAT: integer values 1 (the correct result)
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为OpenGL 1)认为源数据是浮点形式,2)认为着色器输入也是浮点形式(它们实际上是int和int),因此不应用任何转换,将int保留为int(或浮动,如它认为的那样).这有效,但它看起来非常h​​acky和不可靠,因为我认为没有保证CPU浮动到GPU浮动不需要转换(不是一些GPU使用16位浮点数?也许这只是pre-OpenGL 3但是仍然) - 它不在我的GPU上.

Ben*_*igt 5

对于其中一个着色器(不记得是哪个),您需要使用varying关键字。或者也许是attribute关键字。GLSL 的更高版本使用inout代替。

我认为你需要:

attribute int name;
Run Code Online (Sandbox Code Playgroud)

用于进入顶点着色器的数据,以及

varying int name;
Run Code Online (Sandbox Code Playgroud)

用于从顶点着色器到片段着色器的数据。

还要确保使用glEnableVertexAttribArray.


我在使int属性工作时也遇到了一些麻烦,但我确实发现该type字段(GL_INTGL_FLOAT传递给glVertexAttribPointer匹配传递给它的数据,而不是着色器中的数据类型)。所以我最终使用glVertexAttribPointerand GL_INTwhichint在我的主机上转换为float我的着色器,这对我来说很好,因为我的属性是位置数据,vec2无论如何都需要通过浮点转换。

可能您需要glVertexAttribIPointerEXT匹配着色器int属性,然后还需要匹配GL_INT主机是否以int数组形式提供数据。

  • @Luca:它们是在 1.30 中引入的。 (2认同)