The QVTKWidget is dead. Long live the QVTKWidget?
"I play games today, and I know if the developer cares about every pixel or not. Caring about every pixel on the screen is important. Every pixel is important." Chris Taylor, the developer of Total Annihilation (the pinnacle of RTS games ever), cited from his talk. We're not game devs, but we're all into graphics anyway.
There is something strange about this new QVTKOpenGLNativeWidget class that is supposed to replace the good old QVTKWidget. You can find the problem definition in the corresponding ticket #17154 that remains in the open state for already two years or so. It seems that after some preliminary analysis, this issue was somehow abandoned. The funny thing is that the same day that I started my playing with the antialiasing (AA) again, that evil #17154 ticket got an update from Ken Martin, an architect of VTK and cofounder of Kitware (I'm always thrilled seeing cofounders keeping hands dirty).
Rendering with QVTKOpenGLNativeWidget and polygon offset enabled for resolving coincident primitives.
You can appreciate the difference between the rendering results using one or another Qt widget looking at the green line in the images above and below. Notice a small amount of noise that the old QVTKWidget happened to avoid producing thanks to its specialized way of rendering (via the QPainter utility class). The things are not that perfect with the new widget, and it starts to annoy after days and weeks of usage (and especially if you know it could work better). Btw, Kitware devs explained that they decided to move to the new approach because of some bugs and limitations in Paraview.
Rendering with the old QVTKWidget without polygon offsets.
Actually, the adjustment of visual settings in Analysis Situs is a time killer to me. So many weekends were wasted just to configure some VTK props, and all these efforts were simply tossed out with upcoming releases and testing on new platforms. So, here's another round of ticking on and off that random set of visualization tumblers. Okay, since QVTKOpenGLNativeWidget does not do the job, I've finally decided to copy and paste the old QVTKWidget sources into the project (shame on me). Although that's seemingly a straightforward thing, such a workaround does have a price:
- There is no confidence that the old widget will compile with upcoming releases of VTK. What was the burden of Kitware now becomes the burden of yours, and given that I have zero knowledge in OpenGL plus a little knowledge of Qt, that's going to bite. Then, even if it compiles, who knows how smoothly it's going to work (spoiler: it's going to yield really strange bugs for QDockWidgets that are sometimes not updated after docking them around).
- The widget is deprecated since VTK 8.2, so to make it alive, you'd need to adjust the sources a bit or take them from an older version of VTK. That's not a big deal, of course.
- It's an ugly approach. Really, it sucks.
One can take the widget and its related classes from any VTK version up to ver. 8.2 (there's some difference in QVTKWidget sources between 8.0 and 8.2, but it looks cosmetics mostly).
git clone https://gitlab.kitware.com/vtk/vtk.git vtk-old cd vtk-old git checkout v8.0.1
There are two classes to grab for reviving the old widget:
QVTKWidget -> MyQVTKWidget QVTKPaintEngine -> MyQVTKPaintEngine
Once absorbed, it's a good idea to give those classes new names to avoid name conflicts with the VTK's baseline. After preliminary tests, the visualization looked better than with QVTKOpenGLNativeWidget, so the patch was merged to the master branch of Analysis Situs. Also, that backporting did not affect offscreen rendering as the latter does not rely on any Qt widgets.
At the same time, there was something absolutely crazy about UI bugs induced by that "fix." Have a look at the animation below:
The title bar got stuck in a non-updated state and there is nothing the end-user can do about this: even minimizing and maximizing the whole window does not help. The following line appeared to be the cause of that problem:
QSurfaceFormat::setDefaultFormat( QVTKOpenGLNativeWidget::defaultFormat() );
It's no surprise in fact, as adding this line is one of the things you have to do when migrating from QVTKWidget to QVTKOpenGLNativeWidget. On backporting, this stuff has to go away. If not, it begins to take revenge. Another strange thing, however, is that after eliminating setDefaultFormat() I've got AA not working on Linux. Here is how it looked like:
Broken AA on Linux.
So, on Linux, it's not that simple. The following code can be used to set the surface format (copied from QVTKOpenGLNativeWidget):
#ifndef _WIN32 QSurfaceFormat fmt; fmt.setRenderableType(QSurfaceFormat::OpenGL); fmt.setVersion(3, 2); fmt.setProfile(QSurfaceFormat::CoreProfile); fmt.setSwapBehavior(QSurfaceFormat::DoubleBuffer); fmt.setRedBufferSize(1); fmt.setGreenBufferSize(1); fmt.setBlueBufferSize(1); fmt.setDepthBufferSize(1); fmt.setStencilBufferSize(0); fmt.setAlphaBufferSize(1); fmt.setStereo(false); fmt.setSamples( vtkOpenGLRenderWindow::GetGlobalMaximumNumberOfMultiSamples() ); QSurfaceFormat::setDefaultFormat(fmt); #endif
It makes rendering a bit smoother as the following snapshot illustrates:
AA on Linux with QSurfaceFormat::setDefaultFormat().
At the same time, there is no problem with dockable widgets on Linux (at least on my Ubuntu 18_04) when setting up the default surface format, so I wrapped this piece of code with that dirty #ifndef _WIN32.
To conclude, I put my hopes in VTK developers to burn down that annoying regression with AA officially.
Want to discuss this? Jump in to our forum.