Cycles: volume sampling improvements #92570

Open
opened 2021-10-28 14:43:47 +02:00 by Brecht Van Lommel · 18 comments
- [ ] [Product importance sampling ](https://graphics.pixar.com/library/CandidateSampling/) - [ ] [Null scattering ](https://cs.dartmouth.edu/wjarosz/publications/miller19null.html) - [ ] Density bounds - [ ] Volume BVH - [ ] Motion blur: clamp/discard velocity vectors with too high magnitude
Author
Owner

Changed status from 'Needs Triage' to: 'Confirmed'

Changed status from 'Needs Triage' to: 'Confirmed'
Author
Owner

Added subscriber: @brecht

Added subscriber: @brecht
Member

Added subscriber: @Alaska

Added subscriber: @Alaska

Added subscriber: @Emi_Martinez

Added subscriber: @Emi_Martinez

Added subscriber: @GeorgiaPacific

Added subscriber: @GeorgiaPacific

Added subscriber: @webanck

Added subscriber: @webanck

Added subscriber: @Garek

Added subscriber: @Garek
Author
Owner

Memory dump on the Volume BVH idea:

OpenVDB/NanoVDB by itself already stores the volume in a tree structure, with inner nodes that contain leaf nodes, and leaf nodes that contain voxels. NanoVDB also comes with a traversal function in nanovdb/util/HDDA.h that we may be able to use, or adapt.

However we need something on top of that, since a scene can contain multiple objects, and these may be rotated or scaled, or the same object may be instanced multiple times. This I think is the main problem to solve, to find which object instances (potentially) overlap a ray segment from point A to B. For that, we can use a fairly simple BVH structure based on bounding boxes of each object, it doesn't need to be super optimized. And then gather that list of objects in an array in the kernel before volume shading.

Then as a second step, that BVH could be made more fine grained. Instead of the full object bounding box, you could put inner or leaf node bounding boxes into the BVH, to avoid more false positives.

Making the BVH work all the way down to the voxel level (with an algorithm like HDDA) would be a good optimization too, however that's not a requirement for an initial implementation. In some ways this is an orthogonal problem, and would require some deeper rethinking of how we do volume stepping in the shade_volume kernel.

Memory dump on the Volume BVH idea: OpenVDB/NanoVDB by itself already stores the volume in a tree structure, with inner nodes that contain leaf nodes, and leaf nodes that contain voxels. NanoVDB also comes with a traversal function in `nanovdb/util/HDDA.h` that we may be able to use, or adapt. However we need something on top of that, since a scene can contain multiple objects, and these may be rotated or scaled, or the same object may be instanced multiple times. This I think is the main problem to solve, to find which object instances (potentially) overlap a ray segment from point A to B. For that, we can use a fairly simple BVH structure based on bounding boxes of each object, it doesn't need to be super optimized. And then gather that list of objects in an array in the kernel before volume shading. Then as a second step, that BVH could be made more fine grained. Instead of the full object bounding box, you could put inner or leaf node bounding boxes into the BVH, to avoid more false positives. Making the BVH work all the way down to the voxel level (with an algorithm like HDDA) would be a good optimization too, however that's not a requirement for an initial implementation. In some ways this is an orthogonal problem, and would require some deeper rethinking of how we do volume stepping in the `shade_volume` kernel.

Added subscriber: @Rin-San

Added subscriber: @Rin-San

Added subscriber: @kevindietrich

Added subscriber: @kevindietrich

I did not mention it during the last rendering meeting, but while working on Tangent's patch for volume motion blur, I also spent a bit of time updating their delta/residual tracking work to current master. I'll just put some notes from my observation of this work.

I managed to get some render out of it. Although it wasn't looking good: emission is not working, direct light is missing, and the volume mesh was visible. Then, even for Tangent, this was work in progress.

In there, they use an octree to encode the volumes topology as well as some extra data. The octree is supposed to replace both the volume meshes and the volume stack. I did not update the BVH traversal to also include the volume octree traversal; that could explain some of the volume mesh artifacts. To replace the volume stack, each leaf node in the octree has a list of active volumes. For now the list of volumes is fixed to 1024 volume objects, which is a bit much too much memory-wise to my liking, maybe it should be somehow more dynamic (e.g. the leaf nodes could store a pointer into some packed list).

The leaf nodes also store the min/max values for the volumes so null scattering probability is bounded by the actual volume density, however this is computed over the entire domain, so minimum is pretty much always 0. That should be more granular and done at the OpenVDB tile level, or maybe leaf level. The octree is built from the list of objects which have a volume geometry, so this could perhaps already handle instances. The octree is built from the volume bounding boxes though; it could be more fined grained.

I guess I could post a patch as some sort of proof of concept, or as a starting point or reference for me or someone else to continue this work. At least it is somewhat up to date with master.

I did not mention it during the last rendering meeting, but while working on Tangent's patch for volume motion blur, I also spent a bit of time updating their delta/residual tracking work to current master. I'll just put some notes from my observation of this work. I managed to get some render out of it. Although it wasn't looking good: emission is not working, direct light is missing, and the volume mesh was visible. Then, even for Tangent, this was work in progress. In there, they use an octree to encode the volumes topology as well as some extra data. The octree is supposed to replace both the volume meshes and the volume stack. I did not update the BVH traversal to also include the volume octree traversal; that could explain some of the volume mesh artifacts. To replace the volume stack, each leaf node in the octree has a list of active volumes. For now the list of volumes is fixed to 1024 volume objects, which is a bit much too much memory-wise to my liking, maybe it should be somehow more dynamic (e.g. the leaf nodes could store a pointer into some packed list). The leaf nodes also store the min/max values for the volumes so null scattering probability is bounded by the actual volume density, however this is computed over the entire domain, so minimum is pretty much always 0. That should be more granular and done at the OpenVDB tile level, or maybe leaf level. The octree is built from the list of objects which have a volume geometry, so this could perhaps already handle instances. The octree is built from the volume bounding boxes though; it could be more fined grained. I guess I could post a patch as some sort of proof of concept, or as a starting point or reference for me or someone else to continue this work. At least it is somewhat up to date with master.
Author
Owner

Thanks for the info, if you have a patch that applies to master that's always helpful, even if just as a reference.

I'm not exactly sure what you meant regarding including volume octree traversal in BVH traversal, but I think they should be separate. The way I would imagine it to work is that intersect_closest would check if there are any potential intersections after BVH traversal has determined the start/end, to see if there is a need to run the shade_volume kernel. And then in shade_volume we traverse the octree, updating the volume stack as it goes. Direct and indirect light sampling would then work on all volumes between the two surfaces at once.

With null scattering it's also possible to handle each volume separately, but still you'd want to do shading for potentially multiple ray segments of that volume between surfaces in one go.

Thanks for the info, if you have a patch that applies to master that's always helpful, even if just as a reference. I'm not exactly sure what you meant regarding including volume octree traversal in BVH traversal, but I think they should be separate. The way I would imagine it to work is that `intersect_closest` would check if there are any potential intersections after BVH traversal has determined the start/end, to see if there is a need to run the `shade_volume` kernel. And then in `shade_volume` we traverse the octree, updating the volume stack as it goes. Direct and indirect light sampling would then work on all volumes between the two surfaces at once. With null scattering it's also possible to handle each volume separately, but still you'd want to do shading for potentially multiple ray segments of that volume between surfaces in one go.

In #92570#1341274, @brecht wrote:
Thanks for the info, if you have a patch that applies to master that's always helpful, even if just as a reference.

I created a draft revision: D14656: Cycles: ratio tracking for volume rendering [WIP]

I'm not exactly sure what you meant regarding including volume octree traversal in BVH traversal, but I think they should be separate. The way I would imagine it to work is that intersect_closest would check if there are any potential intersections after BVH traversal has determined the start/end, to see if there is a need to run the shade_volume kernel.

Yes, sorry, I meant to say the overall scene traversal. As it stands, I added the octree traversal after scene_intersect in integrator_intersect_closest. Although it commented out.

And then in shade_volume we traverse the octree, updating the volume stack as it goes. Direct and indirect light sampling would then work on all volumes between the two surfaces at once.

With null scattering it's also possible to handle each volume separately, but still you'd want to do shading for potentially multiple ray segments of that volume between surfaces in one go.

Just to note, the patch does not bother with the stack. At each step, all of the volume shaders in the current leaf node are evaluated at once.

> In #92570#1341274, @brecht wrote: > Thanks for the info, if you have a patch that applies to master that's always helpful, even if just as a reference. I created a draft revision: [D14656: Cycles: ratio tracking for volume rendering [WIP]](https://archive.blender.org/developer/D14656) > I'm not exactly sure what you meant regarding including volume octree traversal in BVH traversal, but I think they should be separate. The way I would imagine it to work is that `intersect_closest` would check if there are any potential intersections after BVH traversal has determined the start/end, to see if there is a need to run the `shade_volume` kernel. Yes, sorry, I meant to say the overall scene traversal. As it stands, I added the octree traversal after `scene_intersect` in `integrator_intersect_closest`. Although it commented out. > And then in `shade_volume` we traverse the octree, updating the volume stack as it goes. Direct and indirect light sampling would then work on all volumes between the two surfaces at once. > > With null scattering it's also possible to handle each volume separately, but still you'd want to do shading for potentially multiple ray segments of that volume between surfaces in one go. Just to note, the patch does not bother with the stack. At each step, all of the volume shaders in the current leaf node are evaluated at once.

Added subscriber: @ParallelMayhem

Added subscriber: @ParallelMayhem

Added subscriber: @silex

Added subscriber: @silex

Added subscriber: @Dangry

Added subscriber: @Dangry
Brecht Van Lommel added this to the Render & Cycles project 2023-02-07 19:08:06 +01:00
Philipp Oeser removed the
Interest
Render & Cycles
label 2023-02-09 14:02:56 +01:00

Hi all,

Just wanted to chime in that I am attempting to graft this patch that @kevindietrich adapted from Tangent/Sergen as there is a situation where some production scenes that I'm working on are not rendering correctly (assuming it is a failure with the volume mesh+stack system, it is similar to these problems in #101484 but with mesh geometry inside of a volume at the intersection edges) and I'm trying to avoid the need to use another renderer.

I didn't read this before attempting and indeed I can see that the intersection/bvh is commented out. I can make an updated commit into Gitea so this isn't an entirely wasted endeavour. It is unfortunately against Cycles Standalone 3.6 though.

Hi all, Just wanted to chime in that I am attempting to graft this patch that @kevindietrich adapted from Tangent/Sergen as there is a situation where some production scenes that I'm working on are not rendering correctly (assuming it is a failure with the volume mesh+stack system, it is similar to these problems in https://projects.blender.org/blender/blender/issues/101484 but with mesh geometry inside of a volume at the intersection edges) and I'm trying to avoid the need to use another renderer. I didn't read this before attempting and indeed I can see that the intersection/bvh is commented out. I can make an updated commit into Gitea so this isn't an entirely wasted endeavour. It is unfortunately against Cycles Standalone 3.6 though.

I went on a refactor spree, and got things to compile at least (untested!):
https://projects.blender.org/boberfly/cycles/src/branch/feature/ratio-tracking

I'll be force-pushing to this here and there and see how far I get with it...

I went on a refactor spree, and got things to compile at least (untested!): https://projects.blender.org/boberfly/cycles/src/branch/feature/ratio-tracking I'll be force-pushing to this here and there and see how far I get with it...
Sign in to join this conversation.
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No Assignees
12 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender#92570
No description provided.