2015-01-21 13 views
10

Tôi muốn vẽ một mục trong cảnh QtQuick bằng cách sử dụng các cuộc gọi OpenGL thô. Tôi đã quyết định tiếp cận đề xuất trong this question.Sự cố khi vẽ Mục Qml với các cuộc gọi OpenGL thô

tôi đã tạo ra một Qt mục nhanh bắt nguồn từ QQuickFramebufferObject và tiếp xúc với nó để QML như Renderer: (mã dựa trên ví dụ Qt: Scene Graph - Rendering FBOs)

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

nguồn file:

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

Trong Qml Tôi sử dụng nó như sau:

import QtQuick 2.4 
import SceneGraphRendering 1.0 

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

Tôi wa s mong đợi để thấy rằng rendered "X" sẽ lấp đầy toàn bộ khung cảnh, nhưng thay vào đó tôi nhận được kết quả trình bày dưới đây:

enter image description here

thí nghiệm khác dường như xác nhận rằng đã thu hút hình có luôn đó là kích thước (chiều rộng/chiều cao) chia by 2.

Tôi cũng đã kiểm tra thông số size trong createFramebufferObject có giá trị chính xác.

Tìm tài liệu dẫn tôi đến thuộc tính textureFollowsItemSize trong QQuickFramebufferObject lớp nhưng theo mặc định được đặt thành true.

Tôi có làm điều gì sai hoặc tôi có nên coi hành vi này là lỗi Qt không?

+0

Tôi không biết QQuick, nhưng OpenGL và tôi không thấy rằng bạn đã đặt máy ảnh (chiếu hoặc modelview) hoặc chế độ xem. Nếu bạn sử dụng máy ảnh opengl mặc định, nó sẽ nhìn xuống trục z âm. Vì vậy, khi vẽ trong dương và x- và góc phần tư tôi sẽ mong đợi kết quả bạn hiển thị (nhớ, trong opengl y là lộn ngược). Để hiển thị một số mục 2d trong bộ đệm khung, tôi sẽ đặt máy ảnh ortho theo hướng z và glViewport có giới hạn [0,0] thành [pixel_width, pixel_height] chẳng hạn. – Thomas

+0

Tôi đã sử dụng mã của bạn - trong trường hợp của tôi, màu xanh lá cây chỉ được hiển thị một lần. Tại sao vậy? – Pietrko

Trả lời

2

Hình chữ nhật được vẽ là một nửa kích thước bạn mong đợi bởi vì mặc định phối hợp Phạm vi đó là [-1, 1], không phải là [0, 1] là mã của bạn giả . Nếu bạn muốn sử dụng tỷ lệ [0, 1], thì bạn nên đặt ma trận chiếu một cách thích hợp:

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

Cảm ơn bạn! Nó giải quyết vấn đề của tôi, mặc dù tôi chạy vào một vấn đề khác: Khi tôi thay đổi kích thước cửa sổ chứa mục đó, đối tượng frame-buffer đang được lấp đầy với các tạo tác - mục không được kết xuất chính xác. Tôi sẽ cố gắng để điều tra nó hơn nữa và nếu tôi không tìm thấy câu trả lời tôi có lẽ sẽ gửi câu hỏi mới. – pawel

+0

Bạn có tìm thấy giải pháp về vấn đề mới, liên quan đến việc thay đổi kích thước cửa sổ không? – Mauri

0

Như tài liệu Qt nói: "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." tôi làm điều đó theo cách này:

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

Trong chính. cpp

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

Và sử dụng:

import QtQuick 2.3 
import QtQuick.Window 2.2 
import MyObjects 1.0  

Window { 
    visible: true 
    width: 360 
    height: 360 

    MyObject { 
     anchors.fill: parent 
    } 
} 
+0

Cảm ơn bạn, tiếc là nó không phải là những gì tôi muốn. Tôi biết cách tiếp cận này nhưng trong trường hợp của tôi, tôi cần phải gọi OpenGL thô (tôi đang tích hợp với thư viện bên ngoài mà nên được vẽ trên mục đó). Những điều tôi đang cố gắng làm nên có thể - ví dụ mà tôi đã đề cập trong câu hỏi của tôi không quá (Đồ thị cảnh - Rendering FBOs). – pawel

Các vấn đề liên quan