更改 Qt OpenGL 窗口示例以使用 OpenGL 3.3

2024-05-15

我正在尝试更改 Qt OpenGL 示例以使用更现代的 opengl,版本 330 似乎合适。

所以我做了:

  • 在 main.cpp 上设置版本和配置文件
  • 设置着色器版本
  • 更改着色器以使用统一

它现在构建没有任何错误,但我只看到一个空白窗口。

我错了什么?也许有多种事情?

main.cpp

#include <QGuiApplication>

#include "openglwindow.h"

int main(int argc, char** argv)
{
    QSurfaceFormat fmt;
    fmt.setSamples(16);

    fmt.setDepthBufferSize(24);

    fmt.setVersion(3, 3);
    fmt.setProfile(QSurfaceFormat::CoreProfile);

    QGuiApplication app(argc, argv);
    OpenGLWindow window;

    window.setFormat(fmt);
    window.resize(640, 480);
    window.show();

    window.setAnimating(true);

    return app.exec();
}


openglwindow.h

#include <QWindow>
#include <QOpenGLFunctions>

class QPainter;
class QOpenGLContext;
class QOpenGLPaintDevice;

#include <QOpenGLShaderProgram>
#include <QKeyEvent>

class OpenGLWindow : public QWindow, protected QOpenGLFunctions
{
    Q_OBJECT

    bool m_animating = false;

    QOpenGLContext* m_context = nullptr;
    QOpenGLPaintDevice* m_device = nullptr;

    GLint m_posAttr = 0;
    GLint m_colAttr = 0;
    GLint m_matrixUniform = 0;

    QOpenGLShaderProgram* m_program = nullptr;
    int m_frame = 0;

public:
    explicit OpenGLWindow(QWindow* parent = nullptr);

    virtual void render();

    virtual void initialize();

    void setAnimating(bool animating);

public slots:
    void renderNow();

protected:
    bool event(QEvent* event) override;
    void exposeEvent(QExposeEvent*) override;

    void keyPressEvent(QKeyEvent* event) override
    {
        switch (event->key())
        {
        case Qt::Key_Escape:
            close();
            break;
        }
    }
};

openglwindow.cpp

#include "openglwindow.h"

#include <QOpenGLContext>
#include <QOpenGLPaintDevice>
#include <QPainter>

#include <QGuiApplication>
#include <QMatrix4x4>
#include <QScreen>
#include <QtMath>

const char* vertexShaderSource = R"(
    # version 330 core

    uniform vec4 posAttr;
    uniform vec4 colAttr;

    out vec4 col;

    uniform mat4 matrix;
    void main() {

       col = colAttr;

       gl_Position = matrix * posAttr;
    }
)";

const char* fragmentShaderSource = R"(
    # version 330 core

    out vec4 FragColor;

    in vec4 col;

    void main() {
       FragColor = col;
    }
)";

OpenGLWindow::OpenGLWindow(QWindow* parent)
    : QWindow(parent)
{
    setSurfaceType(QWindow::OpenGLSurface);
}

void OpenGLWindow::initialize()
{
    m_program = new QOpenGLShaderProgram(this);
    m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
    m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
    m_program->link();

    m_posAttr = m_program->uniformLocation("posAttr");

    m_colAttr = m_program->uniformLocation("colAttr");

    m_matrixUniform = m_program->uniformLocation("matrix");

}

void OpenGLWindow::render()
{
    const qreal retinaScale = devicePixelRatio();
    glViewport(0, 0, width() * retinaScale, height() * retinaScale);

    glClear(GL_COLOR_BUFFER_BIT);

    glClearColor(1.0, 1.0, 1.0, 1.0);

    m_program->bind();

    QMatrix4x4 matrix;
    matrix.perspective(60.0f, 4.0f / 3.0f, 0.1f, 100.0f);
    matrix.translate(0, 0, -2);
    matrix.rotate(100.0f * m_frame / screen()->refreshRate(), 0, 1, 0);

    m_program->setUniformValue(m_matrixUniform, matrix);

    static const GLfloat vertices[] = {
         0.0f,  0.707f,
        -0.5f, -0.5f,
         0.5f, -0.5f
    };

    static const GLfloat colors[] = {
        1.0f, 0.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
        0.0f, 0.0f, 1.0f
    };

    glVertexAttribPointer(m_posAttr, 2, GL_FLOAT, GL_FALSE, 0, vertices);
    glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, 0, colors);

    glEnableVertexAttribArray(m_posAttr);
    glEnableVertexAttribArray(m_colAttr);

    glDrawArrays(GL_TRIANGLES, 0, 3);

    glDisableVertexAttribArray(m_colAttr);
    glDisableVertexAttribArray(m_posAttr);

    m_program->release();

    ++m_frame;
}

