c++ Qt + OpenGL,Qt文档中的示例不起作用

watbbzwu  于 2023-08-09  发布在  其他
关注(0)|答案(1)|浏览(133)

我正在尝试在我的教育项目中使用Qt和OpenGL。我做的第一步-我在Qt文档中找到了openglwindow示例,并复制了它以了解这些东西应该如何工作。这个例子:example with explanations和所有源代码:repository
我用与原始cmake有点不同的cmake构建了这个,因为(正如我所读到的)我的qt版本与doc中的qt版本不同。下面是我的CMakeLists.txt:

cmake_minimum_required(VERSION 3.16)                                                
project(openglwindow LANGUAGES CXX)                                                 
                                                                                    
set(CMAKE_AUTOMOC ON)                                                               
set(CMAKE_AUTORCC ON)                                                               
                                                                                    
set(CMAKE_CXX_STANDARD 17)                                                          
set(CMAKE_CXX_STANDARD_REQUIRED ON)                                                 
                                                                                    
if(NOT DEFINED INSTALL_EXAMPLESDIR)                                                 
  set(INSTALL_EXAMPLESDIR "src")                                                    
endif()                                                                             
                                                                                    
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/test_view/build")                    
                                                                                    
find_package(Qt6 REQUIRED COMPONENTS Core Gui OpenGL)                               
                                                                                    
# qt_standard_project_setup()                                                       
                                                                                    
qt_add_executable(openglwindow                                                      
    main.cpp                                                                        
    openglwindow.cpp openglwindow.h                                                 
)                                                                                   
                                                                                    
set_target_properties(openglwindow PROPERTIES                                       
    WIN32_EXECUTABLE TRUE                                                           
    MACOSX_BUNDLE TRUE                                                              
)                                                                                   
                                                                                    
target_link_libraries(openglwindow PRIVATE                                          
    Qt6::Core                                                                       
    Qt6::Gui                                                                        
    Qt6::OpenGL                                                                     
)                                                                                   
                                                                                    
install(TARGETS openglwindow                                                        
    RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"                                     
    BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"                                      
    LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"                                     
)

字符串
main.cpp:

#include "openglwindow.h"

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

class TriangleWindow : public OpenGLWindow
{
public:
    using OpenGLWindow::OpenGLWindow;

    void initialize() override;
    void render() override;

private:
    GLint m_posAttr = 0;
    GLint m_colAttr = 0;
    GLint m_matrixUniform = 0;

    QOpenGLShaderProgram *m_program = nullptr;
    int m_frame = 0;
};

int main(int argc, char **argv)
{
    QGuiApplication app(argc, argv);

    QSurfaceFormat format;
    format.setSamples(16);

    TriangleWindow window;
    window.setFormat(format);
    window.resize(640, 480);
    window.show();

    window.setAnimating(true);

    return app.exec();
}

static const char *vertexShaderSource =
    "attribute highp vec4 posAttr;\n"
    "attribute lowp vec4 colAttr;\n"
    "varying lowp vec4 col;\n"
    "uniform highp mat4 matrix;\n"
    "void main() {\n"
    "   col = colAttr;\n"
    "   gl_Position = matrix * posAttr;\n"
    "}\n";

static const char *fragmentShaderSource =
    "varying lowp vec4 col;\n"
    "void main() {\n"
    "   gl_FragColor = col;\n"
    "}\n";

void TriangleWindow::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->attributeLocation("posAttr");
    Q_ASSERT(m_posAttr != -1);
    m_colAttr = m_program->attributeLocation("colAttr");
    Q_ASSERT(m_colAttr != -1);
    m_matrixUniform = m_program->uniformLocation("matrix");
    Q_ASSERT(m_matrixUniform != -1);
}

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

    glClear(GL_COLOR_BUFFER_BIT);

    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;
}


openglwindow.h:

#ifndef OPENGLWINDOW_H
#define OPENGLWINDOW_H

#include <QWindow>
#include <QOpenGLFunctions>

QT_FORWARD_DECLARE_CLASS(QPainter)
QT_FORWARD_DECLARE_CLASS(QOpenGLContext)
QT_FORWARD_DECLARE_CLASS(QOpenGLPaintDevice)

class OpenGLWindow : public QWindow, protected QOpenGLFunctions
{
    Q_OBJECT
public:
    explicit OpenGLWindow(QWindow *parent = nullptr);
    ~OpenGLWindow();

    virtual void render(QPainter *painter);
    virtual void render();

    virtual void initialize();

    void setAnimating(bool animating);

public slots:
    void renderLater();
    void renderNow();

protected:
    bool event(QEvent *event) override;

    void exposeEvent(QExposeEvent *event) override;

private:
    bool m_animating = false;

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

#endif // OPENGLWINDOW_H


openglwindow.cpp:

#include "openglwindow.h"

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

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

OpenGLWindow::~OpenGLWindow()
{
    delete m_device;
}

void OpenGLWindow::render(QPainter *painter)
{
    Q_UNUSED(painter);
}

void OpenGLWindow::initialize()
{
}

void OpenGLWindow::render()
{
    if (!m_device)
        m_device = new QOpenGLPaintDevice;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    m_device->setSize(size() * devicePixelRatio());
    m_device->setDevicePixelRatio(devicePixelRatio());

    QPainter painter(m_device);
    render(&painter);
}

void OpenGLWindow::renderLater()
{
    requestUpdate();
}

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

void OpenGLWindow::exposeEvent(QExposeEvent *event)
{
    Q_UNUSED(event);

    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)
        renderLater();
}

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

    if (animating)
        renderLater();
}


这里一切都很好,项目建设。但它不工作,我不知道为什么。因此,我有一个空的黑色窗口,没有任何三角形:execution当我使用fsanitize=address和valgrind检查内存泄漏时,两者都显示内存泄漏。在我解决它为什么能工作之前我不能再进一步了。也许是因为Qt版本之间的差异,这是我唯一的假设。

p1iqtdky

p1iqtdky1#

QSurfaceFormat format;
format.setSamples(16);

字符串
在这段代码中,您将16设置为驱动程序的MSAA样本。(16x MSAA)
在这里,您应该知道支持的驱动程序的MSAA示例的最大数量随环境而异。可能您的环境不支持16x MSAA,这就是发生此问题的原因。
如果您的项目是用于实际用途,那么最好检查执行环境支持的驱动程序MSAA示例的最大数量,然后选择适当的示例。(How to determine the maximum number of supported multisample samples
然而,在您的情况下,由于您的项目是用于业余爱好,我认为选择较低的2或4就足够了。

相关问题