【问题标题】:Using OpenGL with QtQuickPainted item将 OpenGL 与 QtQuickPainted 项目一起使用
【发布时间】:2019-08-07 04:45:35
【问题描述】:

我试图弄清楚如何将 OpenGL 与 QtQuickPaintedItem 一起使用。根据文档,这似乎是可能的,并且有几个“帮助”类。

我在下面尝试了这段代码,我还尝试创建 QOpenGLPaintDevice、QOpenGLContext 和 QOpenGLFramebufferObject 并将它们的实例以多种组合传递给它们的函数,但它也不起作用。

/// Simple3d.h

#ifndef SIMPLE3D_H
#define SIMPLE3D_H

#include<QtQuick/QQuickPaintedItem>
#include<QOpenGLFunctions>

// Not sure if I need to use any of these classes.
//#include<QOpenGLPaintDevice>
//#include<QOpenGLContext>
//#include<QOpenGLFramebufferObject>
//#include<QOpenGLShaderProgram>
//#include <GL/gl.h>

/** @brief inherets from QtQuickItem and it draws
 * triangle.
 *
 */
class Simple3d : public QQuickPaintedItem
{

Q_OBJECT

public:

    /** Call this function to be able to instantiate this
     * item in a QML file.
     */
    static void register_qml_item();

    Simple3d();

    void paint(QPainter * painter) override;

    virtual ~Simple3d() override;

private:
    bool mDebug;

    /** OpenGL stuff */
    bool mOpenGlInitialized;
    GLuint mProgramId;
    static const GLuint mVertexArrayID = 0;
    QOpenGLFunctions *mGlFuncs;

    // Not sure when is a good time to update these:
    GLsizei mWidth, mHeight;

    GLuint load_shader(GLenum type, const char *shaderSrc);
    void verify_initialized();
    void draw_open_gl();
};

#endif

/// Simple3d.cpp

#include "simple3d.h"
#include <QSGGeometryNode>
#include <QSGVertexColorMaterial>
#include <QtMath>
#include<QOpenGLFunctions>
#include<QPainter>
#include<QGuiApplication>

using namespace std;

Simple3d::Simple3d()
{
    mDebug = true;
    mOpenGlInitialized = false;
    mGlFuncs = nullptr;
    setFlag(ItemHasContents, true);
}

void Simple3d::paint(QPainter *painter)
{

    if (mDebug) qDebug("Simple3d is running paint()");

    if (!mGlFuncs){
        mGlFuncs = new QOpenGLFunctions();
        mGlFuncs->initializeOpenGLFunctions();
    }

    painter->beginNativePainting();

    verify_initialized();
    draw_open_gl();
    painter->endNativePainting();

    if (mDebug) qDebug("Simple3d finished rendering.");
}

GLuint Simple3d::load_shader(GLenum type, const char *shaderSrc)
{
    GLuint shader;
    GLint compiled;
    // Create the shader object
    shader = mGlFuncs->glCreateShader(type);
    if(shader == 0)
        return 0;
    // Load the shader source
    mGlFuncs->glShaderSource(shader, 1, &shaderSrc, nullptr);
    // Compile the shader
    mGlFuncs->glCompileShader(shader);
    // Check the compile status
    mGlFuncs->glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
    if(!compiled)
    {
        GLint infoLen = 0;
        mGlFuncs->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
        if(infoLen > 1)
        {
            char* infoLog = new char[size_t(infoLen)+1];
            mGlFuncs->glGetShaderInfoLog(shader, infoLen, nullptr, infoLog);
            qDebug("In the shader source:\n%s", shaderSrc);
            qDebug("Error compiling shader:\n%s\n", infoLog);
            delete [] infoLog;
        }
        mGlFuncs->glDeleteShader(shader);
        return 0;
    }
    return shader;
}

