'How to create QT Window and use pure OpenGL core profile inside?

I don't want to use QOpenGLWidget, because of the old version of OpenGL inside. I don't understand what is the difference between getting QOpengGLFunctions from the context and directly initialization of QOpenGLFunctions_4_5_Core. I see, that I don't get all functions from the context, and don't understand why. So, how to get from the context all functions? For example, glPolygonMode() is inaccessible in QOpenGLFunctions gotten from the context and in QOpenGLExtraFunctions also gotten from the context. Could anybody explain how to use pure modern OpenGL with QT?

This is my code: openglwidget.cpp


#include "openglwindow.h"

#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <QOpenGLExtraFunctions>
#include <QOpenGLFunctions_4_5_Core>
#include <QDebug>
#include <QTimer>
#include <sys/time.h>

static const char* vertexShaderSource =
        "#version 450 core\n"
        "layout (location = 0) in vec3 aPos;\n"
        "out vec4 vertexColor;\n"
        "void main()\n"
        "{\n"
        "gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
        "vertexColor = vec4(0.5, 0.0, 0.0, 1.0);\n"
        "}\0";
/*static const char* fragmentShaderSource =
        "#version 450 core\n"
        "out vec4 FragColor;\n"
        "in vec4 vertexColor;\n"
        "void main()\n"
        "{\n"
        "FragColor = vertexColor;\n"
        "}\0";*/

static const char* fragmentShaderSource =
        "#version 450 core\n"
        "out vec4 FragColor;\n"
        "uniform vec4 ourColor;\n"
        "void main()\n"
        "{\n"
        "FragColor = ourColor;\n"
        "}\0";

void OpenGLWindow::GenTriangleBuffer()
{
    float vertices[] = {
                        -0.5f, -0.5f, 0.0f,
                        0.5f, -0.5f, 0.0f,
                        0.0f, 0.5f, 0.0f
                       };
    this->m_funcs->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
}

void OpenGLWindow::GenRectangleBuffer()
{
    float vertices[] = {
                        0.5f, 0.5f, 0.0f, // top right
                        0.5f, -0.5f, 0.0f, // bottom right
                        -0.5f, -0.5f, 0.0f, // bottom left
                        -0.5f, 0.5f, 0.0f // top left
                        };
    unsigned int indices[] = { // note that we start from 0!
                                0, 1, 3, // first triangle
                                1, 2, 3 // second triangle
                             };
    this->m_funcs->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    this->m_funcs->glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices,
                                GL_STATIC_DRAW);

}

OpenGLWindow::OpenGLWindow(QScreen* screen)
    : QWindow(screen)
{
    setSurfaceType(QWindow::OpenGLSurface);
    QSurfaceFormat format;
    format.setDepthBufferSize( 24 );
    format.setMajorVersion(4);
    format.setMinorVersion(5);
    format.setProfile(QSurfaceFormat::CoreProfile);
    format.setSamples(4);
    setFormat(format);
    create();

    // Create an OpenGL context
    this->m_context = new QOpenGLContext;
    this->m_context->setFormat(format);
    this->m_context->create();

    // Make the context current on this window
    this->m_context->makeCurrent(this);

    /*QSet<QByteArray> extensions = m_context->extensions();
    //std::sort(extensions);
    qDebug() << "Supported extensions (" << extensions.count() <<")";

    foreach (const QByteArray &extension, extensions) {
      qDebug() << "    " << extension;
    }*/

    // Obtain a functions object and resolve all entry points
    // m_funcs is declared as: QOpenGLFunctions_4_5_Core* m_funcs
    this->m_funcs = new QOpenGLFunctions_4_5_Core; /*m_context->functions();*/
    //this->m_extra_func = m_context->extraFunctions();
    this->m_funcs->initializeOpenGLFunctions();


    //set window geometry
    this->setGeometry(100, 100, 800, 600);
    //set OpenGL render size

    this->m_funcs->glViewport(this->geometry().x(),
                        this->geometry().y(),
                        this->geometry().width(),
                        this->geometry().height());

    qDebug() << "--- Window geometry: {\n" << this->geometry().x() << ", "
           << this->geometry().y() << ", " << this->geometry().width()
           << ", " << this->geometry().height() << "\n\t} ";
    QTimer *timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, this->render);
    timer->start(500);


    //*OPENGL TRINGLE INITIALIZATION*//
    unsigned int VBO, vertexShader, fragmentShader, EBO;
    this->m_funcs->glGenVertexArrays(1, &VAO);
    this->m_funcs->glGenBuffers(1, &VBO);
    this->m_funcs->glGenBuffers(1, &EBO);
    this->m_funcs->glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

    this->m_funcs->glBindVertexArray(VAO);
    this->m_funcs->glBindBuffer(GL_ARRAY_BUFFER, VBO);
    this->m_funcs->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    GenTriangleBuffer();

    vertexShader = this->m_funcs->glCreateShader(GL_VERTEX_SHADER);
    this->m_funcs->glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    this->m_funcs->glCompileShader(vertexShader);
    int success;
    char infoLog[512];
    this->m_funcs->glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if(!success)
    {
        this->m_funcs->glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        qDebug() << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" <<
        infoLog;
    }

    fragmentShader = this->m_funcs->glCreateShader(GL_FRAGMENT_SHADER);
    this->m_funcs->glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    this->m_funcs->glCompileShader(fragmentShader);
    this->m_funcs->glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if(!success)
    {
        this->m_funcs->glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        qDebug() << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" <<
        infoLog;
    }

    shaderProgram = this->m_funcs->glCreateProgram();
    this->m_funcs->glAttachShader(shaderProgram, vertexShader);
    this->m_funcs->glAttachShader(shaderProgram, fragmentShader);
    this->m_funcs->glLinkProgram(shaderProgram);
    this->m_funcs->glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if(!success) {
        this->m_funcs->glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        qDebug() << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" <<
        infoLog;
    }

    this->m_funcs->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float),
                                        (void*)0);
    this->m_funcs->glEnableVertexAttribArray(0);

    this->m_funcs->glDeleteShader(vertexShader);
    this->m_funcs->glDeleteShader(fragmentShader);
}