bool OpenGLWindow::event(QEvent* event)
{
    switch (event->type()) {
    case QEvent::UpdateRequest:
        renderNow();
        return true;
    default:
        return QWindow::event(event);
    }
}

void OpenGLWindow::exposeEvent(QExposeEvent*)
{
    if (isExposed())
        renderNow();
}

void OpenGLWindow::renderNow()
{
    if (!isExposed())
        return;

    bool needsInitialize = false;

    if (!m_context) {
        m_context = new QOpenGLContext(this);
        m_context->setFormat(requestedFormat());
        m_context->create();

        needsInitialize = true;
    }

    m_context->makeCurrent(this);

    if (needsInitialize) {
        initializeOpenGLFunctions();
        initialize();
    }

    render();

    m_context->swapBuffers(this);

    if (m_animating)
        requestUpdate();
}

void OpenGLWindow::setAnimating(bool animating)
{
    m_animating = animating;
}

尝试了 J. M. Arnold 的建议,但结果是:

QOpenGLFunctions created with non-current context
QOpenGLShaderProgram::uniformLocation(posAttr): shader program is not linked
QOpenGLShaderProgram::uniformLocation(colAttr): shader program is not linked
QOpenGLShaderProgram::uniformLocation(matrix): shader program is not linked
ASSERT: "QOpenGLFunctions::isInitialized(d_ptr)" in file /Users/user/Qt/5.15.2/clang_64/lib/QtGui.framework/Headers/qopenglfunctions.h, line 1092

我检查了 OpenGL 版本

    unsigned int major = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR);
    unsigned int minor = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR);
    cout << "oepngl shader version: " << major << "." << minor << endl;

它打印

oepngl shader version: 4.1

我使用的是 M1 macOS。

在调试模式下运行我看到:

got fallback qt version 0x50f02
2022-12-04 20:11:35.615922+0800 openglwindow[61955:13089400] SecTaskLoadEntitlements failed error=22 cs_flags=20, pid=61955
2022-12-04 20:11:35.616020+0800 openglwindow[61955:13089400] SecTaskCopyDebugDescription: openglwindow[61955]/0#-1 LF=0
2022-12-04 20:11:37.052719+0800 openglwindow[61955:13089400] [] CurrentVBLDelta returned 0 for display 2 -- ignoring unreasonable value
2022-12-04 20:11:37.052744+0800 openglwindow[61955:13089400] [] [0x10c868c20] Bad CurrentVBLDelta for display 2 is zero. defaulting to 60Hz.
2022-12-04 20:11:37.053344+0800 openglwindow[61955:13089476] [] CurrentVBLDelta returned 0 for display 2 -- ignoring unreasonable value
2022-12-04 20:11:37.053354+0800 openglwindow[61955:13089476] [] [0x10c868c20] Bad CurrentVBLDelta for display 2 is zero. defaulting to 60Hz.
2022-12-04 20:11:37.194804+0800 openglwindow[61955:13089476] [] CurrentVBLDelta returned 0 for display 2 -- ignoring unreasonable value
2022-12-04 20:11:37.194832+0800 openglwindow[61955:13089476] [] [0x10c868c20] Bad CurrentVBLDelta for display 2 is zero. defaulting to 60Hz.
2022-12-04 20:11:37.212722+0800 openglwindow[61955:13089476] [] CurrentVBLDelta returned 0 for display 2 -- ignoring unreasonable value
2022-12-04 20:11:37.212748+0800 openglwindow[61955
:13089476] [] [0x10c868c20] Bad CurrentVBLDelta for display 2 is zero. defaulting to 60Hz.
2022-12-04 20:11:37.229195+0800 openglwindow[61955:13089476] [] CurrentVBLDelta returned 0 for display 2 -- ignoring unreasonable value
2022-12-04 20:11:37.229226+0800 openglwindow[61955:13089476] [] [0x10c868c20] Bad CurrentVBLDelta for display 2 is zero. defaulting to 60Hz.
2022-12-04 20:11:37.245219+0800 openglwindow[61955:13089476] [] CurrentVBLDelta returned 0 for display 2 -- ignoring unreasonable value
2022-12-04 20:11:37.245244+0800 openglwindow[61955:13089476] [] [0x10c868c20] Bad CurrentVBLDelta for display 2 is zero. defaulting to 60Hz.
2022-12-04 20:11:37.262730+0800 openglwindow[61955:13089476] [] CurrentVBLDelta returned 0 for display 2 -- ignoring unreasonable value
2022-12-04 20:11:37.262760+0800 openglwindow[61955:13089476] [] [0x10c868c20] Bad CurrentVBLDelta for display 2 is zero. defaulting to 60Hz.
2022-12-04 20:11:37.279399+0800 openglwindow[61955:13089476] [] CurrentVBLDelta returned 0 for display 2 -- ignoring unreasonable value
2022-12-04 20:11:37.279446+0800 openglwindow[61955:13089476] [] [0x10c868c20] Bad CurrentVBLDelta for display 2 is zero. defaulting to 60Hz.
2022-12-04 20:11:37.296006+0800 openglwindow[61955:13089476] [] CurrentVBLDelta returned 0 for display 2 -- ignoring unreasonable value
2022-12-04 20:11:37.296045+0800 openglwindow[61955:13089476] [] [0x10c868c20] Bad CurrentVBLDelta for display 2 is zero. defaulting to 60Hz.
2022-12-04 20:11:37.312713+0800 openglwindow[61955:13089476] [] CurrentVBLDelta returned 0 for display 2 -- ignoring unreasonable value
2022-12-04 20:11:37.312746+0800 openglwindow[61955:13089476] [] [0x10c868c20] Bad CurrentVBLDelta for display 2 is zero. defaulting to 60Hz.
2022-12-04 20:11:37.329405+0800 openglwindow[61955:13089476] [] CurrentVBLDelta returned 0 for display 2 -- ignoring unreasonable value
2022-12-04 20:11:37.329449+0800 openglwindow[61955

错误在你的内心eposeEvent:

void OpenGLWindow::exposeEvent(QExposeEvent*)
{
    if (isExposed())
        renderNow();
}

您忘记初始化 OpenGL 上下文:调用initialize(); and render();而不是你的renderNow();!

这应该是working最后:

void OpenGLWindow::exposeEvent(QExposeEvent*)
{
    if (isExposed()) {
        initialize();
        render();
    }
}

顺便一提:renderNow()初始化方法OpenGLWindow::render()但它不会初始化该方法OpenGLWindow::initialize() (-> OpenGLWindow::initialize()只会被调用一次OpenGLWindow首先创建对象,但是OpenGLWindow::render()每当renderNow()叫做)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

更改 Qt OpenGL 窗口示例以使用 OpenGL 3.3 的相关文章

随机推荐

  • 何时使用 =default 使析构函数默认?

    尽管对构造函数使用 default 对我来说很清楚 即强制编译器在其他构造函数存在时创建默认构造函数 但我仍然无法理解这两种类型的析构函数之间的区别 那些使用 default 的 那些没有显式定义并由编译器自动生成的 我唯一想到的是 gro
  • Watir 更改 Mozilla Firefox 首选项

    我正在使用 Watir 运行 Ruby 脚本来自动执行一些操作 我正在尝试自动将一些文件保存到某个目录 因此 在我的 Mozilla 设置中 我将默认下载目录设置为桌面并选择自动保存文件 然而 当我开始运行脚本时 这些更改并未反映出来 似乎
  • Vue Draggable - 如何仅替换所选项目以防止移动网格上的所有其他项目?

    这是一个要测试的示例 https codesandbox io s j4vn761455 file src App vue 112 116 https codesandbox io s j4vn761455 file src App vue
  • FileStream 构造函数和默认缓冲区大小

    我们有一个使用 NET 4 用 C 编写的日志记录类 我想添加一个构造函数参数 该参数可以选择设置文件选项 WriteThrough http msdn microsoft com en us library system io fileo
  • SVG 中三角形的圆角

    我正在尝试制作一个具有圆角的三角形 三角形将如下所示 左下角是唯一看起来相当容易制作的角 主要是因为这是一个 90 度的 转弯 该转弯是使用QSVG 中的命令具有以下参数 Q x y height x y height RADIUS从我正在
  • 带有 backstack Resume 的嵌套片段

    在我的应用程序中有几个fragments in an activity我正在维护一个backStack对于这些fragment 一切都很好 但其中有一个嵌套的片段 当我把它放入backStack然后再次按后退按钮恢复 该片段看起来与先前的内
  • 如何在 Elixir 中截断字符串?

    我正在使用长生不老药的鼻涕虫 想法是 我有一个字符串 a zA Z0 9 用连字符分隔的单词 喜欢 string another long string to be truncated and much text here 我想确保最大字符
  • 使用 Enumerable.OfType() 或 LINQ 查找特定类型的所有子控件

    Existed MyControl1 Controls OfType
  • 在 VBA 中循环合并单元格

    是否可以循环遍历合并的单元格vba questions tagged vba 我的范围内有 6 个合并单元格B4 B40 我只需要这 6 个单元格中的值 6 次迭代 上面的答案看起来已经让你排序了 如果您不知道合并的单元格在哪里 那么您可以
  • 拖放在浏览器堆栈中的 safari 浏览器中未触发

    使用的代码 第一次迭代 line1 Functions highlightelement vertical slider highlights the given xpath value line2 browser actions drag
  • Java Applet 中的 Apache FOP - 未找到数据的 ImagePreloader

    我正在研究成熟商业产品中的一个问题 简而言之 我们使用 Apache POI 库的一部分来读取 Word DOC 或 DOCX 文件 并将其转换为 XSL FO 以便我们可以进行标记替换 然后 我们使用嵌入到 Java 程序中的 FOP 将
  • 如何在 javascript 或 jquery 中按尺寸对图像进行排序

    如何在 JavaScript 或 jQuery 中按尺寸对图像进行排序 我的代码如下 var imgsrc if document images length lt 1 alert No images to open return for
  • 在网络上编写数学方程的最佳方法是什么?

    Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案或互动 我正在开发一个与数学相关的网页 并正在寻找一种将数学方程轻松写入网页的解决方案 目前我可以使用
  • 有人可以推荐一个免费的 xslt 工具吗? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 为什么在创建矩阵类时使用向量不好?

    对于我的矩阵类 我做了 template
  • 如何转义角度 HttpParams?

    在 Angular 服务中 我使用 HttpParams 将字符串发送到服务 get phone string Observable
  • 如何在 Visual Studio for Mac 上开发 Windows 应用程序

    我最近购买了一台iMac 以便在更好的环境中在Visual Studio for Mac上开发我的应用程序 Windows上有很多问题 但是在Visual Studio for mac上 没有UWP项目 据了解 我必须创建一个新的 NET
  • Android应用主题更换流畅

    我正在开发一个提供白天和夜间主题的项目 我正在更改主题 夜间主题 AppCompatDelegate setDefaultNightMode AppCompatDelegate MODE NIGHT YES 日主题 AppCompatDel
  • Paramiko SSHException 通道已关闭

    我一直在使用 Paramiko 在 Linux Windows 机器上发送命令 它可以很好地在 Ubuntu 机器上远程执行测试 但是 它不适用于 Windows 7 主机 以下是我收到的错误 def unit for event self
  • 更改 Qt OpenGL 窗口示例以使用 OpenGL 3.3

    我正在尝试更改 Qt OpenGL 示例以使用更现代的 opengl 版本 330 似乎合适 所以我做了 在 main cpp 上设置版本和配置文件 设置着色器版本 更改着色器以使用统一 它现在构建没有任何错误 但我只看到一个空白窗口 我错