This is my final report on improving volume rendering in Cycles. At the beginning of GSoC, I proposed to implement the following features:
- Compression of sparse volume textures to lower memory requirements.
- Importing of external OpenVDB files to render in Cycles.
- Begin work on implementing a native Volume primitive in Blender.
- Optionally, implement volumetric motion blur.
I am happy to say that three out of the four features above have for the most part been successfully completed, and barring minor bug-fixes, is ready for merging with the Blender 2.8 branch. You may try out these features in this branch. While I have done some minor work on the Volume primitive, it is quite a large task and has not been worked on for some time unfortunately.
Sparse Volume Textures
Volumes tend to be very large in memory size compared to other types of primitives, while at the same time, many volumes contain huge swaths of uniform data values. Following the philosophy outlined by OpenVDB and NVIDIA GVDB Voxels, it is much more memory efficient to only store "active" voxels of the volume. The threshold of which values can be considered active can be set using Physics panel > Smoke Domain > Empty Space option.
The amount of memory saved is dependant upon the size and nature of the volume, though it usually hovers around 33-50% smaller. Irregularly shaped volumes and/or narrow-band level sets can be reduced by as much as 75% of the original memory footprint, even usually requiring less memory than an equivalent OpenVDB grid. Rendering using CUDA reduces the amount of memory saved (~80% of dense memory usage) since the compressed texture must be padded to be compatible with the texture sampler.
This feature comes with a minor trade-off in rendering time, since there is some extra calculation required to look up voxels in the sparse grid as opposed to direct array access normally. An example of memory and time usage with rendering a VDB converted to a sparse grid:
- Dense Grid: 551.45M, Time: 03:07:42
- Sparse Grid: 130.06M, Time: 03:18:57
- VDB Grid: 137.86M
(Space reduced by 76.4%, Time increased by 6.0%)
Right now, sampling has yet to be tested for GPU rendering, though it should in theory work fine.
Building upon previous work in integrating OpenVDB in Blender in general by Kevin Dietrich and importing in particular by Luca Rood, OpenVDB files can now be imported to and previewed in Blender, as well as rendered in Cycles. With the previously mentioned compression, VDBs can be easily rendered due to the much the much higher memory ceiling.
When building Blender with OpenVDB features enabled, users can import a .vdb by going to File > Import > OpenVDB (.vdb). This creates a new special smoke domain object containing the VDB data. The domain can be scaled, translated, rotated, etc. just like any other normal smoke domain.
As the UI for this feature is not entirely decided upon yet, most other smoke settings for the "special" domain are disabled. The implementation is somewhat limited on the user's part, as the VDBs cannot be edited and cannot interact e.g. with collision objects. Right now, the only way to expose the VDB settings panel is via the menu import.
The new settings:
- File Path - file path of VDB to import
- Simplify - simplifies the preview of the VDB in case it is too large for the memory. Larger values give less detailed previews.
- Multiple import - treats the path in "File Path" as one file in a animation and series and will attempt to import the rest of the animation. For example, if we have some files abc001.vdb, abc002.vdb, abc003.vdb, etc., with "Multi Import" checked, we can put any of the files in "File Path" and Blender and Cycles will automatically check for the rest of the VDBs and will math the files with the frames specified by the numbers at the end of their filename.
For Cycles to render the smoke grids, the Attribute nodes must be used exactly the same as they are currently used to pass Blender smoke data to Cycles. For example, to render a "density" grid from a VDB, the smoke domain's material must have an attached Attribute node "density". Since Cycles is informed of the existence of grids in the file via Attribute nodes, this means that only grids with names that are valid smoke attributes can be imported. They are as follows:
Note that the VDB grid's name must match the attribute names above, or they will not be imported.
- When importing a single VDB file, it will appear on all frames of an animation by default.
- Currently, the viewport can preview VDBs in Blender 2.79, but not in Blender 2.8. However, in 2.8, the bounding box is still available to view and edit, and Cycles is unaffected.
- Currently, VDB grids will only be imported as smoke, as there is no support for point data.
- Common grid types such as Double, Bool, Float, Int32, Int64, Vec3D, etc. are supported, but will be converted to floats internally.
Volume Motion Blur
The Eulerian motion blur algorithm was chosen for simulating smoke motion blur since it utilizes the already exisiting velocity data from Blender generated smoke. Using TUVs was originally considered but is rather impractical as it would require a complete restructure of how Cycles handles volume textures and is excessively memory heavy. It would be better to provide a simpler option, and in the future TUVs could perhaps be implemented as an alternative to Eulerian blur.
With "Motion Blur" enabled in the "Render" panel, the user may activate motion blur for a volume by selecting its smoke domain, going to the Object Panel > Motion Blur, and checking "Volume". Steps must also be greater than 0, although this value does not affect motion blur otherwise.
One interesting trick is that motion blur can be used to lessen pixelation in low-division smoke (such as in the sample render here), which may be helpful for rendering good looking smoke on computers with less memory available.
Note that enabling motion blur greatly increases rendering time since velocity grids tend to be composed almost entirely of high value voxels which means that the mesh builder speedup does not work well on it. It may be possible to improve the mesh builder to ignore voxels even with high value velocities.
For motion blur, further testing still needs to be done with a variety of different smokes to see if the effects of the blurring are acceptable.
I would like to thank my mentors Stefan and Lukas as well as Brecht and others on #cycles for helping and providing feedback and suggestions over the course of this GSoC. I really enjoyed working on a project as large as Cycles and Blender, and creating features that may be greatly useful to many people. I would really like to be able to continue to contribute to Cycles and Blender in the future, now that I am much more familiar with many aspects of the codebase.