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-pp06qT6ckboaOhnm9FxmzHpbYMy 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 "position" //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 "color" //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