VBO display nothing, but VAO yes

Started by
9 comments, last by Xycaleth 9 years, 5 months ago

Hi,

i want to display a triangle using OpenGL 3.3 and QT.

I have tried an example on the web which display a triangle using VBO + VAO + GLSL

it works.

But now, i want to modify the code to use only VBO+GLSL (no VAO)(i want to make it compatible with OpenGL ES for the future). But it displays nothing.

This is the code which works unsing VAO:


void MyGLWindow::InitVAO()
{
   const float vertexData[] = {
         // x    y     z    w
         0.0f, 0.5f, 0.0f, 1.0f,
         0.5f, -0.366f, 0.0f, 1.0f,
         -0.5f, -0.366f, 0.0f, 1.0f,

         // R    G     B    A
         1.0f, 0.0f, 0.0f, 1.0f,
         0.0f, 1.0f, 0.0f, 1.0f,
         0.0f, 0.0f, 1.0f, 1.0f,
     };

     // create Vertex Buffer Object
     glGenBuffers(1, &VB_Position);
     glBindBuffer(GL_ARRAY_BUFFER, VB_Position);
     glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
     glBindBuffer(GL_ARRAY_BUFFER, 0);

     // create Vertex Array Object
     glGenVertexArrays(1, &VAO);
     glBindVertexArray(VAO);

     glBindBuffer(GL_ARRAY_BUFFER, VB_Position);
     glEnableVertexAttribArray(0);
     glEnableVertexAttribArray(1);
     glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
     glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)48);

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

void MyGLWindow::RenderWithVAO()
{
    m_context->makeCurrent(this);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    glUseProgram(m_program->programId());

    glBindVertexArray(VAO);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glBindVertexArray(0);

    glUseProgram(0);
    m_context->swapBuffers(this);
}

This is my code which do not use VAO, just VBO. I don't know why it does not work.


void MyGLWindow::InitVBOSeveralArrays()
{
    float vertexPositionData[] = {
        // x    y     z    w
        0.0f, 0.5f, 0.0f, 1.0f,
        0.5f, -0.366f, 0.0f, 1.0f,
        -0.5f, -0.366f, 0.0f, 1.0f
    };
    float vertexColorData[] = {
        // R    G     B    A
        1.0f, 0.0f, 0.0f, 1.0f,
        0.0f, 1.0f, 0.0f, 1.0f,
        0.0f, 0.0f, 1.0f, 1.0f
    };
    int indexData[] = {
       0,1,2
    };

    glGenBuffers(1, &VB_Position); // create Vertex Buffer Object
    glBindBuffer(GL_ARRAY_BUFFER, VB_Position);  // bind it to the GL_ARRAY_BUFFER
    glBufferData(GL_ARRAY_BUFFER, 4*3*sizeof(float), vertexPositionData, GL_STATIC_DRAW); // copy data to GPU
    glBindBuffer(GL_ARRAY_BUFFER, 0);  // bind the GL_ARRAY_BUFFER to 0

    glGenBuffers(1, &VB_Color); // create Vertex Buffer Object
    glBindBuffer(GL_ARRAY_BUFFER, VB_Color);  // bind it to the GL_ARRAY_BUFFER
    glBufferData(GL_ARRAY_BUFFER, 4*3*sizeof(float), vertexColorData, GL_STATIC_DRAW); // copy data to GPU
    glBindBuffer(GL_ARRAY_BUFFER, 0);  // bind the GL_ARRAY_BUFFER to 0

    glGenBuffers( 1, &VB_Index );
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER_ARB, VB_Index );
    glBufferData( GL_ELEMENT_ARRAY_BUFFER_ARB, 3*sizeof(int), indexData, GL_STATIC_DRAW_ARB );
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void MyGLWindow::RenderWithVBOSeveralArrays()
{
    m_context->makeCurrent(this);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    glUseProgram(m_program->programId());
    GLuint positionIndex	= glGetAttribLocation(m_program->programId(), "position");
    GLuint colorIndex		= glGetAttribLocation(m_program->programId(), "color");

    // Vertices
    glBindBuffer(GL_ARRAY_BUFFER_ARB, VB_Position);
    glVertexAttribPointer(positionIndex, 4, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(positionIndex);

    // Color
    glBindBuffer(GL_ARRAY_BUFFER_ARB, VB_Color);
    glVertexAttribPointer(colorIndex, 4, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(colorIndex);

    // Indices
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, VB_Index);

    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr); // Draw

    glDisableVertexAttribArray(positionIndex);
    glDisableVertexAttribArray(colorIndex);

    glUseProgram(0);
    m_context->swapBuffers(this);

}

Do you have some ideas ?

I have attached a very simple source code of the project.

Thanks.

Advertisement

If my memory serves me right, vertex array objects are mandatory from version 3.3. It is an error to bind vertex buffer objects and set pointers and such without a bound vertex array object. However, nothing prevents you from binding a dummy-object at the beginning and then pretending you don't use vertex array objects.

i want to modify the code to use only VBO+GLSL (no VAO)(i want to make it compatible with OpenGL ES for the future).

OpenGL ES 2.0 and above support VAO, so I don't see any good reason to avoid them on the desktop either. Care to elaborate on your reasoning?

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

OpenGL ES do not seems to support glGenVertexArrays:

https://www.khronos.org/opengles/sdk/docs/man3/html/glGenVertexArrays.xhtml

This example do not seems to use Vertex Array:

http://qt-project.org/doc/qt-4.8/opengl-cube.html

Unless you ask Qt to create an explicit 3.3 context it will create a rather compatible context where you do not need a VAO. If you do so, my memory agrees with Brother Bob: it should not work at all without a VAO (although some driver versions did not always properly enforce that). If you used Qt 5 instead, they have prebuilt versions with GLES for desktop available (using ANGLE).

That aside, creating a single VAO and binding it before you do your first attempt at rendering should work. That should be a single #ifdef-block in the right spot.

i want to modify the code to use only VBO+GLSL (no VAO)(i want to make it compatible with OpenGL ES for the future).

OpenGL ES 2.0 and above support VAO, so I don't see any good reason to avoid them on the desktop either. Care to elaborate on your reasoning?

VAOs weren't introduced into ES until 3.0.

texel3d, I'm with Brother Bob on this. If you want minimal code changes. then for OpenGL, create a dummy VAO, for OpenGL ES don't do anything. The rest of your code can remain the same.

VAOs weren't introduced into ES until 3.0.

Yay, GL extensions. My driver is happily supporting VAO in a GLES 2.0 context - I assumed it was doing the expected thing, but I see not.

Does anyone maintain a database of extension support on mobile chipsets?

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

It woks without VAO now. I use

format.setProfile(QSurfaceFormat::CompatibilityProfile);

I think i can build an OpenGL ES program for desktop and the same for Android. I don't need to use OpenGL.

But my new question is:

How can i modify my code of my QWindow (not a QGLWidget) to support OpenGL ES for Android project ?

The same code above crash at execution for android project (executed on desktop). I have just added:

format.setRenderableType(QSurfaceFormat::OpenGLES);

Maybe i should start an another thread.

#ifdef ANDROID
   format.setRenderableType(QSurfaceFormat::OpenGLES);
#else
   format.setProfile(QSurfaceFormat::CompatibilityProfile);
#endif
Not sure if the ANDROID define actually exists but in general you can identify the used platform by the defines set by the compiler. You might have to research your relevant platforms first.

This topic is closed to new replies.

Advertisement