Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: glDrawElements trouble

  1. #1
    Intern Contributor
    Join Date
    Jun 2012
    Posts
    63

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

  2. #2
    Super Moderator OpenGL Guru
    Join Date
    Feb 2000
    Location
    Montreal, Canada
    Posts
    4,264
    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.
    ------------------------------
    Sig: http://glhlib.sourceforge.net
    an open source GLU replacement library. Much more modern than GLU.
    float matrix[16], inverse_matrix[16];
    glhLoadIdentityf2(matrix);
    glhTranslatef2(matrix, 0.0, 0.0, 5.0);
    glhRotateAboutXf2(matrix, angleInRadians);
    glhScalef2(matrix, 1.0, 1.0, -1.0);
    glhQuickInvertMatrixf2(matrix, inverse_matrix);
    glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
    glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);

  3. #3
    Intern Contributor
    Join Date
    Jun 2012
    Posts
    63
    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.

  4. #4
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,948
    There is a difference between "using a VAO" and "using VAOs". The former means that you put these three lines in your initialization routine:

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

  5. #5
    Senior Member OpenGL Pro
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    1,098
    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

  6. #6
    Intern Contributor
    Join Date
    Jun 2012
    Posts
    63
    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?

  7. #7
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,948
    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.

  8. #8
    Intern Contributor
    Join Date
    Jun 2012
    Posts
    63
    So I could replace
    Code :
    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
    Code :
    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?

  9. #9
    Senior Member OpenGL Pro
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    1,098
    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
    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.

  10. #10
    Intern Contributor
    Join Date
    Jun 2012
    Posts
    63
    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,
    Code :
    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?

Posting Permissions

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