顶点着色器 VAO 是不是需要 VBO?

Posted

技术标签:

【中文标题】顶点着色器 VAO 是不是需要 VBO?【英文标题】:Does a Vertex Shader VAO need a VBO?顶点着色器 VAO 是否需要 VBO? 【发布时间】:2016-11-17 03:09:32 【问题描述】:

我正在尝试使用带有顶点着色器的 VAO。这有效,但前提是我将 bufferData 的长度设置为 0。我的理解是,当使用顶点着色器时,不需要 VBO,因为我的着色器正在生成四边形的顶点。如果我尝试在不绑定缓冲区的情况下创建 VAO,它也会崩溃。

正如我所提到的,这可行,但我很担心,因为在 Apple 的 Instruments 中,OpenGL 专家报告了一个严重错误:

Draw Call Exceeded Array Buffer Bounds
No Buffer Data - DYFKNoBufferData

这是生成 VAO 的代码:

    glGenVertexArrays(1, &vaoID); // Create our Vertex Array Object
    glBindVertexArray(avoid); // Bind VAO

    GLfloat vertices[12];  // Vertices for our square

    vertices[0] = -0.5; vertices[1] = 0.5; vertices[2] = 0.0; // Top left corner
    vertices[3] = -0.5; vertices[4] = -0.5; vertices[5] = 0.0; // Bottom left corner
    vertices[6] = 0.5; vertices[7] = 0.5; vertices[8] = 0.0; // Top Right corner
    vertices[9] = 0.5; vertices[10] = -0.5; vertices[11] = 0.0; // Bottom right corner

    glGenBuffers(1, &fboTextureVboID); // Create our Vertex Buffer Object
    glBindBuffer(GL_ARRAY_BUFFER, fboTextureVboID); // Bind VBO
    // As long as I set the buffer data length to 0
    // then my glDrawArrays(GL_TRIANGLE_STRIP, 0, 4) call works
    // otherwise I get EXC_BAD_ACCESS
    glBufferData(GL_ARRAY_BUFFER, 0, vertices, GL_STATIC_DRAW);

    // configure vertex attributes
    glEnableVertexAttribArray (...
    glVertexAttribPointer(...
    ...

    glEnableVertexAttribArray(0); // Make our Vertex Array Object Inactive
    glBindVertexArray(0); // Make our Vertex Buffer Object Inactive

绘图:

glUseProgram(vertexShaderProgram);
glBindVertexArray(vaoID);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

我可以放心地忽略 Apple 的错误吗?我正在尝试为顶点着色器使用 VAO,因为我想消除我的绘图代码中的所有顶点属性绑定。或者有没有更好的方法来使用带或不带 VAO 的着色器?

编辑:

这是我的顶点着色器源代码:

#version 300 es
uniform lowp mat4 uProjectionMatrix;
in lowp vec4 a_position;
in lowp vec2 a_texCoord;
out lowp vec2 v_texCoord;
void main()

    gl_Position = uProjectionMatrix * a_position;
    v_texCoord = a_texCoord;

及片段着色器来源:

#version 300 es
precision mediump float;
uniform lowp sampler2D uTexture;
in lowp vec2 v_texCoord;
out lowp vec4 fragmentColor;
void main()

    fragmentColor = texture( uTexture, v_texCoord );

【问题讨论】:

"所以实际上不需要几何图形来绘制" 嗯...为什么不需要绘制数据?您是否打算通过使用gl_VertexID 来发明顶点数据?我并不是说这是错误的,但如果您的想法是您的顶点着色器不需要任何用户定义的输入,您应该在您的问题中这么说 "禁用我们的顶点数组对象" 这不是那个调用的作用。 "Disable our Vertex Buffer Object" 这也不是 that 调用的作用。 根据post,顶点可以只是着色器的一部分。 抱歉,我应该写 "Make our Vertex Buffer Object inactive" - 这就是我的意思 - 我会编辑帖子。 您更新的 cmets 仍然没有描述这些函数的实际作用。 【参考方案1】:

你可以选择两件事之一。

拥有一个没有附加缓冲区对象的 VAO 是完全合法的。但是,这并不意味着“创建一个缓冲区对象,但不要在其中放入任何东西”。这意味着不要将缓冲区对象附加到 VAO。您只需调用glGenVertexArrays 来生成顶点数组,您就完成了

没有呼叫glEnableVertexAttribArrays。没有电话到glVertexAttribPointer。如果您根本不使用顶点数组,则根本不应该进行这些调用。

拥有一个包含缓冲区对象的 VAO 也是完全合法的。这些工作正常。

你不能做的是创建一个没有分配的缓冲区对象,然后尝试将它用于顶点数据。如果您只删除 glBufferData,就会发生这种情况。

所以你必须选择道路的一侧或另一侧。您的 VAO 要么使用一个或多个缓冲区,要么不使用。如果它使用缓冲区,则这些缓冲区必须具有存储空间。如果没有,那么它不会在意。

【讨论】:

您说只需使用glGenVertexArrays,我就完成了。问题是这对我不起作用。除非我将它与 glBufferData 绑定,否则它会在 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4) 调用时崩溃。 @JeshuaLacock:你真的在使用 OpenGL ES 3.0 吗?您是否尝试在 VS 中使用输入变量? 是的,我使用的是 OpenGL ES 3.0。我正在尝试将顶点属性数组和制服与顶点着色器一起使用。 你说不给glEnableVertexAttribArraysglVertexAttribPointer打电话,但我在我的代码中表明了这一点。 "但我在我的代码中展示了这一点。" 我可以看到您的代码调用了这些函数。我的观点是,OpenGL ES 3.0 中的任何内容都不需要您设置任何属性数组才能进行渲染。所以这些电话不是你应该需要的。

以上是关于顶点着色器 VAO 是不是需要 VBO?的主要内容,如果未能解决你的问题,请参考以下文章

在 GLSL 着色器中访问 VBO/VAO 数据

OpenGL VAO VBO 着色器混淆

OpenGL - 如何理解 VAO 与 VBO 之间的关系

OpenGL 大项目、VAO-s 等

使用着色器和 VBO 绘制四边形

OpenGL - 告诉顶点着色器 VBO 已经改变