I'm trying to set up a QWindow with an depth buffer, and I can't seem to get it to work. I started with the QWindow OpenGL example, and simplified it heavily. I'm drawing two triangles: one with coloured vertices, one with white vertices. I draw the white triangle second, but with larger Z coordinates, so it should appear to be behind the coloured triangle if I turn on depth buffering.
glEnable(GL_DEPTH_TEST) didn't work. I requested a 24 bit depth buffer, and nothing happened. Printing the QWindow's format reveals that the depth buffer's size is 0. The output:
It doesn't seem like anyone else is asking this question, so I assume I'm doing something stupid (I'm an OpenGL beginner). How do I make depth buffering work?Quote:
format: QSurfaceFormat(version 2.0, options QFlags() , depthBufferSize 0 , redBufferSize 8 , greenBufferSize 8 , blueBufferSize 8 , alphaBufferSize 8 , stencilBufferSize 0 , samples -1 , swapBehavior 0 , profile 0 )
I've set up the same code with a QGLWidget, and had no trouble turning on depth buffering. I'm using Qt 5.2 on an Arch Linux system.
My code:
SphereWindow.h:
Code:
#include <QColor> #include <QEvent> #include <QExposeEvent> #include <QOpenGLContext> #include <QOpenGLFunctions> #include <QOpenGLPaintDevice> #include <QOpenGLShaderProgram> #include <QPainter> #include <QResizeEvent> #include <QSize> #include <QWindow> class SphereWindow : public QWindow, protected QOpenGLFunctions { Q_OBJECT public: SphereWindow(QWindow * = 0); virtual ~SphereWindow(); virtual void render(); virtual void initialize(); public slots: protected: private: bool _initialized; QOpenGLContext *_context; QOpenGLPaintDevice *_device; QOpenGLShaderProgram *_program; QColor _backgroundColour; GLuint _posAttr; GLuint _colAttr; };
SphereWindow.cpp:
Code:
#include <QCoreApplication> #include <QMatrix4x4> #include <QOpenGLShader> #include <QScreen> #include <QSurfaceFormat> #include <QDebug> #include "SphereWindow.h" SphereWindow::SphereWindow(QWindow *parent) : QWindow(parent), _initialized(0), _program(0), _backgroundColour(Qt::black) { setSurfaceType(QWindow::OpenGLSurface); create(); qDebug() << "format:" << format(); _context = new QOpenGLContext(this); _context->setFormat(requestedFormat()); _context->create(); } SphereWindow::~SphereWindow() { } { resizeViewport(event->size()); } { int width = size.width(); int height = size.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); } void SphereWindow::render() { if (! _initialized) initialize(); if (! isExposed()) return; glEnable(GL_DEPTH_TEST); _context->makeCurrent(this); glClearColor(_backgroundColour.redF(), _backgroundColour.greenF(), _backgroundColour.blueF(), 1.0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); _program->bind(); GLfloat vertices[] = { -0.75f, 0.75f, 0.0f, -0.75f, -0.75f, 0.0f, 0.75f, -0.75f, 0.0f, 0.75f, 0.75f, 0.5f, 0.75f, -0.75f, 0.5f, -0.75f, -0.75f, 0.5f, }; GLfloat colors[] = { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, }; glVertexAttribPointer(_posAttr, 3, GL_FLOAT, GL_FALSE, 0, vertices); glVertexAttribPointer(_colAttr, 3, GL_FLOAT, GL_FALSE, 0, colors); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glDrawArrays(GL_TRIANGLES, 0, 6); glDisableVertexAttribArray(1); glDisableVertexAttribArray(0); _program->release(); _context->swapBuffers(this); _context->doneCurrent(); } static const char *vertexShaderSource = "attribute highp vec4 posAttr;\n" "attribute lowp vec4 colAttr;\n" "varying lowp vec4 col;\n" "void main() {\n" " col = colAttr;\n" " gl_Position = posAttr;\n" "}\n"; static const char *fragmentShaderSource = "varying lowp vec4 col;\n" "void main() {\n" " gl_FragColor = col;\n" "}\n"; void SphereWindow::initialize() { _context->makeCurrent(this); _program = new QOpenGLShaderProgram(this); _program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource); _program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource); _program->link(); _program->bind(); _posAttr = _program->attributeLocation("posAttr"); _colAttr = _program->attributeLocation("colAttr"); _program->release(); initializeOpenGLFunctions(); }
testWindow.cpp:
Code:
#include <QApplication> #include <QDialog> #include <QLabel> #include <QResizeEvent> #include <QSurfaceFormat> #include <QWidget> #include <QWindow> #include <QVBoxLayout> #include "SphereWindow.h" { public: { QSurfaceFormat format; format.setSamples(16); format.setDepthBufferSize(24); window = new SphereWindow; window->setFormat(format); window->render(); layout->addWidget(glWidget); } ~GLDialog() { delete window; } protected: { window->resize(event->size()); window->render(); } private: SphereWindow *window; }; int main(int argc, char **argv) { dlg->resize(640,480); dlg->show(); return app.exec(); }
testwindow.pro:
Code:
###################################################################### # Automatically generated by qmake (3.0) Sat May 3 05:01:55 2014 ###################################################################### TEMPLATE = app TARGET = testqwindow INCLUDEPATH += . QT += widgets CONFIG += debug # Input HEADERS += SphereWindow.h SOURCES += SphereWindow.cpp testWindow.cpp
Added after 18 minutes:
I knew I was doing something stupid. I was setting the context's format in my SphereWindow constructor, but not setting the SphereWindow instance's format until after... so the context was ending up with no depth buffer. I moved the calls to QOpenGLContext::setFormat() and QOpenGLContext::create into my initialize function, like so:
Code:
SphereWindow::SphereWindow(QWindow *parent) : QWindow(parent), _initialized(0), _program(0), _backgroundColour(Qt::black) { setSurfaceType(QWindow::OpenGLSurface); create(); qDebug() << "format:" << format(); _context = new QOpenGLContext(this); /* Move these lines into initialize() */ // _context->setFormat(requestedFormat()); // _context->create(); } ... void SphereWindow::initialize() { _context->setFormat(requestedFormat()); _context->create(); _context->makeCurrent(this); _program = new QOpenGLShaderProgram(this); _program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource); _program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource); _program->link(); _program->bind(); _posAttr = _program->attributeLocation("posAttr"); _colAttr = _program->attributeLocation("colAttr"); _program->release(); initializeOpenGLFunctions(); }