glDrawElements trouble

I’ve used glDrawElements (in OpenGL 3.1) before without problems. Now, however, it doesn’t want to draw anything, and I can’t figure out why. My render code looks like this:

void renderFunc(){
	frameCount++;
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	baseShader.bind();
	testProp.render();
	glUseProgram(0);
	glutSwapBuffers();
	glutPostRedisplay();
}

And the Prop class’s render function is:

void Prop::render(){
	glBindBuffer(GL_ARRAY_BUFFER, this->vboId);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->iboId);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vert), (GLvoid*)0);
	glEnableVertexAttribArray(0);

	//glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
	glDrawElements(GL_TRIANGLE_STRIP, 3, GL_UNSIGNED_BYTE, (GLvoid*)0);

	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
	glDisableVertexAttribArray(0);
}

The Prop’s initialization function is:

void Prop::init(){
	Vert baseVert1;
	Vert baseVert2;
	Vert baseVert3;
	baseVert1.pos = glm::vec3(1.0f, 0.0f, -4.0f);
	baseVert2.pos = glm::vec3(0.0f, 1.0f, -4.0f);
	baseVert3.pos = glm::vec3(-1.0f, 0.0f, -4.0f);
	Vert vertices[3] = {baseVert1, baseVert2, baseVert3};
	GLubyte indices[3] = {0, 1, 2};

	glGenBuffers(1, &this->vboId);
	glBindBuffer(GL_ARRAY_BUFFER, this->vboId);
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vert)*3, vertices, GL_STATIC_DRAW);

	glGenBuffers(1, &this->iboId);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->iboId);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte)*3, indices, GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}

And my vertex and fragment shaders:

//Vertex shader:
#version 130

in vec3 in_Position;
//in vec4 in_Color;
out vec4 ex_Color;
out float ex_Time;

uniform float time;
uniform mat4 PMatrix;
uniform mat4 VMatrix;
uniform mat4 MMatrix;

void main(void)
{
	ex_Time = time;
	//ex_Color = in_Color;
	ex_Color = vec4(0.0f, 1.0f, 0.0f, 1.0f);
	gl_Position = (PMatrix * VMatrix * MMatrix) * vec4(in_Position, 1.0f);
}


// Fragment shader:
#version 130

in vec4 ex_Color;
in float ex_Time;
out vec4 out_Color;

void main(void)
{
	ex_Time = 0.0f;
	out_Color = ex_Color;
}

I also create and bind a vertex array object early after the context’s initialization.
Now, the weird thing is that with glDrawElements, I get a blank screen, while with glDrawArrays I get a white (not a green) triangle which doesn’t seem to respond to the shaders. I’ve tried a whole bunch of stuff, from using glEnableClientState calls to moving the VAO binding inside the prop’s render function. I don’t really know what I’m doing; I can’t find anything wrong. Am I missing something blatantly obvious?

Are you using a VAO? You don’t need to bind the VBO and IBO while rendering. Just bind the VAO and call glDrawElements.
Also, try using unsigned short instead of unsigned byte for the indices.

I am using a VAO; I create it and bind it just after I initialize GLEW in the beginning. But I don’t need to bind the VBO and IBO? What if I have multiple VBOs and IBOs? If I don’t bind them, how does OpenGL know which one I mean? At any rate, commenting out the glBindBuffer calls in the render function gave me a solid white screen.

I guess when it comes down to it I’m not quite sure what the purpose of the VAO is. Someone explained it to me as storing information about how vertex data is stored in the VBOs, but then I thought you’d still need to bind whichever specific VBO you wanted to draw from.

There is a difference between “using a VAO” and “using VAOs”. The former means that you put these three lines in your initialization routine:


GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

And then you completely forget that VAOs even exist.

That’s not using VAOs. That’s satisfying the needs of core OpenGL. Using VAOs means having a VAO for each object you use, setting it up beforehand with glVertexAttribPointer calls and the like, then binding that VAO when you want to render that object (or set of objects).

The VAO sets the draw conditions so it binds the buffers and sets the vertex bindings.

When you create the VAO, use the following sequence

generate vao
bind vao
generate vbo (optional can be created earlier)
bind vbo
generate veb (opional can be created earlier)
bind veb (if used)
set vertex binding - after vbo bound
unbind vao (locks things in place any subsequent changes to vbo, veb or vertex binding will not affect this vao)

When you draw
bind vao

What if you do want to change the vertices stored in a VBO between render calls? If the VAO locks things in place, what’s the point of flags like GL_STATIC_DRAW or GL_DYNAMIC_DRAW?

The VAO doesn’t “locks things in place”. It stores the association between an attribute and a buffer object, as well as the format. The actual data contained by the buffer object is essentially orthogonal.

The VAO says, “attribute 0 comes from buffer object X, starting at byte Y, with format Z.” The exact byte data at offset Y is irrelevant, so long as buffer object X has at least Y bytes in it. Binding a VAO is functionally equivalent to making the glBindBuffer/glEnableVertexAttribArrays/glVertexAttribPointer calls yourself.

So I could replace

glBindBuffer(GL_ARRAY_BUFFER, this->vboId);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->iboId);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vert), (GLvoid*)0);
	glEnableVertexAttribArray(0);
 
	//glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
	glDrawElements(GL_TRIANGLE_STRIP, 3, GL_UNSIGNED_BYTE, (GLvoid*)0);
 
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
	glDisableVertexAttribArray(0);

with

glBindVertexArray(vaoId);
	glDrawElements(GL_TRIANGLE_STRIP, 3, GL_UNSIGNED_BYTE, (GLvoid*)0);
	glBindVertexArray(0);

Even if I unbound the Prop’s vbo and ibo after filling them with data?

Correct.

Alfonse it more correct - the only reason I recommended unbinding the vao is to stop potential errors caused by calling glBindBuffer/glVertexAttribPointer elsewhere in the code while the vao is still bound
because these calls will be applied to the current bound vao.

Also be aware that in this code



glBindVertexArray(vaoId);
glBindBuffer(GL_ARRAY_BUFFER, another_vbo);
 glDrawElements(GL_TRIANGLE_STRIP, 3, GL_UNSIGNED_BYTE, (GLvoid*)0); 
glBindVertexArray(0);

The data for the draw will come from vao binding not the newly bound vbo.

I apologize for how slow I am to pick this up, but doesn’t calling glBindBuffer right after glBindVertexArray change which vbo is associated with that vao? So wouldn’t the vertex positions and everything for the draw come from the new vbo you bound?

I guess where I’m getting tripped up is, how does the vao remember which vbo was bound while it itself was bound? That is,

glGenVertexArrays(1, &vaoId);
glGenBuffers(1, &vboId);

glBindVertexArray(vaoId);
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, other stuff);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);

glGenBuffers(1, &secondVboId);
glBindVertexArray(vaoId);
glBindBuffer(GL_ARRAY_BUFFER, secondVboId);
glBufferData(GL_ARRAY_BUFFER, other stuff);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);

// Here's where I'm confused:
glBindVertexArray(vaoId);
glDrawArrays(stuff);
// Which vbo is used to draw?  vboId or secondVboId?  How does that glDrawArrays call even work if GL_ARRAY_BUFFER is bound to 0?

Why doesn’t tonyo’s example code there change which vbo is associated with that vao?

Which vbo is used to draw?

Neither. As clearly stated in the OpenGL Wiki page, calling glBindBuffer with GL_ARRAY_BUFFER does nothing to the VAO. It’s the call to glVertexAttrib*Pointer that makes the association between a buffer object and the VAO.