glDrawElements - Drawing first few elements from a larger index and vertex array

Hi folks,

I’m setting up my vertex array object and I’m having troubles drawing anything on the screen.

I have checked with a simple triangle of 3 vertices and everything works as intended but I am now trying something more complex and it doesn’t work.

This is how my VAO is setup


	// Generate and bind VAO
	glGenVertexArrays(1, &m_vao);
	glBindVertexArray(m_vao);

	// Vertex Buffer
	GLuint vbuffer;
	glGenBuffers(1, &vbuffer);
	glBindBuffer(GL_ARRAY_BUFFER, vbuffer);	

	// Vertex Attributes

	// Position
	glEnableVertexAttribArray(0);		// layout(location = 0) [GLSL]
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexPositionTexture), (void*)BUFFER_OFFSET(0));
	
	// Texture UV
	glEnableVertexAttribArray(1);		// layout(location = 1) [GLSL]
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(VertexPositionTexture), (void*)BUFFER_OFFSET(12));

	// Index buffer
	GLuint ibuffer;
	glGenBuffers(1, &ibuffer);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuffer);

	// This only needs to be done once as the indices never change
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, maxIndices * sizeof(GLushort), &m_indices[0], GL_STATIC_DRAW);

	glBindVertexArray(0);

The indices are generated with this method, they account for the maximum number of quadrangles I can draw in one draw call.

	
        int numIndices = 0;

	for (int i = 0; i < maxQuadrangles; i++)
	{
		// CW Winding [0, 1, 2] [1, 3, 2]
		m_indices[numIndices++] = 0 + i;
        m_indices[numIndices++] = 1 + i;
        m_indices[numIndices++] = 2 + i;

        m_indices[numIndices++] = 1 + i;
        m_indices[numIndices++] = 3 + i;
        m_indices[numIndices++] = 2 + i;
	}

The array for vertices is also initialised to the maximum size possible for each draw call


std::array<VertexPositionTexture, maxVertices> m_vertices;

If I wish to draw a quadrangle then I copy the appropriate vertices for each quadrangle to draw


	// Copy the vertex data to the drawer's large vertices array
	std::array<VertexPositionTexture, 4> v = quadrangle.getVertices();
	std::copy(v.begin(), v.end(), m_vertices.begin() + (m_numQuadrangles * 4));
        m_numQuadrangles++;

Now for the part that doesn’t appear to work.


	// Bind VAO (restores all buffer bindings and attribute settings that were previously set up)
	glBindVertexArray(m_vao);

	// Update the vertex buffer with the new data (Copy data into the vertex buffer object)
	glBufferData(GL_ARRAY_BUFFER, maxVertices * sizeof(VertexPositionTexture), &m_vertices[0], GL_DYNAMIC_DRAW);

	glDrawElements(GL_TRIANGLES, m_numQuadrangles * 2, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));	

	// Unbind VAO
	glBindVertexArray(0);

	// Reset number of quadrangles
	m_numQuadrangles = 0;

What I am trying to do with the code above is copy the entire vertices array m_vertices to the vertex buffer.

Then depending on the number of quadrangles added for this batch I wish to only use part of the index and vertex buffers.

So m_numQuadrangles * 2 means I wish to use 2 triangles per quadrangle in the batch.

I have also tried


glDrawRangeElements(GL_TRIANGLES, 0, m_numQuadrangles * 6, m_numQuadrangles * 2, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));

BUFFER_OFFSET is defined as


#define BUFFER_OFFSET(i) ((char *)NULL + (i))

Why am I getting nothing drawn to the screen?

One potential problem: the buffer currently bound to GL_ARRAY_BUFFER isn’t part of VAO state - it’s context state, so you need to bind the buffer object before loading new data to it.

Like so?


	// Bind VAO (restores all buffer bindings and attribute settings that were previously set up)
	glBindVertexArray(m_vao);

	// Update the vertex buffer with the new data (Copy data into the vertex buffer object)
	glBindBuffer(GL_ARRAY_BUFFER, vbuffer);	
	glBufferData(GL_ARRAY_BUFFER, maxVertices * sizeof(VertexPositionTexture), &m_vertices[0], GL_DYNAMIC_DRAW);

	// 'count' parameter is the number of indices to use from the 'm_indices' array
	glDrawElements(GL_TRIANGLES, m_numQuadrangles * 6, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));	
	
	// Unbind VAO
	glBindVertexArray(0);

	// Reset number of quadrangles
	m_numQuadrangles = 0;

It works but I would like to make sure it is correct.

If the indices change at any point would I have to do the same for them too? In other words calling glBindBuffer for the index buffer each time the index data changes.

Thanks for your help :slight_smile:

[QUOTE=Spankenstein;1242141]Like so?


    // Bind VAO (restores all buffer bindings and attribute settings that were previously set up)
    glBindVertexArray(m_vao);

    // Update the vertex buffer with the new data (Copy data into the vertex buffer object)
    glBindBuffer(GL_ARRAY_BUFFER, vbuffer);    
    glBufferData(GL_ARRAY_BUFFER, maxVertices * sizeof(VertexPositionTexture), &m_vertices[0], GL_DYNAMIC_DRAW);

    // 'count' parameter is the number of indices to use from the 'm_indices' array
    glDrawElements(GL_TRIANGLES, m_numQuadrangles * 6, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));    
    
    // Unbind VAO
    glBindVertexArray(0);

    // Reset number of quadrangles
    m_numQuadrangles = 0;

It works but I would like to make sure it is correct.
[/QUOTE]
Yeah, that’s right.

OpenGL stores a reference to the buffer currently bound to GL_ARRAY_BUFFER when you make the glVertexAttribPointer/gl[***]Pointer call for the specified attribute, so you can have multiple buffer objects referenced by a single VAO. This means that the GL_ARRAY_BUFFER binding point is not needed for the draw call, so isn’t stored with the VAO. If you were to use multiple VBOs with dynamic data, you would need to upload data to each of these in turn.

If the indices change at any point would I have to do the same for them too? In other words calling glBindBuffer for the index buffer each time the index data changes.

Thanks for your help :slight_smile:

The GL_ELEMENT_ARRAY_BUFFER binding is a part of VAO state, so there’s no need to do the same for indices. If you look at the state tables in the OpenGL appendices, they have one table with “Vertex Array Object State” + one table with “Vertex Array Data (not in Vertex Array objects)” so if you’re unsure you can check which table a certain piece of state is in.

[QUOTE=Dan Bartlett;1242143]
If you look at the state tables in the OpenGL appendices, they have one table with “Vertex Array Object State” + one table with “Vertex Array Data (not in Vertex Array objects)” so if you’re unsure you can check which table a certain piece of state is in.[/QUOTE]

Hi Dan. Could you please post a link to the table you mentioned? I’m having trouble locating it.

It’s in the OpenGL specification. Searching for the words “Vertex Array Object State” will take you right there.

Thanks very much :slight_smile: