如何创建QT窗口并在其中使用纯OpenGL内核配置文件?

5rgfhyps  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(139)

我不想使用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();
}
tsm1rwdh

tsm1rwdh1#

试着让你的OpenGLWindow继承自
公共QOpenGL控件,受保护的QOpenGL函数
就像这样:
class OpenGLWindow : public QOpenGLWidget, protected QOpenGLFunctions_4_5_Core { ... };

相关问题