#c #qt #opengl
#c #qt #opengl
Вопрос:
Я не хочу использовать QOpenGLWidget из-за старой версии OpenGL внутри. Я не понимаю, в чем разница между получением qopengglфункций из контекста и прямой инициализацией qopenglфункций_4_5_core. Я вижу, что я не получаю все функции из контекста, и не понимаю, почему. Итак, как получить из контекста все функции? Например, glPolygonMode() недоступен в qopenglфункциях, полученных из контекста, и в QOpenGLExtraFunctions, также полученных из контекста. Кто-нибудь может объяснить, как использовать чистый современный OpenGL с QT?
Это мой код: 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 coren"
"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"
"}";
/*static const char* fragmentShaderSource =
"#version 450 coren"
"out vec4 FragColor;n"
"in vec4 vertexColor;n"
"void main()n"
"{n"
"FragColor = vertexColor;n"
"}";*/
static const char* fragmentShaderSource =
"#version 450 coren"
"out vec4 FragColor;n"
"uniform vec4 ourColor;n"
"void main()n"
"{n"
"FragColor = ourColor;n"
"}";
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 amp;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() << "nt} ";
QTimer *timer = new QTimer(this);
connect(timer, amp;QTimer::timeout, this, this->render);
timer->start(500);
//*OPENGL TRINGLE INITIALIZATION*//
unsigned int VBO, vertexShader, fragmentShader, EBO;
this->m_funcs->glGenVertexArrays(1, amp;VAO);
this->m_funcs->glGenBuffers(1, amp;VBO);
this->m_funcs->glGenBuffers(1, amp;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, amp;vertexShaderSource, NULL);
this->m_funcs->glCompileShader(vertexShader);
int success;
char infoLog[512];
this->m_funcs->glGetShaderiv(vertexShader, GL_COMPILE_STATUS, amp;success);
if(!success)
{
this->m_funcs->glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
qDebug() << "ERROR::SHADER::VERTEX::COMPILATION_FAILEDn" <<
infoLog;
}
fragmentShader = this->m_funcs->glCreateShader(GL_FRAGMENT_SHADER);
this->m_funcs->glShaderSource(fragmentShader, 1, amp;fragmentShaderSource, NULL);
this->m_funcs->glCompileShader(fragmentShader);
this->m_funcs->glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, amp;success);
if(!success)
{
this->m_funcs->glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
qDebug() << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILEDn" <<
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, amp;success);
if(!success) {
this->m_funcs->glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
qDebug() << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILEDn" <<
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() << "nt} ";*/
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() << "nt} ";*/
if(this->m_funcs)
this->m_funcs->glViewport(0,
0,
this->geometry().width(),
this->geometry().height());
}
void OpenGLWindow::render()
{
timeval tim;
gettimeofday(amp;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();
}
Комментарии:
1. Я не уверен, что действительно понимаю проблему.
example code
Демонстрируется, как связать aQOpenGLWidget
с функциями из определенного профиля — наследовать от обоихQOpenGLWidget
иQOpenGLFunctions_4_5_Core
. Разве это не то, что вы ищете?2. Возможно, но в чем разница между получением функций из контекста и QOpenGLFunctions_4_5_Core ?
3. Я могу вручную установить контекст на версию ядра 4.5, но я не получаю все функции, объявленные в QOpenGLFunctions_4_5_Core
4. Кроме того, вам важно знать, я использую QT 6.2, в нем нет функции context->versionFunctions<T>() . Вы отправили документацию для QT 5.15
Ответ №1:
Попробуйте сделать так, чтобы ваш OpenGLWindow наследует от
общедоступный QOpenGLWidget, защищенные функции QOpenGL
вот так:
class OpenGLWindow : public QOpenGLWidget, protected QOpenGLFunctions_4_5_Core { ... };