I need to add some 3D graphics to an existing Qt application. I'm using Qt 5.2, but I'm using the old QGL* classes, at least for the moment. To start, I just want to draw a single triangle.
I had things working, but then I tried to explicitly set the OpenGL version by calling QGLWidget::setFormat, and suddenly my triangle doesn't draw anymore. I commented out the line where I actually set the version, and it made no difference: calling QGLWidget::setFormat with the value returned by QGLWidget::format suddenly makes drawing not happen. What happened?
testGL.cpp:
#include <QApplication>
#include <QDialog>
#include <QVBoxLayout>
#include "GLWidget.h"
class GLDialog : public QDialog
{
public:
GLDialog()
{
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(new GLWidget);
}
};
int main(int argc, char **argv)
{
QApplication app(argc, argv);
GLDialog dlg;
dlg.resize(200,200);
dlg.show();
return app.exec();
}
GLWidget.h:
#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <QColor>
#include <QGLWidget>
#include <QVector>
#include <QVector3D>
class GLWidget : public QGLWidget
{
Q_OBJECT
public:
GLWidget(QWidget * = 0, const QGLWidget * = 0, Qt::WindowFlags = 0);
protected:
virtual void initializeGL();
virtual void paintGL();
virtual void resizeGL(int, int);
//virtual void mousePressEvent(QMouseEvent *);
//virtual void mouseMoveEvent(QMouseEvent *);
private:
QVector<QVector3D> _triangle;
QColor _backgroundColour;
QColor _triangleColour;
};
#endif
GLWidget.cpp:
#include <QtOpenGL>
#include <QGLContext>
#include <QGLFormat>
#include <QGLShader>
#include <QGLShaderProgram>
#include <QDebug>
#include "GLWidget.h"
GLWidget::GLWidget(QWidget *parent, const QGLWidget *shareWidget, Qt::WindowFlags f)
: QGLWidget(parent, shareWidget, f)
{
QGLFormat newFormat(format());
//newFormat.setVersion(3,3);
/* Comment out the following line and a triangle appears */
setFormat(newFormat);
}
void GLWidget::initializeGL()
{
_backgroundColour = Qt::black;
_triangleColour = Qt::white;
_triangle.push_back(QVector3D(-0.75, 0.75, 0));
_triangle.push_back(QVector3D(-0.75, -0.75, 0));
_triangle.push_back(QVector3D(0.75, -0.75, 0));
}
void GLWidget::paintGL()
{
qglClearColor(_backgroundColour);
glClear(GL_COLOR_BUFFER_BIT);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, _triangle.constData());
glDrawArrays(GL_TRIANGLES, 0, 3);
}
void GLWidget::resizeGL(int width, int height)
{
int side = qMin(width, height);
int hoffset = (int)((width - side) / 2.0 + 0.5);
int voffset = (int)((height - side) / 2.0 + 0.5);
glViewport(hoffset, voffset, side, side);
}
testGL.pro:
######################################################################
# Automatically generated by qmake (3.0) Fri Apr 18 16:09:15 2014
######################################################################
TEMPLATE = app
TARGET = testGL
INCLUDEPATH += .
CONFIG += qt warn_on debug
QT += opengl
# Input
HEADERS += GLWidget.h
SOURCES += GLWidget.cpp testGL.cpp
I'm a total beginner to OpenGL, so please excuse silliness in my code. Note that I'm not explicitly setting shaders. That was going to be my next step.
UPDATE:
I followed this advice and used the alternate QGLWidget constructor that takes a QGLFormat object. I get some interesting behaviour.
- If I just create a QGLFormat, but don't set its version, I get a triangle. The version requested is 2.0, but checking the version inside my GLWidget constructor reveals that it's 3.0.
- If I explicitly call QGLFormat::setVersion(3,0), I get version 3.3, and I don't get a triangle.
- If I explicitly call QGLFormat::setVersion(2,0), I get a triangle, and the version that's set is 3.0.
The new GLDialog code:
class GLDialog : public QDialog
{
public:
GLDialog()
{
QVBoxLayout *layout = new QVBoxLayout(this);
QGLFormat format;
/* Comment this line out or change to 2,0 to get a triangle */
format.setVersion(3,0);
layout->addWidget(new GLWidget(format,this));
}
};
Outputs this format string in the GLWidget constructor:
QGLFormat(options QFlags(0x1|0x2|0x4|0x8|0x20|0x80|0x400) , plane 0 , depthBufferSize 24 , accumBufferSize -1 , stencilBufferSize 8 , redBufferSize 8 , greenBufferSize 8 , blueBufferSize 8 , alphaBufferSize 8 , samples -1 , swapInterval -1 , majorVersion 3 , minorVersion 3 , profile 1 )
And if I comment out the line indicated:
QGLFormat(options QFlags(0x1|0x2|0x4|0x8|0x20|0x80|0x400) , plane 0 , depthBufferSize 24 , accumBufferSize -1 , stencilBufferSize 8 , redBufferSize 8 , greenBufferSize 8 , blueBufferSize 8 , alphaBufferSize 8 , samples -1 , swapInterval -1 , majorVersion 3 , minorVersion 0 , profile 0 )
And if I change the requested version to 2.0:
QGLFormat(options QFlags(0x1|0x2|0x4|0x8|0x20|0x80|0x400) , plane 0 , depthBufferSize 24 , accumBufferSize -1 , stencilBufferSize 8 , redBufferSize 8 , greenBufferSize 8 , blueBufferSize 8 , alphaBufferSize 8 , samples -1 , swapInterval -1 , majorVersion 3 , minorVersion 0 , profile 0 )
setFormat
is obsolete. Don't use it. Deal with the context directly. – Kuba hasn't forgotten Monica