将 uint 属性传递给 GLSL

Posted

技术标签:

【中文标题】将 uint 属性传递给 GLSL【英文标题】:Passing uint attribute to GLSL 【发布时间】:2013-09-20 14:59:38 【问题描述】:

我正在尝试将一堆连续的无符号整数作为属性传递给我的 GLSL 着色器。

到目前为止,我想出了

s_number = glGetAttribLocation(shader, "number");

numberData = new GLuint[dotAmount];
for (GLuint i = 0; i < dotAmount; i++) 
    numberData[i] = i;


glGenBuffers(1, &vertBuf);
glBindBuffer(GL_ARRAY_BUFFER, vertBuf);

glBufferData(
        GL_ARRAY_BUFFER,
        sizeof(dotAmount),
        numberData,
        GL_STATIC_DRAW
);

渲染函数是

glUseProgram(shader);

[..]

glEnableVertexAttribArray(s_number);
glBindBuffer(GL_ARRAY_BUFFER, vertBuf);

glVertexAttribPointer(
        s_number,
        1,
        GL_UNSIGNED_INT,
        GL_FALSE,
        0,
        BUFFER_OFFSET(0)
);

glDrawArrays(GL_POINTS, 0, dotAmount);

我尝试像这样在顶点着色器中使用数字:

attribute uint number;

(名称“vertBuf”实际上有点误导,因为它不是我要传递的顶点数据) 我正在使用 OpenGL 3 和着色器版本 1.3。

我想要实现的是,我希望着色器被执行dotAmount 次。定位是在着色器中以数学方式完成的。但我得到的只是一个空白屏幕......

我很确定问题不在于着色器。我想画点,如果我把gl_Position = vec4(0.0, 0.0, 0.0, 0.0); 放在顶点着色器中,我认为它应该画一些东西。

【问题讨论】:

顺便说一句,如果你想要的只是一个从 0 到 dotAmount-1 的序列,你可以读取 gl_VertexID (opengl.org/sdk/docs/manglsl/xhtml/gl_VertexID.xml)。如果您迁移到 GLSL 1.4+,那么您可以使用实例渲染和 gl_InstanceID。 感谢您的提示,非常有用。 【参考方案1】:

您使用了错误的 API 调用来指定您的顶点属性指针。

glVertexAttribPointer (...) 用于浮点顶点属性。它很乐意接受整数数据类型的值,但最终该值将转换为浮点数。这就是为什么它有一个参数来控制浮点归一化。启用规范化后,您传递的整数值会使用类型的范围进行调整,以使其适合规范化的浮点范围:[-1.0, 1.0](有符号)或[0.0, 1.0](无符号);禁用时,整数将被有效地视为已转换为 GLfloat

在您的情况下,您不需要上述任何行为。在您的顶点着色器中,您的顶点属性一开始就不是浮点类型,因此让 OpenGL 将您的顶点数组数据转换为浮点数将产生毫无意义的结果。

您需要做的是使用glVertexAttribIPointer (...)。注意这个函数如何缺少用于标准化的布尔值?它会将您的整数顶点数据完全原封不动地传递给您的顶点着色器,这正是您想要的。

总结:

    glVertexAttribPointer (...) 非常适合为浮点顶点属性(即vec&lt;N&gt;mat4float)提供数据,并且会为您进行数据类型转换。

    glVertexAttribIPointer (...) 专为整数属性而设计(即ivec&lt;N&gt;uint)。

【讨论】:

这对问题无关紧要,但这是一个非常好的信息! 这对我很有帮助! 我只是想花一点时间来表达我对你的爱。这个答案解决了我所有的问题。 非常好的答案,这对我很有帮助【参考方案2】:

尝试将片段着色器更改为gl_FragColor = vec4(1,0,0,1); 这将确保输出颜色使片段可见。

另外,你应该有gl_Position = vec4(0, 0, 0, 1);(原因是gl_Position必须在齐次坐标中,这意味着前三个分量将被第四个除。)

【讨论】:

gl_Position 不设置颜色,而是设置剪辑空间位置。但是,您的点仍然有效,因为 (0.0, 0.0, 0.0, 0.0) 处的剪辑空间点会导致除以零和未定义的 NDC/屏幕坐标。

以上是关于将 uint 属性传递给 GLSL的主要内容,如果未能解决你的问题,请参考以下文章

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

GLSL 将 uint 转换为 float 以获取颜色

将 uint8_t 数组传递给方法

将指向 uint16_t 的指针传递给需要 C 中 uint8_t[] 数组的子例程 - 如何?

OOP:将对象与将属性传递给方法

将 MSI 属性传递给 sqlstring