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 8 of 8

Thread: glEnableVertexAttribArray

  1. #1
    Junior Member Newbie
    Join Date
    Jan 2013
    Location
    Paris
    Posts
    17

    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 :

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

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

  2. #2
    Senior Member OpenGL Pro
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    1,101
    do not call
    Code :
     
    glDisableVertexAttribArray(0);

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

  3. #3
    Junior Member Newbie
    Join Date
    Jan 2013
    Location
    Paris
    Posts
    17
    Quote Originally Posted by tonyo_au View Post
    do not call
    Code :
     
    glDisableVertexAttribArray(0);

    AFAIK this will change the state in the currently bound VAO.
    What should I use then ?
    I have to use it because otherwise it will not render at all.
    Last edited by holyll; 01-16-2013 at 07:51 AM.

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

  5. #5
    Junior Member Newbie
    Join Date
    Jan 2013
    Location
    Paris
    Posts
    17
    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::V ertex, "vertex.txt");
    shaderProgram.addShaderFromSourceFile(QGLShader::F ragment, "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, 3*vertices.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.

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

  7. #7
    Junior Member Newbie
    Join Date
    Jan 2013
    Location
    Paris
    Posts
    17
    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);

  8. #8
    Senior Member OpenGL Pro
    Join Date
    Apr 2010
    Location
    Germany
    Posts
    1,099
    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 ... ). 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.

Posting Permissions

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