2015-01-21 14 views
10

Chcę narysować pojedynczy element w scenie QtQuick za pomocą nieprzetworzonych wywołań OpenGL. Postanowiłem zastosować podejście sugerowane w this question.Problem z rysowaniem elementu Qml z surowymi wywołaniami OpenGL

Stworzyłem QT Szybki pozycję wynikającą z QQuickFramebufferObject i wystawia go do QML jak Renderer: (kod jest oparty na Qt przykład: Scene Graph - Rendering FBOs) Plik

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

źródło:

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

W Qml Używam go w następujący sposób:

I wa s spodziewając się zobaczyć, które nadają „X” wypełni całą scenę, ale zamiast tego pojawia się wynik przedstawiony poniżej:

enter image description here

Inne eksperymenty wydają się potwierdzać, że zwrócił kształt ma zawsze to rozmiar (szerokość/wysokość) podzielony przez 2.

Sprawdziłem również, czy parametr size w createFramebufferObject ma poprawną wartość.

Przeglądanie dokumentów doprowadziło mnie do właściwości textureFollowsItemSize w klasie QQuickFramebufferObject, ale domyślnie jest to true.

Czy robię coś złego, czy też powinienem uważać to zachowanie za błąd Qt?

+0

nie wiem QQuick, ale OpenGL i nie widzę, że masz ustawione albo kamerę (projekcja lub modelview) lub rzutni. Jeśli używasz domyślnej kamery OpenGL, spogląda ona w dół ujemnej osi Z. Tak więc, podczas rysowania dodatniego kwadratu x i y oczekiwałbym rezultatu, który pokazałeś (pamiętaj, że w opengl y jest do góry nogami). Aby wyrenderować niektóre elementy 2d w buforze ramki, ustawię kamerę orto w kierunku z i glViewport z zakresem [0,0] na [pixels_width, pixels_height] na przykład. – Thomas

+0

Użyłem twojego kodu - w moim przypadku zielona rzecz jest wyświetlana tylko raz. Dlaczego? – Pietrko

Odpowiedz

2

Wylosowane prostokąt to połowa wielkości można się spodziewać, ponieważ domyślna koordynować zakres wynosi [-1, 1], a nie [0, 1], jako kod zakłada . Jeśli chcesz użyć [0, 1], skalować, to należy odpowiednio ustawić macierz projekcji:

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

Dziękujemy! Rozwiązał on mój problem, chociaż natrafiłem na inny: Kiedy zmieniam rozmiar okna, które zawiera ten element, obiekt bufora ramki jest wypełniany artefaktami - element nie jest poprawnie renderowany. Postaram się zbadać to dalej i jeśli nie znajdę odpowiedzi, prawdopodobnie opublikuję nowe pytanie. – pawel

+0

Czy znalazłeś rozwiązanie dotyczące nowego problemu dotyczącego zmiany rozmiaru okna? – Mauri

0

jako dokumentacja Qt mówi: "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." zrobić to w ten sposób:

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

W głównego. cpp

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

i użytkowania:

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

Dziękuję, niestety, nie tego chciałem. Znam to podejście, ale w moim przypadku muszę wywołać surowy OpenGL (integruję z biblioteką zewnętrzną, która powinna rysować na tym elemencie). Rzeczy, które próbuję zrobić, powinny być możliwe - przykład, o którym wspomniałem w moim pytaniu, również to (Scena Graph - Rendering FBO). – pawel

Powiązane problemy