0
\$\begingroup\$

Let's say I am not using VAOs. I have an array of vertex positions in memory that I want to send to the shader. I do the following (assume I have enabled the corresponding vertex attrib arrays):

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertexDataAsFloats);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, textureData);
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 0, someOtherData);
glDrawArrays(...);

This works well and I see the mesh with proper textures. someOtherData is sent to the shader correctly as well. Now I decide to put the vertexDataAsFloats and textureData in VBOs:

BindVAO(1); // binds the VAO with a handle generated from glGenVertexArrays()
glBindBuffer(GL_ARRAY_BUFFER, vertexDataBufferObject);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, textureData);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
UnBindVAO();

Later, before drawing:

glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 0, someOtherData);
BindVAO(1);
glDrawArrays(...);
UnBindVAO();

Can I mix the calls to glVertexAttribPointer and VAO before the draw call, where someOtherData is not in a VBO? Currently, this approach is not working as I am not receiving valid data for someOtherData in the shader.

I realize that someOtherData should go in a VBO as well and bound with the VAO. There is some legacy code that I have to work with which does not use VBOs. In any case, I would like to know if the above is legal in OpenGL.

\$\endgroup\$
0
\$\begingroup\$

It would appear that mixing VAOs with glVertexAttribArray() calls where the latter does not use a VBO does not work and emits no OpenGL errors. This means that if you decide to use VAOs then all glVertexAttrbArray() calls must be made to a corresponding VBO.

\$\endgroup\$
0
\$\begingroup\$

The specification for GL_ARB_vertex_array_object is clear on this:

...client memory cannot be accessed through a non-zero vertex array object...

However, there is a workaround for you here. You can use use VAOs for everything else, but just bind VAO 0 and then issue the full set of glVertexAttribPointer calls (i.e referencing both buffer objects and client memory) for the legacy part of your code.

\$\endgroup\$
  • \$\begingroup\$ Seems as if it is allowed in Apple's VAO extension however: "This extension differs from GL_APPLE_vertex_array_object in that client memory cannot be accessed through a non-zero vertex array object." \$\endgroup\$ – bogglez Oct 8 '14 at 20:44
0
\$\begingroup\$

The gl*Pointer calls will store the currently bound buffer object and use it as the data source no matter what buffer object is bound during glDrawArrays and other draw calls.

So as long as you unbind the buffer object before you call glVertexAttribPointer it will interpret its source argument as an absolute address instead of an offset into a buffer object.

EDIT: apparently it used to be possible because the extension was based on the APPLE VAO extension, but isn't anymore. Refer to the revision history in https://www.opengl.org/registry/specs/ARB/vertex_array_object.txt

I guess nowadays you should really just use streaming with buffer objects in a double buffer setup.

\$\endgroup\$
  • \$\begingroup\$ Just so that I understood correctly, calling glVertexAttribPointer with an absolute address before binding a VAO and then doing a draw call should work? I am unable to get this to work so I wanted to be absolutely sure so that I look elsewhere in the code for a bug. \$\endgroup\$ – Samaursa Oct 7 '14 at 17:54
  • \$\begingroup\$ Hmm, I think I found your issue. There seems to be a difference between glVertexPointer and glVertexAttribPointer in this regard. The docs for glVertexAttribPointer say "GL_INVALID_OPERATION is generated if zero is bound to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL." Can you check for this error? AttribPointer was added later when shaders were introduced already. \$\endgroup\$ – bogglez Oct 7 '14 at 21:25
  • \$\begingroup\$ That's interesting. If I understand the doc correctly, I should get the GL_INVALID_OPERATION when using an absolute address for the pointer argument unless I have a buffer bound. In my case, I get the invalid operation error only if I bind a VAO before calling glVertexAttribPointer. The interesting thing is that if I don't use VBOs/VAOs at all and use glVertexAttribPointer with an absolute address, the attributes are transferred to the shader correctly. The only time when they don't is when I call glVertexAttribPointer and then bind a VAO and then make a draw call. \$\endgroup\$ – Samaursa Oct 7 '14 at 21:41
  • \$\begingroup\$ Apparently it used to be possible in the past to access client memory from VAOs, but it isn't anymore. This is probably because the ARB extension is based on the APPLE extension which allows this. In the changelog it states: "deleted obsolete INVALID_OPERATION on draw with client arrays since it's no longer possible to define a VAOs with client arrays. \$\endgroup\$ – bogglez Oct 8 '14 at 20:50

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.