I have called glVertexAttribPointer without binding GL_ARRAY_BUFFER first:
If pointer is not NULL, a non-zero named buffer object must be bound to the GL_ARRAY_BUFFER target (see glBindBuffer), otherwise an error is generated.
I had trouble finding this bug because the error is GL_NO_ERROR after calling glVertexAttribPointer, but glGet(GL_ARRAY_BUFFER_BINDING) yields 0, so shouldn't this raise this error?
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.
This failure to yield an error happens when pointer is non-null.
Is this a bug in my OpenGL driver? Or am I looking for the error in the wrong way?
If you don't use a Vertex Buffer Object, then you've to use a compatibility profile context.
See OpenGL Context.
When you use glVertexAttribPointer then a named buffer object has to be bound to the ARRAY_BUFFER target and the last parameter is treated as a byte offset into this buffer.
In Legacy OpenGL (compatibility context) there is the option to bind a zero named buffer (0). Then the last parameter is a pointer to the buffer data.
But if you use a core profile context, then a named buffer object has to be bound in any case.
In the OpenGL 4.6 API Compatibility Profile Specification is specified that
An INVALID_OPERATION error is generated if a non-zero vertex array
object is bound, no buffer is bound to ARRAY_BUFFER, and pointer is not
NULL.
This means more or less, if you use a Vertex Array Object than you've to use Vertex Buffer Object, too. It is not allowed to bind a VAO, bind no VBO and to set a pointer.
Related
In order to upload an index buffer to the GPU, I have to call glBindBuffer with GL_ELEMENT_ARRAY_BUFFER then call glBufferData etc. on it.
However, for my engine design where everything is condensed into as few functions as possible this comes unhandy as using GL_ELEMENT_ARRAY_BUFFER with glBindBuffer changes VAO state and I would like to deal with the buffers without changing VAO state.
Can someone tell me if it is possible to allocate and upload an index buffer without touching VAO state? Or would I have to restore GL_ELEMENT_ARRAY_BUFFER state manually?
The following assumes that direct state access functionality is not available to you. If it is, you should just use that, so that you don't have to bind objects just to modify them in the first place.
There is no such thing as an "index buffer" in the OpenGL API. There are just buffer objects, which can be at any point used for any number of purposes (one of which is for vertex indices in a rendering command). No buffer is ever wedded to the notion of being specifically for index data.
Buffer binding points therefore are meaningful only to the degree that you use the functionality associated with those binding points. GL_ARRAY_BUFFER is meaningful only because glVertexAttribPointer calls look at the buffer bound to that binding point. But if you're not actually making a glVertexAttribPointer call, then GL_ARRAY_BUFFER is just a binding point, no different from any other.
For general buffer object management, you therefore can bind any buffer to any binding point. GL_UNIFORM_BUFFER, GL_COPY_READ_BUFFER, whatever. If you're not using the binding for its special purpose, then no binding is different from another (except GL_ELEMENT_ARRAY_BINDING which is part of VAO state).
So just bind the "index buffer" to some innocuous binding point (the indexed ones like GL_UNIFORM_BUFFER are particularly harmless, since they only get special functions when you use glBindBufferRange) and do your upload from there.
I created a VBO (Vertex Buffer Object) and VAO (Vertex Array Objects) and did this:
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(...);
glVertexAttribPointer(...);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
Can I delete the vbo after I did this and then draw with the vao assuming everything is in order?
I know that the buffers bind to the vao so I am assuming I can.
The problem is, if I delete the buffer on my computer (Intel graphics) it works great (everything is displayed correctly), but on my friend computer (AMD) there is nothing displayed.
What could be the problem with that?
(By the way, if I don't delete the buffers the program works both on my computer and on my friend's)
Yes, as per OpenGL 4.5, it is legal to delete it after you unbind the VAO.
2.6.1.2 Name Deletion and Object Deletion
If an object is deleted while it is currently in use by a GL context, its name
is immediately marked as unused, and some types of objects are automatically
unbound from binding points in the current context, as described in section 5.1.2.
However, the actual underlying object is not deleted until it is no longer in use.
This situation is discussed in more detail in section 5.1.3.
5.1.2 Automatic Unbinding of Deleted Objects
When a buffer, texture, or renderbuffer object is deleted, it is unbound from any
bind points it is bound to in the current context, and detached from any attachments
of container objects that are bound to the current context, as described for DeleteBuffers, DeleteTextures, and DeleteRenderbuffers. [...] Attachments to unbound container
objects, such as deletion of a buffer attached to a vertex array object which is not
bound to the context, are not affected and continue to act as references on the
deleted object, as described in the following section.
5.1.3 Deleted Object and Object Name Lifetimes
When a buffer, texture, sampler, renderbuffer, query, or sync object is deleted, its
name immediately becomes invalid (e.g. is marked unused), but the underlying
object will not be deleted until it is no longer in use.
A buffer, texture, sampler, or renderbuffer object is in use if any of the following conditions are satisfied:
the object is attached to any container object
[...]
So either it's an AMD driver bug, or the situation is not as you describe.
When creating a Buffer and setting its data, it is required to bind it first to a target and then populate the buffer bound to that target with some data:
GLenum target = GL_ARRAY_BUFFER;
glGenBuffers(1, &bufferId);
glBindBuffer(target, bufferId);
glBufferData(target, m_capacity*sizeof(value_type), m_data, GL_STREAM_DRAW);
glBindBuffer(target, 0);
But to my understanding it does not really matter if I a buffer that was populated on the GL_ARRAY_BUFFER target is later used on e.g. the GL_UNIFORM_BUFFER target. But if this is the case why do we need the target to populate the buffer and why is the signature of glBufferData not:
void glBufferData( GLint bufferId,
GLsizeiptr size,
const GLvoid * data,
GLenum usage);
Is that just a historical reason or because opengl is a statemachine or do I miss something and the target has an other purpose there.
This is a common OpenGL API thing - most of the work with OpenGL objects (textures, buffers, ...) is done via binding them to a specific target and then using this target to refer to currently bound object (more on this here). Unfortunatelly, I do not know the exact reason for this, but it seems to appear historical now - I've seen some proposed extension for direct object access via object id's (UPD: user ratchet freak says that it is direct_state_access extension, core in 4.5).
The documentation on glBindBuffer says that
When a buffer object is bound to a target, the previous binding for that target is automatically broken.
I'd suppose that changing a buffer's binding type and expecting the buffer's state to stay preserved is not a good idea.
UPDATE
From OpenGL wiki
The target defines how you intend to use this binding of the buffer object. When you're just creating and/or filling the buffer object with data, the target you use doesn't technically matter.
So, it seems that the target matters only on how you use the buffer, and you can safely bind it to any random type and fill it with data, but it still seems to be a bad practice.
To use glBufferData, you need some way of indicating the target of the data you are uploading. The target parameter (the first one), lets this call know the destination for your data. If your only aim is to upload the data and then unbind, as you said, it doesn't really matter which buffer binding you use. You are free to bind that buffer to any other binding at a later time.
However, it quite common to setup vertex attributes during GL_ARRAY_BUFFER data initialization time as well (with glVertexAttribPointer/glEnableVertexArray), which might be another reason to use GL_ARRAY_BUFFER binding over any other arbitrary binding. Also, if you intend to actually use the buffer data you are uploading in a subsequent draw call, and don't need to break the binding, it is more efficient to leave the binding in place.
The buffer currently bound to the GL_ELEMENT_ARRAY_BUFFER target in OpenGL is part of the state contained in a Vertex Array Object (VAO from here on). According to the OpenGL 4.4 core profile spec then, it would seem that attempting to change or access the GL_ELEMENT_ARRAY_BUFFER while no VAO is bound is an error:
10.4 Vertex Array Objects
... An INVALID_OPERATION error is generated by any commands which
modify, draw from, or query vertex array state when no vertex array
is bound. This occurs in the initial GL state, and may occur as a
result of BindVertexArray or a side effect of DeleteVertexArrays.
This is supported by the OpenGL wiki's Buffer Object page:
GL_ELEMENT_ARRAY_BUFFER
All rendering functions of the form gl*Draw*Elements* will use the pointer
field as a byte offset from the beginning of the buffer object bound to this
target. The indices used for indexed rendering will be taken from the buffer
object. Note that this binding target is part of a Vertex Array Objects state,
so a VAO must be bound before binding a buffer here.
Now, it would be nice if this were not the case. It would make it easy to create and manage index buffers separately from any particular VAO. But if just binding a buffer to GL_ELEMENT_ARRAY_BUFFER is verboten when there's no VAO bound, the only alternative is for the class representing an index buffer to bind a dummy VAO when they are created/updated/etc.
Nicol Bolas' excellent OpenGL tutorial says that this type of use is in fact valid:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER): Calling this without a VAO bound will not fail.
This seems to contradict the standard and opengl.org wiki. Is there something in the standard supporting this that I've missed, or is this only referring to compatibility profile contexts where using a VAO is not required?
If you have an AMD or NV GPU you can always use the EXT_direct_state_access extension to manipulate a buffer object without binding it (this is purely a driver feature and does not require any special class of hardware). Sadly, Intel, Mesa and Apple have not bothered to implement this extension despite its 5 year existence -- lazy slackers.
Have a look at the following functions, they will make what you are describing a lot easier:
glNamedBufferDataEXT (...)
glNamedBufferSubDataEXT (...)
glMapNamedBufferEXT (...)
glUnmapNamedBufferEXT (...)
Now, since adoption of DSA is sparse, you will probably have to write some fallback code for systems that do not support it. You can reproduce the functionality of DSA by writing functions with identical function signatures that use a dummy VAO to bind VBOs and IBOs for data manipulation on systems that do not support the extension. You will have to keep track of what VAO was bound before you use it, and restore it before said function returns to eliminate side-effects.
In a good engine you should shadow the VAO binding state rather than having to query it from GL. That is, instead of using glBindVertexArray (...) directly you implement a system that wraps that call and therefore always knows what VAO is bound to a particular context. In the end, this makes emulating DSA functionality where driver support does not exist a lot more efficient. If you attempt something like this, you need to be aware that glDelete (...) functions implicitly unbind (by binding 0) the object being deleted if it is bound in the current context.
But if just binding a buffer to GL_ELEMENT_ARRAY_BUFFER is verboten when there's no VAO bound, the only alternative is for the class representing an index buffer to bind a dummy VAO when they are created/updated/etc.
New reply to an old question, but a simple way to work with an index buffer without requiring a VAO (or interfering with the currently bound VAO) is to bind the buffer to a target other than GL_ELEMENT_ARRAY_BUFFER.
For example, instead of this:
glBindVertexArray(vaoID); // ...Do I even have a VAO yet?
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID); // <- Alters VAO state!
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, ...);
-- one might write this instead:
glBindBuffer(GL_COPY_WRITE_BUFFER, indexBufferID);
glBufferSubData(GL_COPY_WRITE_BUFFER, ...);
(Here I arbitrarily used GL_COPY_WRITE_BUFFER, which exists to provide a temporary target to make copying between buffers easier, but most other targets would be fine as well.)
I'm reading along in this tutorial and i get down towards the end in how to use Vertex Buffers and i see that the vertex buffer which I generated and called glBindBuffer on once already i have to bind a second time:
glBindBuffer(GL_ARRAY_BUFFER, vbo_triangle);
I'm still very new to openGL (like 3 days) so I'm trying to wrap my mind around how a lot of these things work. I spend most of my time on khronos or opengl.org reading about the commands, but I couldn't figure out why this one gets called twice. any hints? Thanks.
Does that particular example strictly need the second bind? No. OpenGL retains state, so if a buffer object is bound to a target, then it will remain bound until you bind something else to that target.
However, what happens if you insert code after the creation of the buffer that creates a second buffer? After all, you might want to have two objects. Or 10. Or however many you want; they don't have to share buffer objects.
Once you do that, your code breaks because the buffer that your code expects to be bound isn't actually bound. Therefore, unless you're good at managing state and really know what you're doing (and if you're still following tutorials, the answer is "no"), you should set whatever state you need to do what you intend.
Therefore, if you intend to draw from a particular buffer, you should bind it and set the appropriate state (the gl*Pointer calls).
You have to bind and unbind the buffer to copy to it from 'C' and draw with it from openGL.
Think of it as locking/unlocking between the program and the graphics.
So the sequence is
create
bind
stuff data
unbind
bind
display
unbind
Brief : The second one usualy unbinds the first one.
If no buffer object with name buffer exists, one is created with that name. When a buffer object is bound to a target, the previous binding for that target is automatically broken.
Buffer object names are unsigned integers. The value zero is reserved, but there is no default buffer object for each buffer object target. Instead, buffer set to zero effectively unbinds any buffer object previously bound, and restores client memory usage for that buffer object target (if supported for that target). Buffer object names and the corresponding buffer object contents are local to the shared object space of the current GL rendering context; two rendering contexts share buffer object names only if they explicitly enable sharing between contexts through the appropriate GL windows interfaces functions.
Reference : https://www.opengl.org/sdk/docs/man/html/glBindBuffer.xhtml