Rendering translucent geometry intermixed with volumes
On a former blog post we discussed about the addition of dual-depth peeling to VTK (vtkDualDepthPeelingPass). As mentioned there, dual-depth peeling roughly doubled the frame rate of correctly-ordered translucent-geometry rendering when compared to legacy depth-peeling.
Rendering correctness in a rasterized scene containing translucent geometry and volumes has been a long standing issue in VTK. Understandably so, it is not simple to architecturally achieve this given the necessity for various rendering passes and resource sharing across different mappers. Likewise, achieving any reasonable performance is challenging. Recently, thanks to the performance improvements of dual-depth peeling we were able to extend the rendering pass to correctly handle intermixed translucent geometry with volumes.
Volume-peeling: additions to the dual depth-peeling algorithm
Dual-depth peeling for geometry computes color and depth of front and back layers (peels) in a single render pass, computed colors are accumulated in separate buffers and the updated depths are used to feed the next pair of peels in a following render pass. In order to handle volumes, the resulting depths obtained from a geometry-peeling pass are used as entry/exit points for ray-casting in an additional pass where the volume mapper is invoked, essentially rendering the peels of volume contained within peels of geometry. As with translucent geometry, a single render-pass accommodates both front and back ray-casting of the current peels. Sections of the volume not enclosed within translucent geometry are rendered altogether in a separate pass at the beginning (before the peeling passes) and the computed fragment colors are used to initialize the front and back rendering targets.
The following example shows some of the passes to render a frame from TestGPURayCastDepthPeeling. This test renders a volume vase enclosed in two transparent polygonal spheres.
Initial volumetric pass rendering sections not enclosed in translucent geometry (PeelVolumesOutsideTranslucentRange()):
First volumetric peel (PeelVolumetricGeometry()), the resulting depths from the first translucent geometry peel (PeelTranslucentGeometry()) are used as entry/exit points for ray-casting:
Final state of the accumulation buffers before its final composition:
Additions to the API
Volume-peeling is currently off by default and needs to be explicitly enabled. As with the rest of the API, it is directly exposed through the renderer.
vtkNew<vtkRenderer> ren;
ren->SetUseDepthPeelingForVolumes(true);
Performance notes
As before, performance highly depends on the geometry complexity (for higher complexity, higher number of passes are required for a full set of correctly ordered fragments). In addition, when volume-peeling is enabled performance will also depend on the ray-sampling distance. Our initial benchmark suggests that the time spent rendering volume peels is far greater than the time spent drawing the translucent geometry, so adjusting volume mapper settings will have a significant impact on performance. In addition, the accumulated time spent peeling the volumes is around 75% greater than the time required to render them without peeling. This appears to be due to the overhead of repeatedly initializing the ray-casting code as we switch between volumetric and translucent geometry, so limiting the number of peels (and thus ray-cast initializations) will have significant performance impacts.