void Simple3d::verify_initialized()
{
    if (mOpenGlInitialized) return;
    // This piece is partially taken from:
    // https://www.khronos.org/assets/uploads/books/openglr_es_20_programming_guide_sample.pdf

    mWidth = 50;
    mHeight = 50;

    const char vShaderStr[] =
            "attribute vec4 vPosition;\n"
            "void main()\n"
            "{\n"
            "    gl_Position = vPosition;\n"
            "}\n";
    const char fShaderStr[] =
            "//precision mediump float;\n"
            "void main()\n"
            "{\n"
            " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); \n"
            "}\n";
    GLuint vertexShader;
    GLuint fragmentShader;
    GLint linked;
    // Load the vertex/fragment shaders
    vertexShader = load_shader(GL_VERTEX_SHADER, vShaderStr);
    fragmentShader = load_shader(GL_FRAGMENT_SHADER, fShaderStr);
    // Create the program object
    mProgramId = mGlFuncs->glCreateProgram();
    if(mProgramId == 0) {
        qDebug("Failed to create the OpenGL program.");
        return;
    }
    mGlFuncs->glAttachShader(mProgramId, vertexShader);

    mGlFuncs->glAttachShader(mProgramId, fragmentShader);
    // Bind vPosition to attribute 0
    mGlFuncs->glBindAttribLocation(mProgramId, mVertexArrayID, "vPosition");
    // Link the program
    mGlFuncs->glLinkProgram(mProgramId);
    // Check the link status
    mGlFuncs->glGetProgramiv(mProgramId, GL_LINK_STATUS, &linked);
    if(!linked)
    {
        qDebug("Failed to link OpenGL program.");
        GLint infoLen = 0;
        mGlFuncs->glGetProgramiv(mProgramId, GL_INFO_LOG_LENGTH, &infoLen);
        if(infoLen > 1)
        {
            char* infoLog = new char[size_t(infoLen)];
            mGlFuncs->glGetProgramInfoLog(mProgramId, infoLen, nullptr, infoLog);
            qDebug("Error linking program:\n%s\n", infoLog);
            delete [] infoLog;
        }
        mGlFuncs->glDeleteProgram(mProgramId);
        return;
    }
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    mOpenGlInitialized = true;
    qDebug("OpenGL was initialized successfully.");
    return;
}

void Simple3d::draw_open_gl()
{

    if (!mOpenGlInitialized){
        QGuiApplication::exit(1);
        return;
    }

    mGlFuncs->glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    mGlFuncs->glEnable(GL_DEPTH_TEST);

    mGlFuncs->glUseProgram(mProgramId);

    GLfloat vVertices[] =
        {0.0f, 0.5f, 0.0f,
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f};

    // Set the viewport
    mGlFuncs->glViewport(0, 0, mWidth, mHeight);

    // Clear the color buffer
    glClear(GL_COLOR_BUFFER_BIT);

    // Load the vertex data
    mGlFuncs->glVertexAttribPointer(mVertexArrayID, 3, GL_FLOAT, GL_FALSE, 0, vVertices);
    mGlFuncs->glEnableVertexAttribArray(0);
    mGlFuncs->glDrawArrays(GL_TRIANGLES, 0, 3);
    mGlFuncs->glFlush();
    mGlFuncs->glFinish();
    mGlFuncs->glUseProgram(0); // release the program.
}

Simple3d::~Simple3d()
{

}

void Simple3d::register_qml_item()
{
    qmlRegisterType<Simple3d>("CustomGraphicsItems", 1, 0, "Simple3d");
}

/// main.cpp

#include "simple3d.h"
#include <stdexcept>

using namespace std;

int main(int argc, char *argv[]){

    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    Simple3d::register_qml_item();

    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/example_Simple3d.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                    &app, [url](QObject *obj, const QUrl &objUrl)
    {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    int num_root_objects = engine.rootObjects().size();
    qDebug("The number of root objects: %i", num_root_objects);

    if (engine.rootObjects().size()!=1){
        throw logic_error("Expected exactly one root object"
                          "in the qml file");
    }
    QObject * root = engine.rootObjects()[0];

    Simple3d * draw_3d_item = root->findChild<Simple3d*>("draw_3d_item");
    if (!draw_3d_item){
        throw logic_error("Did not find item 'draw_3d_item'.");
    }

    int result = app.exec();

    qDebug("The app is exiting.");
    return result;
}

/// example_Simple3d.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import CustomGraphicsItems 1.0
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12

Window {
    visible:  true
    Simple3d{
        id: draw_3d_item
        width: 50
        height: 50
        anchors.fill: parent
        objectName: "draw_3d_item"
    }
}

代码应该在黑色背景上显示一个红色三角形,但没有绘制任何内容。

【问题讨论】:

    标签: opengl qt-quick


    【解决方案1】:

    这个问题类似这样:Rendering custom opengl in qt5's qtquick 2.0

    我喜欢 Gunnar Sletta 的回答。诀窍是使用 QQuickFramebufferObject,而不是 QtQuickPaintedItem。

    QQuickFramebufferObject 参考页的第一行说它是一个辅助类,但实际上如果你想在 QtQuick 框架中创建自定义 OpenGL,它是关键类。他们应该叫它 QQuickOpenGLItem。

    请阅读这是使用 QQuickFramebufferObject 的示例: https://doc.qt.io/qt-5/qtquick-scenegraph-textureinsgnode-example.html(点击链接“示例项目@code.qt.io”。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多