Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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 a vtkExternalRenderWindow to render to before filling out the FBO (I think).

    This is what the chart looks like:
    0_1536935965084_Screen Shot 2018-09-14 at 9.38.56 AM.png
    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.


Log in to reply