Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 7 of 7

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

  1. #1
    Junior Member Newbie
    Join Date
    Sep 2012
    Posts
    9

    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

    Code :
    	// 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.

    Code :
            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

    Code :
    std::array<VertexPositionTexture, maxVertices> m_vertices;

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

    Code :
    	// 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.

    Code :
    	// 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

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

    BUFFER_OFFSET is defined as

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

    Why am I getting nothing drawn to the screen?

  2. #2
    Member Regular Contributor
    Join Date
    Aug 2008
    Posts
    393
    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.

  3. #3
    Junior Member Newbie
    Join Date
    Sep 2012
    Posts
    9
    Quote Originally Posted by Dan Bartlett View Post
    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?

    Code :
    	// 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

  4. #4
    Member Regular Contributor
    Join Date
    Aug 2008
    Posts
    393
    Quote Originally Posted by Spankenstein View Post
    Like so?

    Code :
        // 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.
    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
    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.

  5. #5
    Junior Member Newbie
    Join Date
    Sep 2012
    Posts
    9
    Quote Originally Posted by Dan Bartlett View Post
    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.
    Hi Dan. Could you please post a link to the table you mentioned? I'm having trouble locating it.

  6. #6
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,792
    It's in the OpenGL specification. Searching for the words "Vertex Array Object State" will take you right there.

  7. #7
    Junior Member Newbie
    Join Date
    Sep 2012
    Posts
    9
    Thanks very much

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •