使用原始OpenGL调用绘制Qml项时出现问题

时间:2015-01-21 15:24:49

标签: qt opengl qml qt-quick qtquick2

我想使用原始OpenGL调用在QtQuick场景中绘制单个项目。我决定采用this question建议的方法。

我创建了一个源自QQuickFramebufferObject的Qt Quick项目,并将其作为Renderer公开给QML :(代码基于Qt示例:Scene Graph - Rendering FBOs

class FboInSGRenderer : public QQuickFramebufferObject {
    Q_OBJECT
public:
    Renderer *createRenderer() const;
};

源文件:

class LogoInFboRenderer : public QQuickFramebufferObject::Renderer {
    public:
        LogoInFboRenderer() { }

        void render() {
            int width = 1, height = 1;
            glEnable(GL_BLEND);
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
            glColor4f(0.0, 1.0, 0.0, 0.8);
            glBegin(GL_QUADS);
            glVertex2f(0, 0);
            glVertex2f(width, 0);
            glVertex2f(width, height);
            glVertex2f(0, height);
            glEnd();

            glLineWidth(2.5);
            glColor4f(0.0, 0.0, 0.0, 1.0);
            glBegin(GL_LINES);
            glVertex2f(0, 0);
            glVertex2f(width, height);
            glVertex2f(width, 0);
            glVertex2f(0, height);
            glEnd();

            update();
        }

        QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) {
            QOpenGLFramebufferObjectFormat format;
            format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
            format.setSamples(4);
            return new QOpenGLFramebufferObject(size, format);
        }
};

QQuickFramebufferObject::Renderer *FboInSGRenderer::createRenderer() const {
    return new LogoInFboRenderer();
}

在Qml中,我按如下方式使用它:

import QtQuick 2.4
import SceneGraphRendering 1.0

Rectangle {
    width: 400
    height: 400
    color: "purple"
    Renderer {
        id: renderer
        anchors.fill: parent
    }
}

我期待看到渲染的" X"将填满整个场景,但我得到的结果如下:

enter image description here

其他实验似乎证实,画出的形状总是大小(宽度/高度)除以2。

我还检查size中的createFramebufferObject参数是否具有正确的值。

查看文档会将我带到QQuickFramebufferObject类中的属性textureFollowsItemSize,但默认设置为true

我做错了什么或者我应该将此行为视为Qt错误?

2 个答案:

答案 0 :(得分:2)

绘制的矩形是您期望的一半大小,因为默认坐标范围是[-1,1],而不是代码假设的[0,1]。如果要使用[0,1]比例,则应适当设置投影矩阵:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);

答案 1 :(得分:0)

正如Qt文档所说:"Warning: It is crucial that OpenGL operations and interaction with the scene graph happens exclusively on the rendering thread, primarily during the updatePaintNode() call. The best rule of thumb is to only use classes with the "QSG" prefix inside the QQuickItem::updatePaintNode() function."我这样做:

<强> *的.h

class MyQuickItem : public QQuickItem
{
    Q_OBJECT
public:
    MyQuickItem();
    ~MyQuickItem();

protected:
    QSGNode *updatePaintNode(QSGNode * oldNode, UpdatePaintNodeData * updatePaintNodeData);
    QSGNode *addNode(QSGGeometry *geometry, const QColor &color);
};

<强> *。CPP

MyQuickItem::MyQuickItem()
{
    setFlag(QQuickItem::ItemHasContents,true);
}

MyQuickItem::~MyQuickItem()
{

}

QSGNode *MyQuickItem::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *updatePaintNodeData)
{
    Q_UNUSED(updatePaintNodeData)

    QSGTransformNode *root = static_cast<QSGTransformNode *>(oldNode);
    if(!root) root = new QSGTransformNode;
    QSGNode *node;
    QSGGeometry *geometry;

    QSGSimpleRectNode *rect = new QSGSimpleRectNode();
    rect->setColor(Qt::green);
    rect->setRect(boundingRect());
    root->appendChildNode(rect);

    geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 2);
    geometry->setDrawingMode(GL_LINES);
    geometry->setLineWidth(5.0);
    geometry->vertexDataAsPoint2D()[0].set(x(), y());
    geometry->vertexDataAsPoint2D()[1].set(width(), height());
    node = addNode(geometry,Qt::blue);
    root->appendChildNode(node);

    geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 2);
    geometry->setDrawingMode(GL_LINES);
    geometry->setLineWidth(5.0);
    geometry->vertexDataAsPoint2D()[0].set(width(), y());
    geometry->vertexDataAsPoint2D()[1].set(x(), height());
    node = addNode(geometry,Qt::blue);
    root->appendChildNode(node);

    return root;
}

QSGNode *MyQuickItem::addNode(QSGGeometry *geometry, const QColor &color)
{
    QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
    material->setColor(color);
    QSGGeometryNode *node = new QSGGeometryNode;
    node->setGeometry(geometry);
    node->setFlag(QSGNode::OwnsGeometry);
    node->setMaterial(material);
    node->setFlag(QSGNode::OwnsMaterial);
    return node;
}

main.cpp

qmlRegisterType<MyQuickItem>("MyObjects", 1, 0, "MyObject");

用法:

import QtQuick 2.3
import QtQuick.Window 2.2
import MyObjects 1.0    

Window {
    visible: true
    width: 360
    height: 360

    MyObject {
        anchors.fill: parent
    }
}