MacOSX integration with VTK on QQuickFramebufferObject
-
I'm currently working to integrate VTK into the rendering process of my QtQuick app. I currently am displaying a chart through a QQuickFramebufferObject in a window. I currently have an issue with how the chart is being displayed though, I believe the issue to be my configuration of OpenGL in Qt or something, as the examples given by the VTK community look much better. The issue I'm looking at is that the axis text look off (I'm not sure how to describe it), as well as some of the lines in a
vtkChartXY
(they aren't being antialiased or something). The code I've written is loosely based on an example here: https://github.com/nicanor-romero/QtVtk . In summary, it uses avtkExternalRenderWindow
to render to before filling out the FBO (I think).This is what the chart looks like:
As you can see, the axis text looks a bit off and I can't figure out how to smooth anything (SetLineSmoothing
does nothing).This is the main rendering header file:
class DepthChartView; class DepthChartRenderer : public QObject, public QQuickFramebufferObject::Renderer, protected QOpenGLFunctions { Q_OBJECT public: DepthChartRenderer(); virtual void synchronize(QQuickFramebufferObject * item); virtual void render(); virtual void openGLInitState(); QOpenGLFramebufferObject * createFramebufferObject(const QSize & size); private: void initScene(); DepthChartView * m_vtkFboItem = nullptr; uint m_realTime; vtkSmartPointer<vtkExternalOpenGLRenderWindow> m_vtkRenderWindow; vtkSmartPointer<vtkRenderer> m_renderer; vtkSmartPointer<vtkGenericRenderWindowInteractor> m_vtkRenderWindowInteractor; std::map<std::string, std::vector<uint>> m_bpdAnimationFrames; std::map<std::string, std::vector<uint>> m_cpdAnimationFrames; vtkSmartPointer<vtkTable> m_bpdTable; std::vector<std::vector<vtkSmartPointer<vtkTable>>> m_cpdTables; vtkSmartPointer<vtkChartXY> m_chart; vtkSmartPointer<vtkContextView> m_view; vtkPlot * m_bpdLine; std::vector<std::vector<vtkPlot *>> m_cpdLines; std::vector<uint> r = {255, 0, 0}; std::vector<uint> g = {0, 255, 0}; std::vector<uint> b = {0, 0, 255}; bool m_firstRender = true; };
And this is the source for it:
DepthChartRenderer::DepthChartRenderer() : m_realTime(0), m_bpdAnimationFrames(), m_cpdAnimationFrames(), m_bpdLine(0), m_cpdLines() { // Renderer m_vtkRenderWindow = vtkSmartPointer<vtkExternalOpenGLRenderWindow>::New(); m_renderer = vtkSmartPointer<vtkRenderer>::New(); m_vtkRenderWindow->AddRenderer(m_renderer); // Initialize the OpenGL context for the renderer m_vtkRenderWindow->OpenGLInitContext(); update(); } void DepthChartRenderer::synchronize(QQuickFramebufferObject * item) { // For the first synchronize if (!m_vtkFboItem) { m_vtkFboItem = static_cast<DepthChartView *>(item); } if (!m_vtkFboItem->isInitialized()) { m_vtkFboItem->setVtkFboRenderer(this); emit m_vtkFboItem->rendererInitialized(); } int * rendererSize = m_vtkRenderWindow->GetSize(); if (m_vtkFboItem->width() != rendererSize[0] || m_vtkFboItem->height() != rendererSize[1]) { m_vtkRenderWindow->SetSize(m_vtkFboItem->width(), m_vtkFboItem->height()); } // Copy animation frames for (auto entry : m_vtkFboItem->m_bpdAnimationFrames) { m_bpdAnimationFrames[entry.first] = entry.second; } m_vtkFboItem->m_bpdAnimationFrames.clear(); for (auto entry : m_vtkFboItem->m_cpdAnimationFrames) { m_cpdAnimationFrames[entry.first] = entry.second; } // Create the chart if (!m_chart) { // Add multiple line plots, setting the colors etc m_chart = vtkSmartPointer<vtkChartXY>::New(); m_chart->GetAxis(vtkAxis::BOTTOM)->SetTitle("Depth"); m_chart->GetAxis(vtkAxis::LEFT)->SetTitle("#BT"); m_chart->GetAxis(vtkAxis::RIGHT)->SetTitle("#Calls"); } /* * Update plot content */ if (!m_view) { // Set up the view m_view = vtkSmartPointer<vtkContextView>::New(); m_view->SetRenderWindow(m_vtkRenderWindow); m_view->GetRenderer()->SetBackground(1.0, 1.0, 1.0); m_view->GetScene()->AddItem(m_chart); m_view->GetInteractor()->Initialize(); m_view->GetInteractor()->Start(); } } void DepthChartRenderer::render() { m_vtkRenderWindow->PushState(); this->openGLInitState(); m_vtkRenderWindow->Start(); if (m_firstRender) { this->initScene(); m_firstRender = false; } // Render m_vtkRenderWindow->Render(); m_vtkRenderWindow->PopState(); m_vtkFboItem->window()->resetOpenGLState(); } void DepthChartRenderer::openGLInitState() { m_vtkRenderWindow->OpenGLInitState(); m_vtkRenderWindow->MakeCurrent(); QOpenGLFunctions::initializeOpenGLFunctions(); QOpenGLFunctions::glEnable(GL_MULTISAMPLE); QOpenGLFunctions::glEnable(GL_LINE_SMOOTH); QOpenGLFunctions::glUseProgram(0); } QOpenGLFramebufferObject * DepthChartRenderer::createFramebufferObject(const QSize & size) { QSize macSize = QSize(size.width() / 2, size.height() / 2); QOpenGLFramebufferObjectFormat format; format.setAttachment(QOpenGLFramebufferObject::Depth); #ifdef Q_OS_MAC std::unique_ptr<QOpenGLFramebufferObject> framebufferObject(new QOpenGLFramebufferObject(macSize, format)); #else std::unique_ptr<QOpenGLFramebufferObject> framebufferObject(new QOpenGLFramebufferObject(size, format)); #endif m_vtkRenderWindow->SetBackLeftBuffer(GL_COLOR_ATTACHMENT0); m_vtkRenderWindow->SetFrontLeftBuffer(GL_COLOR_ATTACHMENT0); m_vtkRenderWindow->SetBackBuffer(GL_COLOR_ATTACHMENT0); m_vtkRenderWindow->SetFrontBuffer(GL_COLOR_ATTACHMENT0); m_vtkRenderWindow->SetSize(framebufferObject->size().width(), framebufferObject->size().height()); m_vtkRenderWindow->SetOffScreenRendering(true); m_vtkRenderWindow->Modified(); return framebufferObject.release(); } void DepthChartRenderer::initScene() { m_vtkRenderWindow->SetOffScreenRendering(true); }
I'm running this on the newest Macbook Pro 2018 with Qt 5.11.1 and VTK 8.1.1. I can't think of any other useful information at the moment. If there is anything else I can provide, please let me know. I feel like it has to do with something in the
QQuickFramebufferObject
surface formatting, since I can run vtk qt examples just fine, but I don't know what to look for anymore.