Qt and OpenGL in Widget: Can't use glDrawArrays



  • Hello,

    I'm trying to build a tile based rogue-like/dungeon crawler that uses Qt for the general interface and OpenGL for displaying the models and landscape. Up till now I've been able to draw using the glBegin/glEnd method but not through the glDrawArrays or glDrawElements methods (seeing only a widget with the cleared color). I've looked through several examples but have yet to find one that works:

    https://steventaitinger.wordpress.com/2015/11/24/part-1-modern-opengl-using-qt-5-5-tutorial/
    http://www.ics.com/blog/qt-and-opengl-loading-3d-model-open-asset-import-library-assimp-part-2
    https://www.youtube.com/playlist?list=PLRwVmtr-pp06qT6ckboaOhnm9FxmzHpbY

    My current tactic is using a QWidget promoted to a custom widget (as seems to be the general method) though I'm open to any other alternatives.

    (Apologies for the messy code)
    oglwidget.h:

    #ifndef OGLWIDGET_H
    #define OGLWIDGET_H
    
    #include <QWidget>
    #include <QOpenGLWidget>
    #include <glm/glm.hpp>
    #include <QOpenGLFunctions>
    #include <vector>
    #include "entity.h"
    #include "general.h"
    #include <GL/glu.h>
    #include <GL/gl.h>
    
    #define VERTEXATTR 0
    #define INDEXATTR 1
    #define POSITIONATTR 2
    #define ROTATIONATTR 3
    
    using namespace std;
    
    
    class OGLWidget : public QOpenGLWidget
    {
        vector<GLuint>statics;  //-----buffer number for static models
        vector<GLuint>dynamics; //-----buffer number of dynamic models
    
        vector<GLfloat[1]>staticVerts;   //-----vertex data for static models
        vector<GLfloat[1]>dynamicVerts;  //-----vertex data for dynamic models
    
        vector<vector<GLfloat>*>staticPos;   //-----position data for static models
        vector<vector<GLfloat>*>dynamicPos;  //-----position data for dynamic models
    
        vector<GLfloat>staticRot;   //-----rotation data for static models
        vector<GLfloat>dynamicRot;  //-----rotation data for dynamic models
    
        vector<string>loadedPaths;  //-----name in folder of matching VBO
    
        //-----testing
        GLuint buf;
    
        //Method 2
        QOpenGLShaderProgram        shader;
        QOpenGLVertexArrayObject    VAO;
        QOpenGLBuffer               VBO, NBO;
        QOpenGLBuffer               IBP;
        QMatrix4x4                  projectionMatrix, viewMatrix;
        GLuint                      VBOi,NBOi,IBPi;
    
    public:
        OGLWidget(QWidget *parent = 0);
        ~OGLWidget();
        int loadModel(string path);
    private:
        void draw();
        QGLShaderProgram m_shader;
        QGLBuffer m_vertexBuffer;
    
    protected:
        void initializeGL();
        void resizeGL(int w, int h);
        void paintGL();
    };
    
    #endif // OGLWIDGET_H
    

    oglwidget.cpp:

    #include <GL/glew.h>
    #include <GL/glext.h>
    #include "oglwidget.h"
    #include "general.h"
    
    extern const char * vertexShader;
    extern const char * fragmentShader;
    
    OGLWidget::OGLWidget(QWidget *parent): QOpenGLWidget(parent)
    {
    
    }
    
    OGLWidget::~OGLWidget()
    {
    }
    
    void OGLWidget::initializeGL()
    {
        QOpenGLFunctions gl;
        gl.initializeOpenGLFunctions();
        glClearColor(0.05,0,0,1);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_LIGHT0);
        glEnable(GL_LIGHTING);
        glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
        glEnable(GL_COLOR_MATERIAL);
        shader.create();
        //-----Create Shader
        if (!shader.addShaderFromSourceCode( QOpenGLShader::Vertex, vertexShader)) {
            qDebug() << "Error in vertex shader:" << shader.log();
        }
        if (!shader.addShaderFromSourceCode( QOpenGLShader::Fragment, fragmentShader)) {
            qDebug() << "Error in fragment shader:" << shader.log();
        }
        if (!shader.link()) {
            qDebug() << "Error linking shader program:" << shader.log();
        }
        shader.bind();
    
        static const float vertexPositions[] = {
        -1.0f, 0.0f, 0.0f, //(x,y,z) bottom left
        1.0f, 0.0f, 0.0f, //bottom right
        0.0f, 1.0f, 0.0f //top middle
        };
    
        static const float vertexColors[] = {
        1.0f, .0f, .0f, //red (r,g,b) values for each vertex
        .0f, 1.0f, .0f, //green
        .0f, .0f, 1.0f //blue
        };
        VAO.create();
        VAO.bind(); //sets the Vertex Array Object current to the OpenGL context so we can write attributes to it
    
        /*QOpenGLBuffer m_vvbo(QOpenGLBuffer::VertexBuffer);
        m_vvbo.create();
        m_vvbo.setUsagePattern(QOpenGLBuffer::StaticDraw);
        m_vvbo.bind();
        m_vvbo.allocate(vertexPositions, 9 * sizeof(float));
        shader.enableAttributeArray("position"); //this labels an attribute &quot;position&quot;
        //that points to the memory slot from the last buffer allocate()
        //the position attribute is an input to our vertex shader
        shader.setAttributeBuffer("position", GL_FLOAT, 0, 3);
    
        QOpenGLBuffer m_vcbo(QOpenGLBuffer::VertexBuffer);
        m_vcbo.create();
        m_vcbo.setUsagePattern(QOpenGLBuffer::StaticDraw);
        m_vcbo.bind();
        m_vcbo.allocate(vertexColors, 9 * sizeof(float));
        shader.enableAttributeArray("color"); //this labels an attribute &quot;color&quot;
        //that points to the memory slot from the last buffer allocate()
        //the color attribute is an input to our vertex shader
        shader.setAttributeBuffer("color", GL_FLOAT, 0, 3);
    
        // Release (unbind) all
        m_vvbo.release();
        m_vcbo.release();
        VAO.release();
        shader.release();*/
        //VBO.allocate(vertexPositions,sizeof(vertexPositions));
        gl.glGenBuffers(1,&VBOi);
        gl.glBindBuffer(GL_VERTEX_ARRAY,VBOi);
        gl.glBufferData(GL_VERTEX_ARRAY,GL_FLOAT,vertexPositions,GL_STATIC_DRAW);
    }
    
    void OGLWidget::paintGL(){
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        // Render using our shader
        shader.bind();
        VAO.bind(); //sets
        glTranslatef(0.0f,0.0f,-3.0f);
        //glDrawArrays(GL_TRIANGLES, 0, 3);
        draw();
        VAO.release();
        shader.release();
    }
    
    
    void OGLWidget::resizeGL(int w, int h)
    {
        /*glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glViewport(0,0,w,h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glFrustum (-1.0, 1.0, -1.0, 1.0, 1.0, 1000.0);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();*/
    }
    int OGLWidget::loadModel(string path){
        //-----loads the model path if not already loaded, returns the index of the model
        //---check if already loaded
        for(int p=0;p<loadedPaths.size();p++){
            if(!loadedPaths[p].compare(path)){
                return p;
            }
        }
        loadedPaths.push_back(path);
        //-----continue with path loading
        Model m;
        m.loadModel(path);
        return loadedPaths.size()-1;
    }
    
    void OGLWidget::draw()
    {
        glMatrixMode(GL_MODELVIEW);
        cout<<"drawing..."<<endl;
        //glScaled(0.5,0.5,0.5);
        glBegin(GL_QUADS);
            glNormal3f(0,0,-1);
            glVertex3f(-1,-1,0);
            glVertex3f(-1,1,0);
            glVertex3f(1,1,0);
            glVertex3f(1,-1,0);
    
        glEnd();
        glBegin(GL_TRIANGLES);
            glNormal3f(0,-1,0.707);
            glVertex3f(-1,-1,0);
            glVertex3f(1,-1,0);
            glVertex3f(0,0,1.2);
        glEnd();
        glBegin(GL_TRIANGLES);
            glNormal3f(1,0, 0.707);
            glVertex3f(1,-1,0);
            glVertex3f(1,1,0);
            glVertex3f(0,0,1.2);
        glEnd();
        glBegin(GL_TRIANGLES);
            glNormal3f(0,1,0.707);
            glVertex3f(1,1,0);
            glVertex3f(-1,1,0);
            glVertex3f(0,0,1.2);
        glEnd();
        glBegin(GL_TRIANGLES);
            glNormal3f(-1,0,0.707);
            glVertex3f(-1,1,0);
            glVertex3f(-1,-1,0);
            glVertex3f(0,0,1.2);
        glEnd();
    }
    

    shader.cpp:

    //-----http://www.opentk.com/node/802
    const char * vertexShader=
            "#version 130\n"
            "in vec3 position;\n"
            "in vec3 normal;\n"
            "in vec2 texcoord;\n"
            "out vec3 out_normal;\n"
            "out vec2 out_texcoord;\n"
            "uniform mat4x4 modelviewproj;\n"
            "\n"
            "void main(){\n"
            "   gl_Position=modelviewproj*vec4(position,1.0);\n"
            "   out_normal=normal;\n"
            "   out_texcoord=texcoord;\n"
            "}\n"
            ;
    
    const char * fragmentShader=
            "#version 130\n"
            "in  vec3 out_normal;"
            "out vec4 out_color;\n"
            "const vec3 lightDir=vec3(-1,1,0);\n"
            "void main(){\n"
            "    vec3 nlightDir=normalize(lightDir);\n"
            "    float diffuse=clamp(dot(nlightDir,out_normal),0,1);\n"
            "    out_color=vec4(diffuse*vec3(1,1,1),1.0);\n"
            "}\n"
            ;
    

    This is my first time working with Qt and OpenGL but from digging I think (correct me if I'm wrong) the best approach is to use GL_STATIC_DRAW for the tiles and any other immovable objects and GL_DYNAMIC_DRAW for the player, items and monsters (things that will move and may leave line sight, therefore not being drawn). I'll also likely use indexing for the tiles models. Models are obj files so the Elements call should fit best and save memory on the GPU.

    I'm also wondering what the best method for drawing the multiple model files would be. Is it a different VBO or VAO for each unique model or a single VBO or VAO?

    To start off with, all I'm looking for is rendering a triangle, each with a different colored vertex to the screen. As it stands, this isn't even working but the code is a patchwork of different examples, I'm on my third rewrite and I don't know which way is up anymore.

    Any help with finding what I'm doing wrong or any other resources would be extremely helpful.

    OS: Debian Testing
    GPU: GeForce 610m
    Qt Version: 5.4 (pretty sure)
    OpenGL version: 3.0 (GLSL 1.30)
    Software: Qt Creator



  • Hi Clockwork

    I didnt read your code with much attention, but for starters if all you want is draw a triangle, check this tutorials I did https://bitbucket.org/joaodeusmorgado/opengltutorials
    I'm using vbos, to draw triangles. I'm using all OpenGL native calls, but should be pretty easy to convert to Qt OpenGL functions. I also recommend you this book wich is great, it has a lot of details that usually are ommited in other books http://alfonse.bitbucket.org/oldtut/index.html



Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.