glEnableVertexAttribArray

Hi,
I am trying to render using VAO, everything works fine but I just want to understand something.
When I initialize my opengl context using Qt I do also create a VAO this way :


    glGenVertexArrays(1, &vao);
	glGenBuffers(1, &vertexBuffer);
	glGenBuffers(1, &indexBuffer);

	glBindVertexArray(vao);
		glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
		glBufferData(GL_ARRAY_BUFFER, 3*vertices.size() * sizeof(GL_FLOAT), vertices.constData(), GL_STATIC_DRAW);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
		glEnableVertexAttribArray(0);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3*indices.size() * sizeof(GL_FLOAT), indices.constData(), GL_STATIC_DRAW);
	glBindVertexArray(0);

You see that glEnableVertexAttribArray(0); is already there.
However when I want to render (after compiling, linking my shader), I have to use this code in order to have something rendered at my screen.


	shaderProgram.bind();
		//UNIFORMS
		shaderProgram.setUniformValue("mvpMatrix", pMatrix * view * model);
		shaderProgram.setUniformValue("color", QColor(255,244,255));
		//ARRAYS
		//VERTEX ARRAY
		glBindVertexArray(vao);
			glEnableVertexAttribArray(0);
			glDrawElements(rendStyle, indices.size(), GL_UNSIGNED_INT, 0);
		glDisableVertexAttribArray(0);
	//RELEASE SHADER
	shaderProgram.release();

So there is a repetition of glEnableVertexAttribArray(0), If I remove this latter from the rendering part nothing is drawn at the screen.

Now, I don’t understand why I have to use glEnableVertexAttribArray(0) in the rendering part since it was already set up in the vao (initilization part).

Thanks.

do not call



glDisableVertexAttribArray(0); 

AFAIK this will change the state in the currently bound VAO.

[QUOTE=tonyo_au;1247149]do not call



glDisableVertexAttribArray(0); 

AFAIK this will change the state in the currently bound VAO.[/QUOTE]

What should I use then ?
I have to use it because otherwise it will not render at all.

His point is that you shouldn’t be calling either of the Enables or the Disables in your rendering function. Just bind the VAO and go.

If I do so I have nothing on the screen.

I am using Qt.
This is the content of my initiliaze function :

GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
qDebug() << glewGetErrorString(err);
}
qDebug() << “GLEW VERSION” << glewGetString(GLEW_VERSION);

qglClearColor(QColor(163,73,163)); // Choose clear Color
//Shader add, compile and link
shaderProgram.addShaderFromSourceFile(QGLShader::Vertex, “vertex.txt”);
shaderProgram.addShaderFromSourceFile(QGLShader::Fragment, “fragment.txt”);
shaderProgram.link();

for(int i=0 ; i < N; i++)
{
for(int j=0; j<N; j++)
{
QVector3D vertice = QVector3D(i-N/2,0,j-N/2);
vertices << vertice;
}
}

initIndices();
//VAO, VBO Part
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vertexBuffer);
glGenBuffers(1, &indexBuffer);

glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, 3vertices.size() * sizeof(GL_FLOAT), vertices.constData(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3
indices.size() * sizeof(GL_FLOAT), indices.constData(), GL_STATIC_DRAW);
glBindVertexArray(0);

And this is the render part

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
view.setToIdentity();
model.setToIdentity();
model.rotate(xr / 16.0, 1.0, 0.0, 0.0);
model.rotate(yr/ 16.0, 0.0, 1.0, 0.0);
model.rotate(zr / 16.0, 0.0, 0.0, 1.0);
view.translate(0.0, 0.0, distance);
//Bind Shader
shaderProgram.bind();
//UNIFORMS
shaderProgram.setUniformValue(“mvpMatrix”, pMatrix * view * model);
shaderProgram.setUniformValue(“color”, QColor(255,244,255));
//ARRAYS
//VERTEX ARRAY
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glDrawElements(rendStyle, indices.size(), GL_UNSIGNED_INT, 0);
glDisableVertexAttribArray(0);

//RELEASE SHADER
shaderProgram.release();

If I remove the blue line I have nothing on the screen… it just can’t work without it.

glDisableVertexAttribArray(0);

You need to remove this line also.

Oh, and why is it that, in your updated code, you removed the glEnableVertexAttribArray call from your initialize routine? That was correct; the enable state of an array is part of the VAO. You set it there, once, and you don’t have to set it again.

Thank you it is working fine !

However I just have one last question, in the render part should I unbind the VAO after calling glDrawElements ?

like this ? does this change anything ?

//VERTEX ARRAY
glBindVertexArray(vao);
glDrawElements(rendStyle, indices.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);

It may be cleaner to unbind after using the state set by binding the VAO. But technically there is no need for it unless you want to make different state current, i.e. bind another VBO and/or index buffer (IBO) and/or different attrib arrays and/or disable/enable a different set of arrays etc. However, since to do that you’d have to simply bind another correctly set up VAO, unbinding would simply incur wasted CPU time since you’d call glBindVertexArray() twice - the first time with 0 and the next time with another VAO handle. That’s one call wasted. Ok, in all fairness, if you only have 2 VAO’s and don’t switch multiple hundred or thousands times per frame, a few unnecessary calls won’t make much of a difference.

Before GL 3.2 core there was the option to not use vertex array objects for vertex attribute submission and other stuff. In that case, unbinding a VAO actually made sense, because like with texture objects and samplers, there could be valid, usable state when no state replacing object was bound. So, if you wanted to render something that wasn’t supposed to be sourced from stuff referenced by a VAO, you would unbind whatever VAO was currently bound, setup your stuff and render. However, since core GL 3.2+ mandates a VAO be active when issuing draw commands (and others) there is no way of not having a VAO bound anyway. Otherwise, you’ll have the GL generate INVALID_OPERATIONs all over the place. So, nowadays with core GL, you basically never need to turn off VAOs at all - just switch them.

In general, binding VAOs is costly, as can be seen using the timelines displayed by AMD’s or NVIDIA’s graphics profilers (on Windows … :frowning: ). So, many VAO changes incur a significant cost and it is probably wise to limit them as much as possible. That means you put as much data into a VBO and IBO referenced by a VAO as possible and draw as many objects from a single data store as possible. You can either do so by providing correctly shifted indices and simply indicate the offset into the index buffer with glDrawElements() or you can go the easy route and use glDrawElementsBaseVertex() and similar.

Notice how I always say a vertex array object references stuff. That’s because a vertex array object is just a container object containing only state, not data. The actual data is managed with the bound ARRAY_BUFFER’s and ELEMENT_ARRAY_BUFFERS’s data stores. This is good to know, although in single context setup it shouldn’t matter to you. As soon as you’re using multiple contexts, however, a VAO, like any other container object, is not shared between contexts and thus not usable from context B if it was generated and setup in context A.

HTH. If all that was too confusing, let us know.