#include "openglwindow.h" #include #include #include #include #include #include OpenGLWindow::OpenGLWindow(QWindow *parent) : QWindow(parent) , m_initialized(false) , m_update_pending(false) { this->setSurfaceType(QSurface::OpenGLSurface); } void OpenGLWindow::initialize() { glViewport(0, 0, width(), height()); m_program.addShaderFromSourceCode(QOpenGLShader::Vertex, "#version 330 core\n" "in vec4 coords;\n" "void main(void)\n" "{\n" " gl_Position = coords;\n" "}"); m_program.addShaderFromSourceCode(QOpenGLShader::Fragment, "#version 330 core\n" "out vec4 color;\n" "void main(void)\n" "{\n" " color = vec4(0.0f, 0.8f, 0.0f, 1.0f);\n" "}"); m_program.link(); m_program.bind(); static QOpenGLVertexArrayObject vao; vao.create(); vao.bind(); // The following code is needed for correct AttributeArray use: // Create buffer and bind it /* m_buffer = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer); m_buffer.create(); m_buffer.setUsagePattern(QOpenGLBuffer::StreamDraw); m_buffer.bind(); */ } void OpenGLWindow::render() { static const GLfloat colorBg[] = {1.0f, 0.0f, 0.0f, 1.0f}; glClearBufferfv(GL_COLOR, 0, colorBg); static GLfloat const triangleVertices[] = { 0.8f, 0.8f, 0.0f, 1.0f, 0.8f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f }; int vertexLocation = m_program.attributeLocation("coords"); // The following code is needed for correct AttributeArray use: /* m_buffer.allocate(triangleVertices, sizeof(triangleVertices)); // Allocate buffer and initialize with data glVertexAttribPointer(vertexLocation, 4, GL_FLOAT, GL_FALSE, 0, 0); // Set data format. Null pointer at the end because data was copied to buffer start */ // This crashes on some systems! m_program.setAttributeArray(vertexLocation, triangleVertices, 4); // Not standard conform! It's the same as: glVertexAttribPointer(vertexLocation, 4, GL_FLOAT, GL_FALSE, 0, triangleVertices); m_program.enableAttributeArray(vertexLocation); glDrawArrays(GL_TRIANGLES, 0, 3); m_program.disableAttributeArray(vertexLocation); } void OpenGLWindow::renderLater() { if (!m_update_pending) { m_update_pending = true; QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest)); } } void OpenGLWindow::renderNow() { // Initialize context if not set if (!m_initialized) { // Define version settings of OpenGL surface QSurfaceFormat format = this->requestedFormat(); format.setRenderableType(QSurfaceFormat::OpenGL); format.setVersion(3, 3); format.setProfile(QSurfaceFormat::CoreProfile); // Create OpenGL context m_context = new QOpenGLContext(this); m_context->setFormat(format); m_context->create(); m_context->makeCurrent(this); // Print version of created OpenGL context qDebug() << "OpenGL <" << m_context->format().majorVersion() << "." << m_context->format().minorVersion() << "> context successfuly created. Profile:" << m_context->format().profile(); // Resolve OpenGL functions and call initialize method bool resolved = initializeOpenGLFunctions(); qDebug() << "OpenGL functions successfully resolved:" << resolved; initialize(); m_initialized = true; } m_context->makeCurrent(this); // Render and swap buffers render(); m_context->swapBuffers(this); // Continue rendering renderLater(); } bool OpenGLWindow::event(QEvent *event) { switch (event->type()) { case QEvent::UpdateRequest: m_update_pending = false; renderNow(); return true; default: return QWindow::event(event); } } void OpenGLWindow::exposeEvent(QExposeEvent *event) { Q_UNUSED(event); if (isExposed()) renderNow(); } void OpenGLWindow::resizeEvent(QResizeEvent *event) { if(m_initialized) glViewport(0, 0, event->size().width(), event->size().height()); }