Anti-Aliasing#

Demonstrate anti-aliasing within PyVista.

PyVista supports three types of anti-aliasing:

  • SSAA - Super-Sample Anti-Aliasing

  • MSAA - Multi-Sample Anti-Aliasing

  • FXAA - Fast Approximate Anti-Aliasing

By default, MSAA anti-aliasing is enabled using 8 samples. This is the default for VTK.

>>> import pyvista as pv
>>> pv.global_theme.multi_samples
8

You can enable additional line smoothing by enabling SSAA or FXAA

Which anti-aliasing technique should you use?

Normally, the default MSAA anti-aliasing should be sufficient as it strikes a balance between efficiency and quality. If you desire additional smoothing, you can either increase the number of multi_samples or use SSAA. Low-end PCs should consider FXAA.

from __future__ import annotations

import pyvista as pv

mesh = pv.Icosphere()

No Anti-Aliasing#

First, let’s show a plot without any anti-aliasing using disable_anti_aliasing().

pl = pv.Plotter()
pl.add_mesh(mesh, style='wireframe', color='k', line_width=2)
pl.disable_anti_aliasing()
pl.camera.zoom(1.5)
pl.show()
anti aliasing

Default: Multi-Sample Anti-Aliasing (MSAA)#

Next, let’s show the default anti-aliasing configuration. By default, PyVista uses 8 samples of MSAA.

MSAA, or Multi-Sample Anti-Aliasing is an optimization of SSAA that reduces the amount of pixel shader evaluations that need to be computed by focusing on overlapping regions of the scene. The result is anti-aliasing along edges that is on par with SSAA and less anti-aliasing along surfaces as these make up the bulk of SSAA computations. MSAA is substantially less computationally expensive than SSAA and results in comparable image quality.

pl = pv.Plotter()
pl.add_mesh(mesh, style='wireframe', color='k', line_width=2)
pl.camera.zoom(1.5)
pl.show()
anti aliasing

You can increase the smoothing by increasing multi_samples using enable_anti_aliasing().

pl = pv.Plotter()
pl.add_mesh(mesh, style='wireframe', color='k', line_width=2)
pl.enable_anti_aliasing('msaa', multi_samples=16)
pl.camera.zoom(1.5)
pl.show()
anti aliasing

Fast Approximate Anti-Aliasing (FXAA)#

FXAA is the most performant of all three anti-aliasing techniques. This is because, in terms of hardware or GPU, FXAA is not that demanding. It directly smooths the 2D image and this reduces the strain on the GPU, making it best for low-end PCs.

Because FXAA only operates on the rendered image, FXAA may result in smoothing out parts of the visual overlay that are usually kept sharp for reasons of clarity as well as smoothing out textures. In general, FXAA is inferior to MSAA and SSAA.

Note how the line width has been adjusted for consistency.

pl = pv.Plotter()
pl.add_mesh(mesh, style='wireframe', color='k', line_width=1.5)
pl.camera.zoom(1.5)
pl.enable_anti_aliasing('fxaa')
pl.show()
anti aliasing

Super-Sample Anti-Aliasing (SSAA)#

SSAA, or Super-Sample Anti-Aliasing is a brute force method of anti-aliasing. It results in the best image quality but comes at a tremendous resource cost. SSAA works by rendering the scene at a higher resolution. The final image is produced by downsampling the massive source image using an averaging filter. This acts as a low pass filter which removes the high frequency components that would cause jaggedness.

Note how the line width has been adjusted for consistency.

pl = pv.Plotter()
pl.add_mesh(mesh, style='wireframe', color='k', line_width=4)
pl.camera.zoom(1.5)
pl.enable_anti_aliasing('ssaa')
pl.show()
anti aliasing

Compare render time#

You can compare the time to render for each one of the anti-aliasing approaches with:

n_render = 100
for anti_aliasing in [False, 'fxaa', 'msaa', 'ssaa']:

    pl = pv.Plotter(off_screen=True)
    pl.add_mesh(mesh, style='wireframe', color='k', line_width=4)
    pl.camera.zoom(1.5)
    if anti_aliasing:
        pl.enable_anti_aliasing(anti_aliasing)
    else:
        pl.disable_anti_aliasing()
    pl.show(auto_close=False)
    tstart = time.time()
    # repeately trigger a render via saving a screenshot
    for __ in range(n_render):
        pl.screenshot('tmp.png')
    telap = (time.time() - tstart)/n_render

    print(f'Render time for {str(anti_aliasing):6}: {telap*1000:.3f} ms')

Here are the timings from an NVIDIA Quadro P2000 and a Intel(R) Xeon(R) E-2288G CPU @ 3.70GHz:

Render time for False : 37.045 ms
Render time for fxaa  : 40.458 ms
Render time for msaa  : 42.566 ms
Render time for ssaa  : 51.450 ms

%% .. tags:: plot

Total running time of the script: (0 minutes 1.465 seconds)

Gallery generated by Sphinx-Gallery