Skip to content

Instantly share code, notes, and snippets.

@nocnokneo
Last active August 15, 2024 15:23
Show Gist options
  • Select an option

  • Save nocnokneo/c3fb01bb7ecaf437f7d6 to your computer and use it in GitHub Desktop.

Select an option

Save nocnokneo/c3fb01bb7ecaf437f7d6 to your computer and use it in GitHub Desktop.

Revisions

  1. Taylor Braun-Jones revised this gist Jul 28, 2014. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion QVTKFramebufferObjectItem.cpp
    Original file line number Diff line number Diff line change
    @@ -121,7 +121,6 @@ class QVTKFramebufferObjectRenderer : public QQuickFramebufferObject::Renderer
    qDebug("QVTKFramebufferObjectRenderer::createFramebufferObject");
    QOpenGLFramebufferObjectFormat format;
    format.setAttachment(QOpenGLFramebufferObject::Depth);
    format.setSamples(4);
    m_framebufferObject = new QOpenGLFramebufferObject(size, format);

    m_vtkRenderWindow->SetFramebufferObject(m_framebufferObject);
  2. nocnokneo revised this gist Jul 18, 2014. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions QVTKFramebufferObjectItem.cpp
    Original file line number Diff line number Diff line change
    @@ -32,6 +32,8 @@ class vtkInternalOpenGLRenderWindow : public vtkGenericOpenGLRenderWindow, prote
    initializeOpenGLFunctions();

    glUseProgram(0); // Shouldn't Superclass::OpenGLInitState() handle this?
    glDisable(GL_DEPTH_TEST); // depth buffer fighting between the cone and the backround without this
    glDisable(GL_BLEND); // doesn't seem crucial (?) but it is one of the differnces that showed up in apitrace analysis
    }

    // Override to use deferred rendering - Tell the QSG that we need to
  3. Taylor Braun-Jones revised this gist Jul 17, 2014. 1 changed file with 12 additions and 5 deletions.
    17 changes: 12 additions & 5 deletions QVTKFramebufferObjectItem.cpp
    Original file line number Diff line number Diff line change
    @@ -1,9 +1,10 @@
    #define GL_GLEXT_PROTOTYPES
    #include <GL/gl.h>
    #include <GL/glext.h>

    #include "QVTKFramebufferObjectItem.h"

    // Use the OpenGL API abstraction from Qt instead of from VTK because vtkgl.h
    // and other Qt OpenGL-related headers do not play nice when included in the
    // same compilation unit
    #include <QOpenGLFunctions>

    #include <QQuickFramebufferObject>
    #include <QOpenGLFramebufferObject>

    @@ -15,7 +16,7 @@

    class QVTKFramebufferObjectRenderer;

    class vtkInternalOpenGLRenderWindow : public vtkGenericOpenGLRenderWindow
    class vtkInternalOpenGLRenderWindow : public vtkGenericOpenGLRenderWindow, protected QOpenGLFunctions
    {
    public:
    static vtkInternalOpenGLRenderWindow* New();
    @@ -24,6 +25,12 @@ class vtkInternalOpenGLRenderWindow : public vtkGenericOpenGLRenderWindow
    virtual void OpenGLInitState()
    {
    Superclass::OpenGLInitState();

    // Before any of the gl* functions in QOpenGLFunctions are called for a
    // given OpenGL context, an initialization must be run within that context
    this->MakeCurrent();
    initializeOpenGLFunctions();

    glUseProgram(0); // Shouldn't Superclass::OpenGLInitState() handle this?
    }

  4. nocnokneo revised this gist May 23, 2014. 3 changed files with 118 additions and 51 deletions.
    151 changes: 105 additions & 46 deletions QVTKFramebufferObjectItem.cpp
    Original file line number Diff line number Diff line change
    @@ -8,79 +8,95 @@
    #include <QOpenGLFramebufferObject>

    #include <vtkGenericOpenGLRenderWindow.h>
    #include "vtkObjectFactory.h"
    #include <vtkObjectFactory.h>

    #include <vtkRendererCollection.h>
    #include <vtkCamera.h>

    class QVTKFramebufferObjectRenderer;

    class vtkInternalOpenGLRenderWindow : public vtkGenericOpenGLRenderWindow
    {
    public:
    static vtkInternalOpenGLRenderWindow* New();
    vtkTypeMacro(vtkInternalOpenGLRenderWindow, vtkGenericOpenGLRenderWindow)

    virtual void OpenGLInitState()
    {
    Superclass::OpenGLInitState();
    glUseProgram(0); // Shouldn't Superclass::OpenGLInitState() handle this?
    }

    // Override to use deferred rendering - Tell the QSG that we need to
    // be rendered which will then, at the appropriate time, call
    // InternalRender to do the actual OpenGL rendering.
    virtual void Render();

    // Do the actual OpenGL rendering
    void InternalRender()
    {
    Superclass::Render();
    }

    // Provides a convenient way to set the protected FBO ivars from an existing
    // FBO that was created and owned by Qt's FBO abstraction class
    // QOpenGLFramebufferObject
    void SetFramebufferObject(QOpenGLFramebufferObject *fbo);

    QVTKFramebufferObjectRenderer *QtParentRenderer;

    protected:
    vtkInternalOpenGLRenderWindow()
    vtkInternalOpenGLRenderWindow() :
    QtParentRenderer(0)
    {
    this->OffScreenRendering = 1;
    }

    ~vtkInternalOpenGLRenderWindow()
    {
    // Prevent superclass destructors from destroying the framebuffer object.
    // QOpenGLFramebufferObject owns the FBO and manages it's lifecyle.
    this->OffScreenRendering = 0;
    }

    public:
    virtual void OpenGLInitState()
    {
    Superclass::OpenGLInitState();
    glUseProgram(0); // Shouldn't Superclass::OpenGLInitState() handle this?
    }

    void SetFramebufferObject(QOpenGLFramebufferObject *fbo)
    {
    // QOpenGLFramebufferObject documentation states that "The color render
    // buffer or texture will have the specified internal format, and will
    // be bound to the GL_COLOR_ATTACHMENT0 attachment in the framebuffer
    // object"
    this->BackLeftBuffer = this->FrontLeftBuffer = this->BackBuffer = this->FrontBuffer =
    static_cast<unsigned int>(GL_COLOR_ATTACHMENT0);

    // Save GL objects by static casting to standard C types. GL* types
    // are not allowed in VTK header files.
    QSize fboSize = fbo->size();
    this->Size[0] = fboSize.width();
    this->Size[1] = fboSize.height();
    this->NumberOfFrameBuffers = 1;
    this->FrameBufferObject = static_cast<unsigned int>(fbo->handle());
    this->DepthRenderBufferObject = 0; // static_cast<unsigned int>(depthRenderBufferObject);
    this->TextureObjects[0] = static_cast<unsigned int>(fbo->texture());
    this->OffScreenUseFrameBuffer = 1;
    this->Modified();
    }
    };
    vtkStandardNewMacro(vtkInternalOpenGLRenderWindow)
    vtkStandardNewMacro(vtkInternalOpenGLRenderWindow);


    class QVTKFramebufferObjectRenderer : public QQuickFramebufferObject::Renderer
    {
    friend class vtkInternalOpenGLRenderWindow;

    public:
    QVTKFramebufferObjectRenderer(vtkInternalOpenGLRenderWindow *rw) :
    m_vtkRenderWindow(rw)
    m_vtkRenderWindow(rw),
    m_framebufferObject(0)
    {
    m_vtkRenderWindow->Register(NULL);
    m_vtkRenderWindow->QtParentRenderer = this;
    }

    ~QVTKFramebufferObjectRenderer()
    {
    m_vtkRenderWindow->QtParentRenderer = 0;
    m_vtkRenderWindow->Delete();
    }

    void render()
    virtual void synchronize(QQuickFramebufferObject * item)
    {
    // the first synchronize call - right before the the framebufferObject
    // is created for the first time
    if (!m_framebufferObject)
    {
    QVTKFrameBufferObjectItem *vtkItem = static_cast<QVTKFrameBufferObjectItem*>(item);
    vtkItem->init();
    }
    }

    // Called from the render thread when the GUI thread is NOT blocked
    virtual void render()
    {
    m_vtkRenderWindow->PushState();
    m_vtkRenderWindow->OpenGLInitState();
    m_vtkRenderWindow->Render(); // vtkXOpenGLRenderWindow renders the scene to the FBO
    m_vtkRenderWindow->InternalRender(); // vtkXOpenGLRenderWindow renders the scene to the FBO
    m_vtkRenderWindow->PopState();

    // Dolly camera back and forth - FOR DEMONSTRATION PURPOSES ONLY
    @@ -93,38 +109,81 @@ class QVTKFramebufferObjectRenderer : public QQuickFramebufferObject::Renderer

    QOpenGLFramebufferObject *createFramebufferObject(const QSize &size)
    {
    qDebug("QVTKFramebufferObjectRenderer::createFramebufferObject");
    QOpenGLFramebufferObjectFormat format;
    format.setAttachment(QOpenGLFramebufferObject::Depth);
    format.setSamples(4);
    QOpenGLFramebufferObject *fbo = new QOpenGLFramebufferObject(size, format);
    m_framebufferObject = new QOpenGLFramebufferObject(size, format);

    m_vtkRenderWindow->SetFramebufferObject(fbo);
    m_vtkRenderWindow->SetFramebufferObject(m_framebufferObject);

    return fbo;
    return m_framebufferObject;
    }

    vtkInternalOpenGLRenderWindow *m_vtkRenderWindow;
    QOpenGLFramebufferObject *m_framebufferObject;
    };

    //
    // vtkInternalOpenGLRenderWindow Definitions
    //

    void vtkInternalOpenGLRenderWindow::Render()
    {
    if (this->QtParentRenderer)
    {
    this->QtParentRenderer->update();
    }
    }

    void vtkInternalOpenGLRenderWindow::SetFramebufferObject(QOpenGLFramebufferObject *fbo)
    {
    // QOpenGLFramebufferObject documentation states that "The color render
    // buffer or texture will have the specified internal format, and will
    // be bound to the GL_COLOR_ATTACHMENT0 attachment in the framebuffer
    // object"
    this->BackLeftBuffer = this->FrontLeftBuffer = this->BackBuffer = this->FrontBuffer =
    static_cast<unsigned int>(GL_COLOR_ATTACHMENT0);

    // Save GL objects by static casting to standard C types. GL* types
    // are not allowed in VTK header files.
    QSize fboSize = fbo->size();
    this->Size[0] = fboSize.width();
    this->Size[1] = fboSize.height();
    this->NumberOfFrameBuffers = 1;
    this->FrameBufferObject = static_cast<unsigned int>(fbo->handle());
    this->DepthRenderBufferObject = 0; // static_cast<unsigned int>(depthRenderBufferObject);
    this->TextureObjects[0] = static_cast<unsigned int>(fbo->texture());
    this->OffScreenRendering = 1;
    this->OffScreenUseFrameBuffer = 1;
    this->Modified();
    }

    //
    // QVTKFrameBufferObjectItem Definitions
    //

    QVTKFrameBufferObjectItem::QVTKFrameBufferObjectItem()
    {
    m_vtkRenderWindow = vtkInternalOpenGLRenderWindow::New();
    m_vtkRenderWindow->Register(NULL);
    m_win = vtkInternalOpenGLRenderWindow::New();
    }

    QVTKFrameBufferObjectItem::~QVTKFrameBufferObjectItem()
    {
    m_vtkRenderWindow->Delete();
    m_win->Delete();
    }

    QQuickFramebufferObject::Renderer *QVTKFrameBufferObjectItem::createRenderer() const
    {
    m_vtkRenderWindow->OpenGLInit();
    return new QVTKFramebufferObjectRenderer(static_cast<vtkInternalOpenGLRenderWindow*>(m_vtkRenderWindow));
    return new QVTKFramebufferObjectRenderer(static_cast<vtkInternalOpenGLRenderWindow*>(m_win));
    }

    vtkGenericOpenGLRenderWindow *QVTKFrameBufferObjectItem::GetRenderWindow() const
    {
    return m_win;
    }

    vtkOpenGLRenderWindow *QVTKFrameBufferObjectItem::getVtkRenderWindow() const
    void QVTKFrameBufferObjectItem::init()
    {
    return m_vtkRenderWindow;
    qDebug("QVTKFrameBufferObjectItem::init");
    }
    14 changes: 11 additions & 3 deletions QVTKFramebufferObjectItem.h
    Original file line number Diff line number Diff line change
    @@ -3,19 +3,27 @@

    #include <QtQuick/QQuickFramebufferObject>

    class vtkOpenGLRenderWindow;
    class vtkGenericOpenGLRenderWindow;
    class QVTKFramebufferObjectRenderer;

    class QVTKFrameBufferObjectItem : public QQuickFramebufferObject
    {
    Q_OBJECT

    public:
    QVTKFrameBufferObjectItem();
    ~QVTKFrameBufferObjectItem();
    Renderer *createRenderer() const;
    vtkOpenGLRenderWindow* getVtkRenderWindow() const;
    vtkGenericOpenGLRenderWindow* GetRenderWindow() const;

    protected:
    vtkOpenGLRenderWindow *m_vtkRenderWindow;
    // Called once before the FBO is created for the first time. This method is
    // called from render thread while the GUI thread is blocked.
    virtual void init();

    vtkGenericOpenGLRenderWindow *m_win;

    friend class QVTKFramebufferObjectRenderer;
    };

    #endif
    4 changes: 2 additions & 2 deletions main.cpp
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,7 @@
    #include <vtkActor.h>
    #include <vtkConeSource.h>
    #include <vtkPolyDataMapper.h>
    #include <vtkOpenGLRenderWindow.h>
    #include <vtkGenericOpenGLRenderWindow.h>
    #include <vtkRenderer.h>
    #include <vtkSmartPointer.h>
    #include <vtkRendererCollection.h>
    @@ -28,7 +28,7 @@ int main(int argc, char **argv)
    // For demonstration: Add a cone to the scene of each QVTKFrameBufferObjectItem
    Q_FOREACH(QVTKFrameBufferObjectItem *vtkItem, vtkItems)
    {
    vtkOpenGLRenderWindow *rw = vtkItem->getVtkRenderWindow();
    vtkGenericOpenGLRenderWindow *rw = vtkItem->GetRenderWindow();
    // Create a renderer and add it to the render window
    vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
    rw->AddRenderer(renderer);
  5. nocnokneo revised this gist May 22, 2014. 1 changed file with 8 additions and 2 deletions.
    10 changes: 8 additions & 2 deletions main.qml
    Original file line number Diff line number Diff line change
    @@ -12,14 +12,20 @@ Rectangle {
    id : vtkRenderWindowContainer
    anchors.fill: parent
    anchors.margins: 20
    rotation: mouseArea.containsMouse ? 10 : -10
    Behavior on rotation { NumberAnimation {} }
    border.width: 4
    border.color: "black"
    color: "blue"

    VtkRenderWindow {
    id: vtkRenderWindow
    anchors.fill: parent
    property real flipAngle: mouseArea.containsMouse ? 0 : 180
    Behavior on flipAngle { NumberAnimation {} }
    transform: Rotation {
    origin { x: vtkRenderWindow.width/2; y: vtkRenderWindow.height/2 }
    axis { x: 0; y: 1; z: 0 }
    angle: vtkRenderWindow.flipAngle
    }
    }
    }

  6. nocnokneo revised this gist May 22, 2014. 4 changed files with 7 additions and 7 deletions.
    2 changes: 1 addition & 1 deletion CMakeLists.txt
    Original file line number Diff line number Diff line change
    @@ -14,7 +14,7 @@ configure_file(VtkFboInQtQuickConfig.h.in ${PROJECT_BINARY_DIR}/VtkFboInQtQuickC

    add_executable(${PROJECT_NAME}
    main.cpp
    QVTKFrameBufferObjectItem.cpp
    QVTKFramebufferObjectItem.cpp
    main.qml
    )
    target_link_libraries(${PROJECT_NAME} ${VTK_LIBRARIES} Qt5::Quick)
    10 changes: 5 additions & 5 deletions QVTKFrameBufferObjectItem.cpp → QVTKFramebufferObjectItem.cpp
    Original file line number Diff line number Diff line change
    @@ -2,7 +2,7 @@
    #include <GL/gl.h>
    #include <GL/glext.h>

    #include "QVTKFrameBufferObjectItem.h"
    #include "QVTKFramebufferObjectItem.h"

    #include <QQuickFramebufferObject>
    #include <QOpenGLFramebufferObject>
    @@ -62,16 +62,16 @@ class vtkInternalOpenGLRenderWindow : public vtkGenericOpenGLRenderWindow
    vtkStandardNewMacro(vtkInternalOpenGLRenderWindow)


    class QVTKFrameBufferObjectRenderer : public QQuickFramebufferObject::Renderer
    class QVTKFramebufferObjectRenderer : public QQuickFramebufferObject::Renderer
    {
    public:
    QVTKFrameBufferObjectRenderer(vtkInternalOpenGLRenderWindow *rw) :
    QVTKFramebufferObjectRenderer(vtkInternalOpenGLRenderWindow *rw) :
    m_vtkRenderWindow(rw)
    {
    m_vtkRenderWindow->Register(NULL);
    }

    ~QVTKFrameBufferObjectRenderer()
    ~QVTKFramebufferObjectRenderer()
    {
    m_vtkRenderWindow->Delete();
    }
    @@ -121,7 +121,7 @@ QVTKFrameBufferObjectItem::~QVTKFrameBufferObjectItem()
    QQuickFramebufferObject::Renderer *QVTKFrameBufferObjectItem::createRenderer() const
    {
    m_vtkRenderWindow->OpenGLInit();
    return new QVTKFrameBufferObjectRenderer(static_cast<vtkInternalOpenGLRenderWindow*>(m_vtkRenderWindow));
    return new QVTKFramebufferObjectRenderer(static_cast<vtkInternalOpenGLRenderWindow*>(m_vtkRenderWindow));
    }

    vtkOpenGLRenderWindow *QVTKFrameBufferObjectItem::getVtkRenderWindow() const
    File renamed without changes.
    2 changes: 1 addition & 1 deletion main.cpp
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,5 @@
    #include "VtkFboInQtQuickConfig.h"
    #include "QVTKFrameBufferObjectItem.h"
    #include "QVTKFramebufferObjectItem.h"

    #include <vtkActor.h>
    #include <vtkConeSource.h>
  7. nocnokneo revised this gist May 22, 2014. 3 changed files with 124 additions and 79 deletions.
    162 changes: 85 additions & 77 deletions QVTKFrameBufferObjectItem.cpp
    Original file line number Diff line number Diff line change
    @@ -7,91 +7,38 @@
    #include <QQuickFramebufferObject>
    #include <QOpenGLFramebufferObject>

    #include <vtkActor.h>
    #include <vtkConeSource.h>
    #include <vtkPolyDataMapper.h>
    #include <vtkRenderWindow.h>
    #if __APPLE__
    #include <vtkCocoaRenderWindow.h>
    #else
    #include <vtkXOpenGLRenderWindow.h>
    #endif

    #include <vtkRenderer.h>
    #include <vtkSmartPointer.h>
    #include <vtkGenericOpenGLRenderWindow.h>
    #include "vtkObjectFactory.h"

    #include <vtkRendererCollection.h>
    #include <vtkCamera.h>
    #include <vtkProperty.h>

    class QVTKFrameBufferObjectRenderer :
    public QQuickFramebufferObject::Renderer,
    #if __APPLE__
    public vtkCocoaRenderWindow
    #else
    public vtkXOpenGLRenderWindow
    #endif

    class vtkInternalOpenGLRenderWindow : public vtkGenericOpenGLRenderWindow
    {
    public:
    QVTKFrameBufferObjectRenderer()
    {
    this->OffScreenRendering = 1;
    #if __APPLE__
    this->OffScreenInitialized = 1;
    #endif

    // Create a renderer and render window
    renderer = vtkRenderer::New();
    this->AddRenderer(renderer);
    renderer->Delete();

    // FOR TESTING
    vtkSmartPointer<vtkConeSource> polyDataSource = vtkSmartPointer<vtkConeSource>::New();
    vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
    mapper->SetInputConnection(polyDataSource->GetOutputPort());
    actor->SetMapper(mapper);
    actor->GetProperty()->SetOpacity(0.5); // demo support for opacity of VTK objects
    renderer->AddActor(actor);
    }

    virtual ~QVTKFrameBufferObjectRenderer()
    {
    renderer->Delete();
    this->OffScreenRendering = 0;
    #if __APPLE__
    this->OffScreenInitialized = 0;
    #endif
    }
    static vtkInternalOpenGLRenderWindow* New();
    vtkTypeMacro(vtkInternalOpenGLRenderWindow, vtkGenericOpenGLRenderWindow)
    protected:
    vtkInternalOpenGLRenderWindow()
    {
    this->OffScreenRendering = 1;
    }
    ~vtkInternalOpenGLRenderWindow()
    {
    // Prevent superclass destructors from destroying the framebuffer object.
    // QOpenGLFramebufferObject owns the FBO and manages it's lifecyle.
    this->OffScreenRendering = 0;
    }

    void render()
    public:
    virtual void OpenGLInitState()
    {
    static int callCount = 0;
    ++callCount;

    // Fix for differences in GL state between first call (before first
    // rendering of the Qt Quick 2 Scene Graph) and second call. In order
    // of most important to least.
    glUseProgram(0); // crucial for the cone to show up at all after the first render
    glDisable(GL_DEPTH_TEST); // depth buffer fighting between the cone and the backround without this
    glDisable(GL_BLEND); // doesn't seem crucial (?) but it is one of the differnces that showed up in apitrace analysis

    this->Render(); // vtkXOpenGLRenderWindow renders the scene to the FBO

    double dolly = 1.0 + ((callCount % 200) > 100 ? -0.001 : 0.001);
    this->GetRenderers()->GetFirstRenderer()->GetActiveCamera()->Dolly(dolly);
    this->update();
    Superclass::OpenGLInitState();
    glUseProgram(0); // Shouldn't Superclass::OpenGLInitState() handle this?
    }

    QOpenGLFramebufferObject *createFramebufferObject(const QSize &size)
    void SetFramebufferObject(QOpenGLFramebufferObject *fbo)
    {
    qDebug("VTKFrameBufferObjectRenderer: createFramebufferObject");

    QOpenGLFramebufferObjectFormat format;
    format.setAttachment(QOpenGLFramebufferObject::Depth);
    format.setSamples(4);
    QOpenGLFramebufferObject *fbo = new QOpenGLFramebufferObject(size, format);

    // QOpenGLFramebufferObject documentation states that "The color render
    // buffer or texture will have the specified internal format, and will
    // be bound to the GL_COLOR_ATTACHMENT0 attachment in the framebuffer
    @@ -110,13 +57,74 @@ class QVTKFrameBufferObjectRenderer :
    this->TextureObjects[0] = static_cast<unsigned int>(fbo->texture());
    this->OffScreenUseFrameBuffer = 1;
    this->Modified();
    }
    };
    vtkStandardNewMacro(vtkInternalOpenGLRenderWindow)


    class QVTKFrameBufferObjectRenderer : public QQuickFramebufferObject::Renderer
    {
    public:
    QVTKFrameBufferObjectRenderer(vtkInternalOpenGLRenderWindow *rw) :
    m_vtkRenderWindow(rw)
    {
    m_vtkRenderWindow->Register(NULL);
    }

    ~QVTKFrameBufferObjectRenderer()
    {
    m_vtkRenderWindow->Delete();
    }

    void render()
    {
    m_vtkRenderWindow->PushState();
    m_vtkRenderWindow->OpenGLInitState();
    m_vtkRenderWindow->Render(); // vtkXOpenGLRenderWindow renders the scene to the FBO
    m_vtkRenderWindow->PopState();

    // Dolly camera back and forth - FOR DEMONSTRATION PURPOSES ONLY
    static int callCount = 0;
    ++callCount;
    double dolly = 1.0 + ((callCount % 200) > 100 ? -0.001 : 0.001);
    m_vtkRenderWindow->GetRenderers()->GetFirstRenderer()->GetActiveCamera()->Dolly(dolly);
    this->update();
    }

    QOpenGLFramebufferObject *createFramebufferObject(const QSize &size)
    {
    QOpenGLFramebufferObjectFormat format;
    format.setAttachment(QOpenGLFramebufferObject::Depth);
    format.setSamples(4);
    QOpenGLFramebufferObject *fbo = new QOpenGLFramebufferObject(size, format);

    m_vtkRenderWindow->SetFramebufferObject(fbo);

    return fbo;
    }
    vtkRenderer *renderer;

    vtkInternalOpenGLRenderWindow *m_vtkRenderWindow;
    };


    QVTKFrameBufferObjectItem::QVTKFrameBufferObjectItem()
    {
    m_vtkRenderWindow = vtkInternalOpenGLRenderWindow::New();
    m_vtkRenderWindow->Register(NULL);
    }

    QVTKFrameBufferObjectItem::~QVTKFrameBufferObjectItem()
    {
    m_vtkRenderWindow->Delete();
    }

    QQuickFramebufferObject::Renderer *QVTKFrameBufferObjectItem::createRenderer() const
    {
    return new QVTKFrameBufferObjectRenderer();
    m_vtkRenderWindow->OpenGLInit();
    return new QVTKFrameBufferObjectRenderer(static_cast<vtkInternalOpenGLRenderWindow*>(m_vtkRenderWindow));
    }

    vtkOpenGLRenderWindow *QVTKFrameBufferObjectItem::getVtkRenderWindow() const
    {
    return m_vtkRenderWindow;
    }
    11 changes: 9 additions & 2 deletions QVTKFrameBufferObjectItem.h
    Original file line number Diff line number Diff line change
    @@ -3,12 +3,19 @@

    #include <QtQuick/QQuickFramebufferObject>

    class vtkOpenGLRenderWindow;

    class QVTKFrameBufferObjectItem : public QQuickFramebufferObject
    {
    Q_OBJECT
    Q_OBJECT
    public:
    Renderer *createRenderer() const;
    QVTKFrameBufferObjectItem();
    ~QVTKFrameBufferObjectItem();
    Renderer *createRenderer() const;
    vtkOpenGLRenderWindow* getVtkRenderWindow() const;

    protected:
    vtkOpenGLRenderWindow *m_vtkRenderWindow;
    };

    #endif
    30 changes: 30 additions & 0 deletions main.cpp
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,19 @@
    #include "VtkFboInQtQuickConfig.h"
    #include "QVTKFrameBufferObjectItem.h"

    #include <vtkActor.h>
    #include <vtkConeSource.h>
    #include <vtkPolyDataMapper.h>
    #include <vtkOpenGLRenderWindow.h>
    #include <vtkRenderer.h>
    #include <vtkSmartPointer.h>
    #include <vtkRendererCollection.h>
    #include <vtkCamera.h>
    #include <vtkProperty.h>

    #include <QGuiApplication>
    #include <QQuickView>
    #include <QList>

    int main(int argc, char **argv)
    {
    @@ -12,6 +23,25 @@ int main(int argc, char **argv)

    QQuickView view;
    view.setSource(QUrl(PROJECT_SOURCE_DIR "/main.qml"));
    QList<QVTKFrameBufferObjectItem*> vtkItems = view.rootObject()->findChildren<QVTKFrameBufferObjectItem*>();

    // For demonstration: Add a cone to the scene of each QVTKFrameBufferObjectItem
    Q_FOREACH(QVTKFrameBufferObjectItem *vtkItem, vtkItems)
    {
    vtkOpenGLRenderWindow *rw = vtkItem->getVtkRenderWindow();
    // Create a renderer and add it to the render window
    vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
    rw->AddRenderer(renderer);

    vtkSmartPointer<vtkConeSource> polyDataSource = vtkSmartPointer<vtkConeSource>::New();
    vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
    mapper->SetInputConnection(polyDataSource->GetOutputPort());
    actor->SetMapper(mapper);
    actor->GetProperty()->SetOpacity(0.5); // demonstrate support for translucent VTK objects
    renderer->AddActor(actor);
    }

    view.setResizeMode( QQuickView::SizeRootObjectToView );
    view.show();

  8. nocnokneo revised this gist May 21, 2014. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion QVTKFrameBufferObjectItem.h
    Original file line number Diff line number Diff line change
    @@ -3,7 +3,6 @@

    #include <QtQuick/QQuickFramebufferObject>

    class LogoRenderer;

    class QVTKFrameBufferObjectItem : public QQuickFramebufferObject
    {
  9. nocnokneo revised this gist May 21, 2014. 1 changed file with 7 additions and 20 deletions.
    27 changes: 7 additions & 20 deletions QVTKFrameBufferObjectItem.cpp
    Original file line number Diff line number Diff line change
    @@ -92,35 +92,22 @@ class QVTKFrameBufferObjectRenderer :
    format.setSamples(4);
    QOpenGLFramebufferObject *fbo = new QOpenGLFramebufferObject(size, format);

    QSize fboSize = fbo->size();
    this->Size[0] = fboSize.width();
    this->Size[1] = fboSize.height();

    GLuint frameBufferObject = fbo->handle();
    GLuint textureObject = fbo->texture();
    // GLint depthRenderBufferObject; // qFrameBufferObject->depthBuffer(); // method not exist (yet) So...
    // fbo->bind();
    // glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
    // GL_DEPTH_ATTACHMENT,
    // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
    // &depthRenderBufferObject); // Crashes
    // fbo->release();

    // QOpenGLFramebufferObject documentation states that "The color render
    // buffer or texture will have the specified internal format, and will
    // be bound to the GL_COLOR_ATTACHMENT0 attachment in the framebuffer
    // object"
    this->BackLeftBuffer = static_cast<unsigned int>(GL_COLOR_ATTACHMENT0);
    this->FrontLeftBuffer = static_cast<unsigned int>(GL_COLOR_ATTACHMENT0);
    this->BackBuffer = static_cast<unsigned int>(GL_COLOR_ATTACHMENT0);
    this->FrontBuffer = static_cast<unsigned int>(GL_COLOR_ATTACHMENT0);
    this->BackLeftBuffer = this->FrontLeftBuffer = this->BackBuffer = this->FrontBuffer =
    static_cast<unsigned int>(GL_COLOR_ATTACHMENT0);

    // Save GL objects by static casting to standard C types. GL* types
    // are not allowed in VTK header files.
    QSize fboSize = fbo->size();
    this->Size[0] = fboSize.width();
    this->Size[1] = fboSize.height();
    this->NumberOfFrameBuffers = 1;
    this->FrameBufferObject = static_cast<unsigned int>(frameBufferObject);
    this->FrameBufferObject = static_cast<unsigned int>(fbo->handle());
    this->DepthRenderBufferObject = 0; // static_cast<unsigned int>(depthRenderBufferObject);
    this->TextureObjects[0] = static_cast<unsigned int>(textureObject);
    this->TextureObjects[0] = static_cast<unsigned int>(fbo->texture());
    this->OffScreenUseFrameBuffer = 1;
    this->Modified();

  10. nocnokneo revised this gist May 21, 2014. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions QVTKFrameBufferObjectItem.cpp
    Original file line number Diff line number Diff line change
    @@ -22,6 +22,7 @@

    #include <vtkRendererCollection.h>
    #include <vtkCamera.h>
    #include <vtkProperty.h>

    class QVTKFrameBufferObjectRenderer :
    public QQuickFramebufferObject::Renderer,
    @@ -50,6 +51,7 @@ class QVTKFrameBufferObjectRenderer :
    vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
    mapper->SetInputConnection(polyDataSource->GetOutputPort());
    actor->SetMapper(mapper);
    actor->GetProperty()->SetOpacity(0.5); // demo support for opacity of VTK objects
    renderer->AddActor(actor);
    }

  11. nocnokneo revised this gist May 21, 2014. 1 changed file with 18 additions and 2 deletions.
    20 changes: 18 additions & 2 deletions QVTKFrameBufferObjectItem.cpp
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,7 @@
    #define GL_GLEXT_PROTOTYPES
    #include <GL/gl.h>
    #include <GL/glext.h>

    #include "QVTKFrameBufferObjectItem.h"

    #include <QQuickFramebufferObject>
    @@ -60,9 +64,21 @@ class QVTKFrameBufferObjectRenderer :

    void render()
    {
    this->GetRenderers()->GetFirstRenderer()->GetActiveCamera()->Dolly(0.8);
    static int callCount = 0;
    ++callCount;

    // Fix for differences in GL state between first call (before first
    // rendering of the Qt Quick 2 Scene Graph) and second call. In order
    // of most important to least.
    glUseProgram(0); // crucial for the cone to show up at all after the first render
    glDisable(GL_DEPTH_TEST); // depth buffer fighting between the cone and the backround without this
    glDisable(GL_BLEND); // doesn't seem crucial (?) but it is one of the differnces that showed up in apitrace analysis

    this->Render(); // vtkXOpenGLRenderWindow renders the scene to the FBO
    // this->update();

    double dolly = 1.0 + ((callCount % 200) > 100 ? -0.001 : 0.001);
    this->GetRenderers()->GetFirstRenderer()->GetActiveCamera()->Dolly(dolly);
    this->update();
    }

    QOpenGLFramebufferObject *createFramebufferObject(const QSize &size)
  12. nocnokneo revised this gist May 21, 2014. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion QVTKFrameBufferObjectItem.cpp
    Original file line number Diff line number Diff line change
    @@ -36,7 +36,7 @@ class QVTKFrameBufferObjectRenderer :
    #endif

    // Create a renderer and render window
    vtkRenderer *renderer = vtkRenderer::New();
    renderer = vtkRenderer::New();
    this->AddRenderer(renderer);
    renderer->Delete();

    @@ -51,6 +51,7 @@ class QVTKFrameBufferObjectRenderer :

    virtual ~QVTKFrameBufferObjectRenderer()
    {
    renderer->Delete();
    this->OffScreenRendering = 0;
    #if __APPLE__
    this->OffScreenInitialized = 0;
    @@ -107,6 +108,7 @@ class QVTKFrameBufferObjectRenderer :

    return fbo;
    }
    vtkRenderer *renderer;
    };

    QQuickFramebufferObject::Renderer *QVTKFrameBufferObjectItem::createRenderer() const
  13. nocnokneo revised this gist May 20, 2014. 1 changed file with 6 additions and 0 deletions.
    6 changes: 6 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -8,6 +8,12 @@ used by [OpenView Core](https://github.com/Kitware/openview/tree/master/core))

    ## Build Instructions

    Requires Qt 5.2 or greater. Tested configurations:

    * RHEL6, VTK 5.10, Qt 5.2.1
    * Ubuntu 12.04, VTK 6.1, Qt 5.3.0
    * Mac OS 10.9,VTK 6.1, Qt 5.2.1

    ```Shell
    git clone https://gist.github.com/c3fb01bb7ecaf437f7d6.git VtkFboInQtQuick
    mkdir VtkFboInQtQuick-build
  14. nocnokneo revised this gist May 19, 2014. 1 changed file with 20 additions and 2 deletions.
    22 changes: 20 additions & 2 deletions QVTKFrameBufferObjectItem.cpp
    Original file line number Diff line number Diff line change
    @@ -1,24 +1,39 @@
    #include "QVTKFrameBufferObjectItem.h"

    #include <QtGui/QOpenGLFramebufferObject>
    #include <QQuickFramebufferObject>
    #include <QOpenGLFramebufferObject>

    #include <vtkActor.h>
    #include <vtkConeSource.h>
    #include <vtkPolyDataMapper.h>
    #include <vtkRenderWindow.h>
    #if __APPLE__
    #include <vtkCocoaRenderWindow.h>
    #else
    #include <vtkXOpenGLRenderWindow.h>
    #endif

    #include <vtkRenderer.h>
    #include <vtkSmartPointer.h>

    #include <vtkRendererCollection.h>
    #include <vtkCamera.h>

    class QVTKFrameBufferObjectRenderer : public QQuickFramebufferObject::Renderer, public vtkXOpenGLRenderWindow
    class QVTKFrameBufferObjectRenderer :
    public QQuickFramebufferObject::Renderer,
    #if __APPLE__
    public vtkCocoaRenderWindow
    #else
    public vtkXOpenGLRenderWindow
    #endif
    {
    public:
    QVTKFrameBufferObjectRenderer()
    {
    this->OffScreenRendering = 1;
    #if __APPLE__
    this->OffScreenInitialized = 1;
    #endif

    // Create a renderer and render window
    vtkRenderer *renderer = vtkRenderer::New();
    @@ -37,6 +52,9 @@ class QVTKFrameBufferObjectRenderer : public QQuickFramebufferObject::Renderer,
    virtual ~QVTKFrameBufferObjectRenderer()
    {
    this->OffScreenRendering = 0;
    #if __APPLE__
    this->OffScreenInitialized = 0;
    #endif
    }

    void render()
  15. nocnokneo revised this gist May 16, 2014. 1 changed file with 5 additions and 5 deletions.
    10 changes: 5 additions & 5 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,10 @@
    # Integrating VTK into Qt Quick 2

    This is a minimal proof-of-concept attempt at integrating VTK into a Qt Quick scene by rendering VTK to an OpenGL Framebuffer Object (FBO) and displaying that FBO in the QSG as a texture. This is a more robust integration approach than using the QSG beforeRendering or afterRendering signals as used by OpenView Core[1]
    This is a minimal proof-of-concept attempt at integrating VTK into a Qt Quick
    scene by rendering VTK to an OpenGL Framebuffer Object (FBO) and displaying
    that FBO in the QSG as a texture. This is a more robust integration approach
    than using the QSG beforeRendering or afterRendering signals (for example, as
    used by [OpenView Core](https://github.com/Kitware/openview/tree/master/core))

    ## Build Instructions

    @@ -16,7 +20,3 @@ cmake ../VtkFboInQtQuick
    make
    ./VtkFboInQtQuick
    ```

    # References

    [1] https://github.com/Kitware/openview/tree/master/core
  16. nocnokneo revised this gist May 16, 2014. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -4,6 +4,7 @@ This is a minimal proof-of-concept attempt at integrating VTK into a Qt Quick sc

    ## Build Instructions

    ```Shell
    git clone https://gist.github.com/c3fb01bb7ecaf437f7d6.git VtkFboInQtQuick
    mkdir VtkFboInQtQuick-build
    cd VtkFboInQtQuick-build
    @@ -14,6 +15,7 @@ cmake ../VtkFboInQtQuick

    make
    ./VtkFboInQtQuick
    ```

    # References

  17. nocnokneo revised this gist May 16, 2014. 1 changed file with 20 additions and 0 deletions.
    20 changes: 20 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,20 @@
    # Integrating VTK into Qt Quick 2

    This is a minimal proof-of-concept attempt at integrating VTK into a Qt Quick scene by rendering VTK to an OpenGL Framebuffer Object (FBO) and displaying that FBO in the QSG as a texture. This is a more robust integration approach than using the QSG beforeRendering or afterRendering signals as used by OpenView Core[1]

    ## Build Instructions

    git clone https://gist.github.com/c3fb01bb7ecaf437f7d6.git VtkFboInQtQuick
    mkdir VtkFboInQtQuick-build
    cd VtkFboInQtQuick-build

    # may need to add: -DVTK_DIR:PATH=<VTK_DIR> where <VTK_DIR> is the
    # path to the directory that contains VTKConfig.cmake
    cmake ../VtkFboInQtQuick

    make
    ./VtkFboInQtQuick

    # References

    [1] https://github.com/Kitware/openview/tree/master/core
  18. nocnokneo revised this gist May 16, 2014. 5 changed files with 199 additions and 0 deletions.
    97 changes: 97 additions & 0 deletions QVTKFrameBufferObjectItem.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,97 @@
    #include "QVTKFrameBufferObjectItem.h"

    #include <QtGui/QOpenGLFramebufferObject>

    #include <vtkActor.h>
    #include <vtkConeSource.h>
    #include <vtkPolyDataMapper.h>
    #include <vtkRenderWindow.h>
    #include <vtkXOpenGLRenderWindow.h>
    #include <vtkRenderer.h>
    #include <vtkSmartPointer.h>

    #include <vtkRendererCollection.h>
    #include <vtkCamera.h>

    class QVTKFrameBufferObjectRenderer : public QQuickFramebufferObject::Renderer, public vtkXOpenGLRenderWindow
    {
    public:
    QVTKFrameBufferObjectRenderer()
    {
    this->OffScreenRendering = 1;

    // Create a renderer and render window
    vtkRenderer *renderer = vtkRenderer::New();
    this->AddRenderer(renderer);
    renderer->Delete();

    // FOR TESTING
    vtkSmartPointer<vtkConeSource> polyDataSource = vtkSmartPointer<vtkConeSource>::New();
    vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
    mapper->SetInputConnection(polyDataSource->GetOutputPort());
    actor->SetMapper(mapper);
    renderer->AddActor(actor);
    }

    virtual ~QVTKFrameBufferObjectRenderer()
    {
    this->OffScreenRendering = 0;
    }

    void render()
    {
    this->GetRenderers()->GetFirstRenderer()->GetActiveCamera()->Dolly(0.8);
    this->Render(); // vtkXOpenGLRenderWindow renders the scene to the FBO
    // this->update();
    }

    QOpenGLFramebufferObject *createFramebufferObject(const QSize &size)
    {
    qDebug("VTKFrameBufferObjectRenderer: createFramebufferObject");

    QOpenGLFramebufferObjectFormat format;
    format.setAttachment(QOpenGLFramebufferObject::Depth);
    format.setSamples(4);
    QOpenGLFramebufferObject *fbo = new QOpenGLFramebufferObject(size, format);

    QSize fboSize = fbo->size();
    this->Size[0] = fboSize.width();
    this->Size[1] = fboSize.height();

    GLuint frameBufferObject = fbo->handle();
    GLuint textureObject = fbo->texture();
    // GLint depthRenderBufferObject; // qFrameBufferObject->depthBuffer(); // method not exist (yet) So...
    // fbo->bind();
    // glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
    // GL_DEPTH_ATTACHMENT,
    // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
    // &depthRenderBufferObject); // Crashes
    // fbo->release();

    // QOpenGLFramebufferObject documentation states that "The color render
    // buffer or texture will have the specified internal format, and will
    // be bound to the GL_COLOR_ATTACHMENT0 attachment in the framebuffer
    // object"
    this->BackLeftBuffer = static_cast<unsigned int>(GL_COLOR_ATTACHMENT0);
    this->FrontLeftBuffer = static_cast<unsigned int>(GL_COLOR_ATTACHMENT0);
    this->BackBuffer = static_cast<unsigned int>(GL_COLOR_ATTACHMENT0);
    this->FrontBuffer = static_cast<unsigned int>(GL_COLOR_ATTACHMENT0);

    // Save GL objects by static casting to standard C types. GL* types
    // are not allowed in VTK header files.
    this->NumberOfFrameBuffers = 1;
    this->FrameBufferObject = static_cast<unsigned int>(frameBufferObject);
    this->DepthRenderBufferObject = 0; // static_cast<unsigned int>(depthRenderBufferObject);
    this->TextureObjects[0] = static_cast<unsigned int>(textureObject);
    this->OffScreenUseFrameBuffer = 1;
    this->Modified();

    return fbo;
    }
    };

    QQuickFramebufferObject::Renderer *QVTKFrameBufferObjectItem::createRenderer() const
    {
    return new QVTKFrameBufferObjectRenderer();
    }
    15 changes: 15 additions & 0 deletions QVTKFrameBufferObjectItem.h
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,15 @@
    #ifndef QVTKFrameBufferObjectItem_h_
    #define QVTKFrameBufferObjectItem_h_

    #include <QtQuick/QQuickFramebufferObject>

    class LogoRenderer;

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

    #endif
    7 changes: 7 additions & 0 deletions VtkFboInQtQuickConfig.h.in
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,7 @@
    #ifndef VTKFBOINQTQUICKCONFIG_H_IN
    #define VTKFBOINQTQUICKCONFIG_H_IN

    #define PROJECT_SOURCE_DIR "@PROJECT_SOURCE_DIR@"
    #define PROJECT_BINARY_DIR "@PROJECT_BINARY_DIR@"

    #endif // VTKFBOINQTQUICKCONFIG_H_IN
    19 changes: 19 additions & 0 deletions main.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,19 @@
    #include "VtkFboInQtQuickConfig.h"
    #include "QVTKFrameBufferObjectItem.h"

    #include <QGuiApplication>
    #include <QQuickView>

    int main(int argc, char **argv)
    {
    QGuiApplication app(argc, argv);

    qmlRegisterType<QVTKFrameBufferObjectItem>("VtkQuick", 1, 0, "VtkRenderWindow");

    QQuickView view;
    view.setSource(QUrl(PROJECT_SOURCE_DIR "/main.qml"));
    view.setResizeMode( QQuickView::SizeRootObjectToView );
    view.show();

    return app.exec();
    }
    61 changes: 61 additions & 0 deletions main.qml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,61 @@
    import QtQuick 2.0
    import VtkQuick 1.0

    Rectangle {
    id: root

    width: 800
    height: 600
    color: "yellow"

    Rectangle {
    id : vtkRenderWindowContainer
    anchors.fill: parent
    anchors.margins: 20
    rotation: mouseArea.containsMouse ? 10 : -10
    Behavior on rotation { NumberAnimation {} }
    border.width: 4
    border.color: "black"
    color: "blue"

    VtkRenderWindow {
    anchors.fill: parent
    }
    }

    Rectangle {
    id: reactiveRect
    color: "mintcream"
    opacity: 0.8
    radius: 10
    border.width: 5
    border.color: "mintcream"

    width: 600
    height: 200

    anchors.centerIn: vtkRenderWindowContainer

    rotation: mouseArea.containsMouse ? -4 : 4
    Behavior on rotation { NumberAnimation {} }

    Text {
    id: label
    anchors.fill: parent
    anchors.margins: 20
    color: mouseArea.containsMouse ? "deeppink" : "dodgerblue"
    Behavior on color { ColorAnimation { duration: 200 } }
    wrapMode: Text.WordWrap
    font.pointSize: 16
    font.bold: true
    verticalAlignment: Text.AlignVCenter
    text: "The objects inside the blue rectangle are rendered to an FBO by QVTKFrameBufferObject. Everything else is a standard Qt Quick component."
    }

    MouseArea {
    id: mouseArea
    anchors.fill: parent
    hoverEnabled: true
    }
    }
    }
  19. nocnokneo created this gist May 16, 2014.
    20 changes: 20 additions & 0 deletions CMakeLists.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,20 @@
    cmake_minimum_required(VERSION 2.8.11)

    project(VtkFboInQtQuick)

    set(CMAKE_INCLUDE_CURRENT_DIR ON)
    set(CMAKE_AUTOMOC ON)

    find_package(VTK REQUIRED)
    include(${VTK_USE_FILE})

    find_package(Qt5Quick REQUIRED)

    configure_file(VtkFboInQtQuickConfig.h.in ${PROJECT_BINARY_DIR}/VtkFboInQtQuickConfig.h)

    add_executable(${PROJECT_NAME}
    main.cpp
    QVTKFrameBufferObjectItem.cpp
    main.qml
    )
    target_link_libraries(${PROJECT_NAME} ${VTK_LIBRARIES} Qt5::Quick)