void OpenGLWindow::resizeEvent(QResizeEvent *)
{
    /*qDebug() << "--- Window RESIZED, new geometry: {\n" << this->geometry().x() << ", "
           << this->geometry().y() << ", " << this->geometry().width()
           << ", " << this->geometry().height() << "\n\t} ";*/
    if(this->m_funcs)
        this->m_funcs->glViewport(0,
                                  0,
                                  this->geometry().width(),
                                  this->geometry().height());
}

void OpenGLWindow::moveEvent(QMoveEvent *)
{
    /*qDebug() << "--- Window MOVED, new geometry: {\n" << this->geometry().x() << ", "
           << this->geometry().y() << ", " << this->geometry().width()
           << ", " << this->geometry().height() << "\n\t} ";*/
    if(this->m_funcs)
        this->m_funcs->glViewport(0,
                                  0,
                                  this->geometry().width(),
                                  this->geometry().height());

}



void OpenGLWindow::render()
{
    timeval tim;
    gettimeofday(&tim,NULL);
    float timeValue = tim.tv_usec;;
    float greenValue = (sin(timeValue) / 2.0f) + 0.5f;
    int vertexColorLocation = this->m_funcs->glGetUniformLocation(shaderProgram, "ourColor");


    this->m_funcs->glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    this->m_funcs->glClear(GL_COLOR_BUFFER_BIT);
    this->m_funcs->glUseProgram(shaderProgram);
    this->m_funcs->glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f);

    this->m_funcs->glBindVertexArray(VAO);
    this->m_funcs->glDrawArrays(GL_TRIANGLES, 0, 3);
    //this->m_funcs->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    this->m_context->swapBuffers(this);

}

void OpenGLWindow::exposeEvent(QExposeEvent *event)
{
    if (this->isExposed())
        this->render();
}

bool OpenGLWindow::event(QEvent *event)
{
    switch (event->type()) {
        case QEvent::UpdateRequest:
            this->render();
            return true;
        default:

            return QWindow::event(event);
        }
}


void OpenGLWindow::keyPressEvent(QKeyEvent *)
{

}

void OpenGLWindow::keyReleaseEvent(QKeyEvent *)
{

}


OpenGLWindow::~OpenGLWindow()
{

}

openglwidget.h

#ifndef GLWIDGET_H
#define GLWIDGET_H

#include <QWindow>

class QOpenGLFunctions;
class QOpenGLContext;
class QOpenGLExtraFunctions;
class QOpenGLFunctions_4_5_Core;

class OpenGLWindow : public QWindow
{
    Q_OBJECT
public:
    explicit OpenGLWindow(QScreen *screen = nullptr);
    ~OpenGLWindow();

public:
    virtual void render();

private:
    QOpenGLContext* m_context = nullptr;
    /*QOpenGLFunctions* m_funcs = nullptr;*/
    QOpenGLFunctions_4_5_Core* m_funcs = nullptr;
    QOpenGLExtraFunctions* m_extra_func = nullptr;
    unsigned int shaderProgram{}, VAO{};
    void GenTriangleBuffer();
    void GenRectangleBuffer();
protected:
    void resizeEvent(QResizeEvent *) override;
    void moveEvent(QMoveEvent *) override;

    void keyPressEvent(QKeyEvent *) override;
    void keyReleaseEvent(QKeyEvent *) override;

    void exposeEvent(QExposeEvent *event) override;
    bool event(QEvent *event) override;
};
#endif // GLWIDGET_H

main.cpp


#include <QApplication>
#include "openglwindow.h"
#include <QWindow>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    OpenGLWindow w(nullptr);
    w.show();
    return a.exec();
}



Solution 1:[1]

Try to make your OpenGLWindow inherits from

public QOpenGLWidget, protected QOpenGLFunctions

like this:

class OpenGLWindow : public QOpenGLWidget, protected QOpenGLFunctions_4_5_Core { ... };

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Patapoom