Screen-Space Ambient Occlusion in VTK 9.0
When rendering geometries in VTK, we can now achieve great results with the newly introduced PBR shading. We just have to configure properly lights, HDRI and materials. However, with complex surfaces like CAD models, something is clearly missing and the rendered image looks fake as illustrated in Figure 1.
Algorithm
Our depth perception is highly sensitive to ambient occlusion. Holes, creases, concave surfaces are occluded by the surrounding geometry. This has to be taken into account when computing illumination. In VTK 9.0, we have added a new render pass called Screen-Space Ambient Occlusion (SSAO). This technique, introduced in 2007 by Crytek, is an efficient alternative to raytracing to approximate ambient occlusion. While only an approximation, it produces very plausible result in real-time. The Figure 2 shows a complex geometry (~3M cells) rendered at 150fps on a RTX 2060 GPU.
In order to compute the ambient occlusion, the render pass modify the PolyDataMapper to save pixels positions and normals in new GPU textures. These textures are used by the SSAO algorithm in order to generate a new occlusion texture that can be combined to the color buffer. The algorithm is illustrated in Figure 3.
Usage
In order to enable SSAO in VTK, it is necessary to create a custom render pass pipeline. Several parameters can be used to configure this render pass:
- Radius: neighbor pixels considered when computing the occlusion
- Bias: tolerance factor used when comparing pixel depth
- KernelSize: number of samples used (controls the quality)
- Blur: controls if occlusion buffer should be blurred before combining it with the color buffer.
An example of a simple render pass pipeline can be found below.
vtkNew<vtkRenderStepsPass> basicPasses;
double sceneSize; // e.g. the diagonal of the bounding box
vtkNew<vtkSSAOPass> ssao;
ssao->SetRadius(0.1 * sceneSize); // comparison radius
ssao->SetBias(0.001 * sceneSize); // comparison bias
ssao->SetKernelSize(128); // number of samples used
ssao->BlurOff(); // do not blur occlusion
ssao->SetDelegatePass(basicPasses);
glRenderer->SetPass(ssao);
Thanks for the great article. It was an incentive to try it within ParaView. Has Kitware consider adding the GUI components (similar to the FXAA) to make that process simpler?
Could you provide more hints about setting the Radius? Should it be related to the diagonal of the 3D bounding box of the object(s)? I found out that most default parameters were good. Radius was the one I needed to tweak.
This has been merged in ParaView ! a blog is coming soon !