我想使用原始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"将填满整个场景,但我得到的结果如下:
其他实验似乎证实,画出的形状总是大小(宽度/高度)除以2。
我还检查size
中的createFramebufferObject
参数是否具有正确的值。
查看文档会将我带到QQuickFramebufferObject
类中的属性textureFollowsItemSize
,但默认设置为true
。
我做错了什么或者我应该将此行为视为Qt错误?
答案 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
}
}