Antialiasing in in slice (MPR) views

Hi everyone,
I was wondering if there was an easy way to reduce aliasing effects in MPR view of the orientation interactor and models.
Screenshot from 2021-12-20 10-52-56

We are developing on slicer 4.11.20210226 but this is also visible on master branch

Thanks for any tips,
Pierre

You can try the antialiasing settings in the View panel. It doesn’t work on all platforms in my experience - it would be good if people could experiment and maybe we can track down when it does and doesn’t help.

Thank you very much Steve it is exactly what I was looking for.
Cheers,
Pierre

Multi-sampling is the true antialiasing method, but that would mess with the Z buffer, and therefore with hardware-accelerated picking that is used for markup nodes label display and control point manipulation, compositing volume rendering and surface rendering, etc. Also as @pieper mentioned there seem to be some some issues with it in recent VTK and Qt versions (for example, I don’t think the MSAA setting has any effect right now on Windows).

Alternatively, you can do screen-space antialiasing using FXAA. It is very fast and simple, but it can alter any displayed content in the renderer (may makes boundary of line-like structures blurry), so it can be applied safely to renderers such as 2D overlays (markup interactors, labels, etc.), but need to be careful with applying to renderers that display images.

You can enable FXAA to all renderers of a slice or 3D views using this code snippet:

def enableFXAA(view, enable):
    renderWindow = view.renderWindow()
    renderers = renderWindow.GetRenderers()
    for renderer in renderers:
        renderer.SetUseFXAA(enable)
    slicer.util.forceRenderAllViews()

# For slice view:
enableFXAA(slicer.app.layoutManager().sliceWidget('Red').sliceView(), True)

# For 3D view:
# enableFXAA(slicer.app.layoutManager().threeDWidget(0).threeDView(), True)

FXAA has trouble with smoothing thin lines and may cause various artifacts. So, while it is extremely fast and simple, it would need some more experimentation to see how it could be utilized in Slicer.

Finally, there is also a computationally expensive but high-quality option: using an SSAAPass (render into higher-resolution image and sample down). You can try it with this code snippet:

def setupSSAA(view, enable):
    renderWindow = view.renderWindow()
    renderer = renderWindow.GetRenderers().GetFirstRenderer()
    # create the basic VTK render steps
    basicPasses = vtk.vtkRenderStepsPass()
    # finally blur the resulting image
    # The blur delegates rendering the unblured image
    # to the basicPasses
    ssaa = vtk.vtkSSAAPass()
    ssaa.SetDelegatePass(basicPasses)
    # tell the renderer to use our render pass pipeline
    if enable:
        renderer.SetPass(ssaa)
    else:
        renderer.SetPass(basicPasses)
    slicer.util.forceRenderAllViews()

#setupSSAA(slicer.app.layoutManager().sliceWidget('Red').sliceView(), True)
setupSSAA(slicer.app.layoutManager().threeDWidget(0).threeDView(), True)

This works quite nicely, but it tends to make thin lines much thinner, and it messes up Z buffer similarly to MSAA (volume rendering is not composited correctly with surfaces, depth peeling does not work, etc.). I haven’t experimented with it much, maybe these issues can be addressed.

I would also mention that I have a hi-dpi laptop and I can barely see aliasing artifacts. So, in some cases upgrading the hardware might be an option, too.

Thank you, Andras, for this complete explanation. I am on Linux and the MSAA is working. I will test other solutions too.

Would it make sense to you to combine MSAA and FXAA?

I’m not sure if combining MSAA and FXAA (applying both of them at the same time) would be useful, because the benefit would be marginal, if any, but all the drawbacks and limitations would be combined.

Even though all 3 current anti-aliasing methods have very serious limitations, it could make sense to expose them on the GUI to allow users experiment with it.