如何使用 glVertexAttribPointer() 添加非数组值

Posted

技术标签:

【中文标题】如何使用 glVertexAttribPointer() 添加非数组值【英文标题】:How to add non-array value using glVertexAttribPointer() 【发布时间】:2020-11-19 13:11:02 【问题描述】:

我知道有uniforms 可以解决这个问题,但我想知道是否可以使用glVertexAttribPointer() 来增加像int 这样的价值?

着色器:

#version 330 core  
layout (location = 0) in vec3 aPosition;
layout (location = 1) in vec3 aColor;
layout (location = 2) in int aSize;

out vec3 vColor;

void main()  
  
    gl_Position = vec4(aPosition, 1.0f);
    gl_PointSize = aSize;
    vColor = aColor;

代码:

makeCurrent();

glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);

glBufferData(GL_ARRAY_BUFFER, points.vbo.size() * sizeof(GLfloat), &points.vbo.front(), GL_STATIC_DRAW);  //look below to the struct
glVertexAttribPointer(0, points.vertexAmount, GL_FLOAT, GL_FALSE, points.stride * sizeof(GLfloat), (GLvoid *)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, points.colorAmount, GL_FLOAT, GL_FALSE, points.stride * sizeof(GLfloat), (GLvoid *)(points.vertexAmount * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(/* ??? how to add simple int here ??? */);
glEnableVertexAttribArray(2);

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);

doneCurrent();

points 结构:

struct RenderedObjects

    std::vector<float> vbo;
    int vertexAmount = 3;
    int colorAmount = 3;
    int stride = vertexAmount + colorAmount;
    int size = 1;
 points;

【问题讨论】:

【参考方案1】:

glVertexAttribPointer 仅用于数据数组。当您发出 dasw 调用时,GPU 将获取每个启用的属性数组的i-th 元素,并使用顶点属性指针数据在 VBO 中查找该元素。

对于未启用属性数组的属性输入,您可以将值设置为 GL 状态的一部分。函数族glVertexAttib...() 允许您设置通用顶点属性的值。

OpenGL 的命名约定在这里可能会有些混乱。默认情况下,顶点属性始终被视为浮点数,即使您将输入指定为整数(与 glVertexAttribPointer()s 类型参数相同)。因此,即使您可能认为 glVertexAttrib1i() 可能会设置标量整数属性的值,但实际上它只是通过提供整数值来设置 float 属性。

稍后添加到 GL 的整数属性,您必须使用 glVertexAttribI() / glVertexAttribIPointer()(注意大写的 I 字母)。

因此,为layout (location = 2) in int aSize; 指定单个常量输入的正确方法是:

 glVertexAttribI1i(2, yourIntegerValue); 
 glDisableVertexAttribArray(2); // do NOT use an array for this attribute

(当您创建 VAO 时,所有属性数组最初都被禁用,因此您可能不需要在此处显式调用 glDisableVertexAttribArray(2)。)

【讨论】:

错误:“glVertexAttribI1i”未在此范围内声明;你的意思是“glVertexAttribP1ui”吗?我需要一些特定的 GL 版本或标题吗?我将着色器和上下文设置为 3.3,我看到 glVertexAttribI1i 甚至适用于 2.0。 我看到它显然不是 QOpenGLFunctions_3_3_Core 的一部分 glVertexAttribI1i 是在 OpenGL 3.0 中引入的,是核心配置文件的一部分,如果这个功能不是 QOpenGLFunctions_3_3_Core 的一部分,我不知道 Qt 会做什么,但是官方的 OpenGL 3.3 核心规范包括这个功能。 我还发现只有在 glEnable(GL_PROGRAM_POINT_SIZE); 之后才能使用点上的着色器进行任何大小操作; “我还发现任何在点上使用着色器的大小操作都只能在 glEnable(GL_PROGRAM_POINT_SIZE); 之后使用”,这是正确的。在桌面 GL 上,有这个设置,而 GLES 没有这个状态,并且总是表现得好像启用了可编程点大小。

以上是关于如何使用 glVertexAttribPointer() 添加非数组值的主要内容,如果未能解决你的问题,请参考以下文章

glVertexAttribPointer和stride参数要求

缓冲区和 glVertexAttribPointer 之间的关系

glVertexAttribPointer() - 啥时候应该调用它?

glVertexAttribPointer 出现 JOGL 错误

glVertexAttribPointer 返回 GL_INVALID_OPERATION

GLES2.0 上的 VBO glDrawElements 和 glVertexAttribPointer 不显示任何内容