'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 |