3
$\begingroup$

I have a very simple OpenGL program where the positions are embedded in the GLSL code. The vertex shader looks like this:

#version 440 core

uniform float offsetX;
uniform float offsetY;

out VS_OUT
{
  vec2 tc;
} vs_out;

void main()
{
  const vec2[4] position = vec2[4](vec2(-0.5, -0.5),
                                   vec2(0.5, -0.5),
                                   vec2(-0.5, 0.5),
                                   vec2(0.5, 0.5));

  vs_out.tc = position[gl_VertexID].xy + vec2(0.5);
  vec2 pos = position[gl_VertexID].xy + vec2(offsetX, offsetY);
  gl_Position = vec4(pos, 0.0, 1.0);
}

To run this, to me it seems like I should basically be able to just be able to call glDrawArrays from my application.

However, this is not the case. I my application I have the following code (reused from an earlier example):

// Create buffer
glCreateBuffers(1, &buffer);
glNamedBufferStorage(buffer, sizeof(vertices), vertices, bufferFlags);

// Create vao
glCreateVertexArrays(1, &vao);

// Enable attributes
glEnableVertexArrayAttrib(vao, positionIndex);
glEnableVertexArrayAttrib(vao, texCoordIndex);

// Set up formats for attributes
glVertexArrayAttribFormat(vao, positionIndex, positionSize, GL_FLOAT, GL_FALSE, firstElementOffset);
glVertexArrayAttribFormat(vao, texCoordIndex, texCoordSize, GL_FLOAT, GL_FALSE, positionSize * sizeof(GLfloat));

// Make attributes use binding 0
glVertexArrayAttribBinding(vao, positionIndex, bufferBindingIndex);
glVertexArrayAttribBinding(vao, texCoordIndex, bufferBindingIndex);

// Bind "buffer" to vertex buffer binding point 0
glVertexArrayVertexBuffer(vao, bufferBindingIndex, buffer, firstElementOffset, elementStride);

None of that actually seems necessary because my shaders are now responsible for generating the position and texture coordinates. However, if I comment out the call to glVertexArrayVertexBuffer my program crashes.

Am I required to have a buffer bound to binding point 0 (even if I do not use any of that buffer's data) before calling glDraw*?

$\endgroup$
3
$\begingroup$

There is nothing in the OpenGL specification that requires you to have enabled attribute arrays in the bound VAO when you render. All of the user-defined vertex attributes will have undefined values, but since you're not reading any of them, that won't be a problem.

What may be a problem is driver bugs. Rendering with an empty VAO is not exactly the most common thing in the world, so it's possible that some drivers won't do the right thing. But the implementation should allow this.

However, if I comment out the call to glVertexArrayVertexBuffer my program crashes.

Of course it does. You have to not enable the attribute array as well. If you have a vertex attribute enabled, it has to come from somewhere. So there must be a buffer behind it. If you don't want to put a buffer there, then you can't have an attribute array source its data from that buffer.

So while you are not required to have enabled attribute arrays, if you have enabled an array, you are required to provide a buffer for it. If you don't want to use vertex attributes, you have to not use vertex attributes.

$\endgroup$
  • $\begingroup$ Excellent answer. After commenting out all of the enabled attributes, I am able to call glDrawArrays with no buffer / enabled attributes. However, I can see that I do still need a VAO bound when I call glDrawArrays. Why is this? My current VAO has no attributes enabled at all so it seems like it wouldn't be necessary. $\endgroup$ – Startec Jul 23 '17 at 20:55
  • 2
    $\begingroup$ @Startec: Because that's the rule; you need a VAO bound for that state to exist. Even if the state is the empty default state, you still need vertex array state in order to render. $\endgroup$ – Nicol Bolas Jul 23 '17 at 21:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.