Current challenges:
OpenVDB effects are never used in real time due to the intensive computational resources required:
High Memory Usage: OpenVDB sequences require a significant amount of memory to store and process. This can be particularly problematic for tech artists who need to work with complex scenes and high-resolution volumetric effects. The high memory footprint can lead to slowdowns and limit the ability to iterate quickly, as scenes take longer to load and modify.
Costly Volume Rendering: Rendering volumetric data, such as smoke, fire, and clouds, in real time, is computationally expensive. Traditional rendering methods consume substantial processing power, leading to lower frame rates and suboptimal performance, especially on mid- to low-end hardware. This can be a major bottleneck for tech artists who need to maintain high visual fidelity while ensuring smooth performance.
Bandwidth Bottlenecks: Unreal Engine’s standard volumetric rendering can create bandwidth bottlenecks, particularly when streaming large VDB sequences from memory to the GPU. This can cause frame rate drops and hinder the ability to achieve real-time rendering, which is crucial for interactive applications and live previews.
Solution:
ZibraVDB addresses these challenges by enabling the compression of VDB sequences and loading them entirely into VRAM. Each frame is then decompressed on-the-fly using the GPU, significantly reducing memory footprint and eliminating the bandwidth bottleneck associated with Unreal SVT.
Moreover, ZibraVDB features its own volumetric renderer, which is 2-3 times faster than Unreal's implementation, allowing for real-time rendering of VDBs of any size.
Realization process:
The entire demo creation process can be divided into several stages: creating VDB effects, compressing and importing effects into Unreal Engine, art directing VFX, and performing optimization steps to enhance demo performance across a range of consumer GPU devices.
VDB effects creation
The scene contains two looped VDB effects:
⚫️ Burning Car Fire: 15.2 GB, 150 frames, 3 channels.
⚫️ Fog: 1.8 GB, 240 frames, 1 channel.
Initially, both effects were created in Embergen. However, we decided to recreate them in Houdini using the Axiom plugin by Theory Accelerated. There are several reasons for this:
Noise in Embergen’s Simulations: Embergen often produces noise in its simulations. Although it has a built-in noise reduction filter, it is often insufficient.
Channel Requirements: For the best smoke and fire simulations, Embergen requires exporting three channels: density, flames, and temperature. In contrast, Axiom can achieve high-quality results with only two channels, such as density and temperature.
Quality and Resolution: Simulations created in Axiom generally look better than those in Embergen when using identical grid sizes. This allows us to use a lower resolution while still maintaining good quality.
Considering these factors, we created more optimized VDB sequences in Houdini using Axiom:
⚫️ Burning Car Fire: 3 GB, 150 frames, 2 channels.
⚫️ Fog: 0.8 GB, 180 frames, 1 channel.
The number of frames remained the same in order to maintain the occupied VRAM without affecting the framerate.
While we could compress the original effects with a higher compression rate, this would impact quality and only reduce decompression time, not the rendering time, since the number of voxels remains the same.
Compressing and Importing into Unreal Engine
The next step was to compress and import these effects into Unreal Engine. Using ZibraVDB, the process is straightforward: simply select the VDB frames, choose the compression quality, and press a button. After compression, our effects have the following sizes:
⚫️ Burning Car Fire: 0.2 GB
⚫️ Fog: 0.04 GB
Once compressed, you can easily drop your ZibraVDB asset into the scene without any additional setup, such as creating materials, as is required with Unreal’s heterogeneous volumes.
Visual and Rendering Optimization
The visual effects in the scene are controlled through the ZibraVDB actor’s parameters, allowing you to:
⚫️ Change the density and color of each channel.
⚫️ Illuminate effects with multiple lights of different types.
⚫️ Enable self-shadowing from each light.
⚫️ Receive shadows from other objects.
⚫️ Control the intensity of illumination or shadowing from each light type.
⚫️ Control playback manually, using either blueprints or the sequencer.
For this demo, we placed multiple animated point lights inside the fire to create the effect of the fire illuminating the scene and the smoke. Streetlights illuminate the smoke from above using spotlights, and police car lights add colored illumination to both effects.
ZibraVDB gives you enough control over renderer parameters for ideal optimization. We have optimized the ray marcher by reducing the number of steps and step size. This hasn’t affected the quality, but has reduced the rendering time a bit.
As for the fog effect, all shadows were turned off since the VFX is not very dense, and shadows do not contribute to the visual look. We have also turned off directional light shadows for the burning car effect, since it is a night scene and the light is not intense enough to make the difference.
Finally, we’ve changed the scalability settings from High to Medium to improve the scene frame time.
Gameplay
With the visuals complete, we've introduced new gameplay elements to enhance interactivity.
⚫️ Players can explore the scene using a flashlight to illuminate different areas.
⚫️ They can also toggle the police car lights on and off.
This creates a more interactive experience, as players can dynamically influence the illumination of static effects.
Fine-tuning the visuals:
As a result, we have created a demo scene where the final optimized version runs at 60+ FPS on an AMD RX5700XT in Full HD. The VDB rendering takes 4ms per frame.
While further compression could enhance performance, we prioritized maintaining the high quality of the original sequence.
Additionally, we plan to introduce new features to further optimize the effects:
⚫️ Support for Downscaled Channels: For instance, downscaling the temperature channel can significantly reduce size, without any noticeable visual impact.
⚫️ Separate Compression Quality for Each Channel: Different channels require varying levels of detail. Compressing channels individually will improve the overall compression rate.