Using VAOs/VBOs

Hi,

I have a problem using VBO’s and VAO’s. In the initializeGL-function I wan’t to calculate vertex-data of different objects and save the data for each object in one VBO. In the paintGL-function I then just wan’t to use glBindVertexArray and glDrawArrays to render all obejcts stored in the VAO. The problem is, that only ever the last generated VBO (via call of Triangle1/Triangle2 in initializeGL) is rendered.
I reduced my actual code to just draw two triangles, so that the mistakes should be easier to find.

In VertexCalculation, two triangles are generated with the methods Triangle1 and Triangle2 and at the end of each method, CreateVBO is called and should store the vertices.


//VertexCalculation.h
#include <QOpenGLExtraFunctions>
class VertexCalculation: protected QOpenGLExtraFunctions
{
    public:
        VertexCalculation();
        ~VertexCalculation();
        void Triangle1(void);
        void Triangle2(void);
    private:
        GLfloat vertices[18];
        void CreateVBO(int);
    protected:
        GLuint VAO[1];
        GLuint VBO[2];
        GLint colLoc;
        GLint posLoc;
};


//VertexCalculation.cpp
#include "vertexcalculation.h"

VertexCalculation::VertexCalculation()
{
}

VertexCalculation::~VertexCalculation()
{
    glDeleteVertexArrays(1, VAO);
    glDeleteBuffers(2, VBO);
}

void VertexCalculation::Triangle1(void)
{
//Vertex 1
/*///////////////////////*/
    vertices[0]=-0.8;
    vertices[1]=-0.8;
    vertices[2]=0;
    //color
    vertices[3]=0.9;
    vertices[4]=0;
    vertices[5]=0;
/*///////////////////////*/

//Vertex 2
/*///////////////////////*/
    vertices[6]=-0.9;
    vertices[7]=-0.5;
    vertices[8]=0;
    //color
    vertices[9]=0.9;
    vertices[10]=0;
    vertices[11]=0;
/*///////////////////////*/

//Vertex 3
/*///////////////////////*/
    vertices[12]=-0.7;
    vertices[13]=-0.5;
    vertices[14]=0;
    //color
    vertices[15]=0.9;
    vertices[16]=0;
    vertices[17]=0;
/*///////////////////////*/
    CreateVBO(0);
}

void VertexCalculation::Triangle2(void)
{
//Vertex 1
/*///////////////////////*/
    vertices[0]=0.3;
    vertices[1]=-0.3;
    vertices[2]=0;
    //color
    vertices[3]=0;
    vertices[4]=0;
    vertices[5]=0.9;
/*///////////////////////*/

//Vertex 2
/*///////////////////////*/
    vertices[6]=0.7;
    vertices[7]=-0.3;
    vertices[8]=0;
    //color
    vertices[9]=0;
    vertices[10]=0;
    vertices[11]=0.9;
/*///////////////////////*/

//Vertex 3
/*///////////////////////*/
    vertices[12]=0.5;
    vertices[13]=0.8;
    vertices[14]=0;
    //color
    vertices[15]=0;
    vertices[16]=0;
    vertices[17]=0.9;
/*///////////////////////*/
    CreateVBO(1);
}

void VertexCalculation::CreateVBO(int nr)
{
    glBindVertexArray(VAO[0]);
    glBindBuffer(GL_ARRAY_BUFFER, VBO[nr]);

    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(colLoc, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));
    glEnableVertexAttribArray(1);

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

Screen entails the shader and render functions.


//Screen.h
#include <QOpenGLWidget>
#include "vertexcalculation.h"
QT_FORWARD_DECLARE_CLASS(QOpenGLShaderProgram)
class Screen : public QOpenGLWidget, protected VertexCalculation
{
    Q_OBJECT
    public:
        explicit Screen(QWidget *parent = 0);
        ~Screen();
    private:    
        QOpenGLShaderProgram *shader;
        QColor clearColor;
    protected:
        virtual void initializeGL() Q_DECL_OVERRIDE;
        virtual void paintGL() Q_DECL_OVERRIDE;
};
#endif // SCREEN_H


//Screen.cpp
#include <QColor>
#include <QOpenGLShaderProgram>
#include "Screen.h"

Screen::Screen(QWidget *parent) :
    QOpenGLWidget(parent),
    shader(0),
    clearColor(Qt::gray)
{    
}

Screen::~Screen()
{
    delete shader;
}

//Shader
/*////////////////////////////////////////////////////////*/
const GLchar *vertexshader =
        "#version 140
"
        "attribute vec3 pos;
"
        "attribute vec3 col;
"
        "varying vec3 col1;
"
        "void main() {
"
        "   col1 = col;
"
        "   gl_Position = vec4(pos.x, pos.y, pos.z, 1.0f);
"
        "}
";//


const GLchar *fragmentshader =
        "#version 140
"
        "varying vec3 col1;
"
        "void main() {
"
        "   gl_FragColor = vec4(col1, 1.0);
"
        "}
";
/*////////////////////////////////////////////////////////*/

void Screen::initializeGL()
{
    initializeOpenGLFunctions();
    glClearColor(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), clearColor.alphaF());

    shader = new QOpenGLShaderProgram(this);
    shader->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexshader);
    shader->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentshader);
    shader->link();

    colLoc = shader->attributeLocation("col");
    posLoc = shader->attributeLocation("pos");
    shader->bind();

    glDeleteShader(*vertexshader);
    glDeleteShader(*fragmentshader);

    glGenVertexArrays(1, VAO);
    glGenBuffers(2, VBO);

    Triangle1();
    Triangle2();
}

void Screen::paintGL()
{
    glBindVertexArray(VAO[0]);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glBindVertexArray(0);
}

Hope that anybody here could help me, because I tried many things and read a lot of threads but couldn’t solve the problem.
Thanks

Is this your render function?


void Screen::paintGL()
{
    glBindVertexArray(VAO[0]);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glBindVertexArray(0);
}

If it is, you only draw 3 vertices when you call paintGL().

I think you might need rebind VBOs before you draw each triangles.

And you can see this post https://www.opengl.org/discussion_boards/showthread.php/183518-How-to-render-switch-between-multiple-VBOs

I already tried with 6 but it’s nearly the same problem. With glDrawArrays(GL_TRIANGLES, 0, 3); one triangle is drawn correct while glDrawArrays(GL_TRIANGLES, 0, 6); also draws this triangle kinda wrong.

CreateVBO() populates a VBO with vertex data than configures the VAO to source attribute data from that VBO. So each call to CreateVBO changes the VBO which the VAO references. Multiple calls will result in the VAO being configured by the last call.

If you want to draw multiple triangles in a single draw call, then the data for those triangles needs to be stored in a single set of VBOs (at most one VBO for each vertex attribute).