我不想使用QOpenGLWidget,因为里面的OpenGL版本太旧了。我不明白从上下文中获取QOpenGLFunctions和直接初始化QOpenGLFunctions_4_5_Core有什么区别。我明白了,我没有从上下文中获取所有函数,也不明白为什么。那么,如何从上下文中获取所有函数呢?例如,glPolygonMode()在从上下文获得的QOpenGLFunctions和同样从上下文获得的QOpenGLExtraFunctions中不可访问。有人能解释一下如何在QT中使用纯粹的现代OpenGL吗?
这是我的代码: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();
}
1条答案
按热度按时间tsm1rwdh1#
试着让你的OpenGLWindow继承自
公共QOpenGL控件,受保护的QOpenGL函数
就像这样:
class OpenGLWindow : public QOpenGLWidget, protected QOpenGLFunctions_4_5_Core { ... };