EEVEE-Next: Add mesh volume bounds estimation #113731

Merged
Clément Foucault merged 27 commits from fclem/blender:eevee-next-volume-object-bounds into main 2023-10-19 19:22:22 +02:00

This adds correct object bounds estimation.

This works by creating an occupancy texture where one
bit represents one froxel. A geometry pre-pass fill this
occupancy texture and doesn't do any shading. Each bit
set to 0 will not be considered occupied by the object
volume and will discard the material compute shader for
this froxel.

There is 2 method of computing the occupancy map:

  • Atomic XOR: For each fragment we compute the amount of
    froxels center in-front of it. We then convert that
    into occupancy bitmask that we apply to the occupancy
    texture using imageAtomicXor. This is straight forward
    and works well for any manifold geometry.
  • Hit List: For each fragment we write the fragment depth
    in a list (contained in one array texture). This list
    is then processed by a fullscreen pass (see
    eevee_occupancy_convert_frag.glsl) that sorts and
    converts all the hits to the occupancy bits. This
    emulate Cycles behavior by considering only back-face
    hits as exit events and front-face hits as entry events.
    The result stores it to the occupancy texture using
    bit-wise OR operation to compose it with other non-hit
    list objects. This also decouple the hit-list evaluation
    complexity from the material evaluation shader.

Limitations

Fast

  • Non-manifolds geometry objects are rendered incorrectly.
  • Non-manifolds geometry objects will affect other objects
    in front of them.

Accurate

  • Limited to 16 hits per layer for now.
  • Non-manifolds geometry objects will affect other objects
    in front of them.

Issues to fix

  • Crossing the surface with the camera near plane
    make the mesh non-manifold and exhibit the
    same issue.
    Fixed by simply reversing the XOR input.
    This way missing front geometry fill the space between
    the camera and the first surface depth.
  • Surface crossing camera far plane exhibit issues
    (Caused by above fix).
    Fix is to use infinite projection
    matrix to never clip.
  • Non-Manifold object affect other objects. Clip
    occupancy bits to the bbox.
    This is a bit involved and
    might disable some optimization. Consider a limitation
    for now.
  • Object intersections are effectively removed
    instead of overlapping.
    Use layered approach.
  • Volumes objects do not use this prepass making
    them not working at all.
    Use selection surface mesh.
  • Volume object have multiple boxes in their coarse
    geometry. This causes overlapping issues.
    Might be fixed
    by drawing with front-face culling, limiting occupancy
    to the cubes volumes and using atomicOr instead of
    atomicXor. This would work because cubes are not
    arbitrary geometry. We might want to do this for
    point clouds too. NOTE: This was delayed and for now,
    volumes still use their bounding boxes.
  • Make sure hit lists are allocated only when needed.

Follow ups

  • Object raster does not follow the froxels jitter
    in XY dimensions (it does in Z). Needs to be fixed as
    part of changing the sampling scheme.
  • Make it possible to have more than 16 hits.

Examples

Fast

Complex Mesh Manifold Geometry Overlapping volumes
Capture d’écran du 2023-10-14 23-12-04 Capture d’écran du 2023-10-14 22-56-08 image
Note: The suzanne being non-manifold by default, this one was edited to make it watertight. Note: Here suzanne is non-manifold. Note correct intersection.

Accurate

Cycles EEVEE
Capture d’écran du 2023-10-17 21-30-37 Capture d’écran du 2023-10-17 21-30-43
This adds correct object bounds estimation. This works by creating an occupancy texture where one bit represents one froxel. A geometry pre-pass fill this occupancy texture and doesn't do any shading. Each bit set to 0 will not be considered occupied by the object volume and will discard the material compute shader for this froxel. There is 2 method of computing the occupancy map: - Atomic XOR: For each fragment we compute the amount of froxels **center** in-front of it. We then convert that into occupancy bitmask that we apply to the occupancy texture using `imageAtomicXor`. This is straight forward and works well for any manifold geometry. - Hit List: For each fragment we write the fragment depth in a list (contained in one array texture). This list is then processed by a fullscreen pass (see `eevee_occupancy_convert_frag.glsl`) that sorts and converts all the hits to the occupancy bits. This emulate Cycles behavior by considering only back-face hits as exit events and front-face hits as entry events. The result stores it to the occupancy texture using bit-wise `OR` operation to compose it with other non-hit list objects. This also decouple the hit-list evaluation complexity from the material evaluation shader. ## Limitations ### Fast - Non-manifolds geometry objects are rendered incorrectly. - Non-manifolds geometry objects will affect other objects in front of them. ### Accurate - Limited to 16 hits per layer for now. - Non-manifolds geometry objects will affect other objects in front of them. ## Issues to fix - [x] ~~Crossing the surface with the camera near plane make the mesh non-manifold and exhibit the same issue.~~ Fixed by simply reversing the XOR input. This way missing front geometry fill the space between the camera and the first surface depth. - [x] ~~Surface crossing camera far plane exhibit issues (Caused by above fix).~~ Fix is to use infinite projection matrix to never clip. - [x] ~~Non-Manifold object affect other objects. Clip occupancy bits to the bbox.~~ This is a bit involved and might disable some optimization. Consider a limitation for now. - [x] ~~Object intersections are effectively removed instead of overlapping.~~ Use layered approach. - [x] ~~Volumes objects do not use this prepass making them not working at all.~~ Use selection surface mesh. - [x] ~~Volume object have multiple boxes in their coarse geometry. This causes overlapping issues.~~ Might be fixed by drawing with front-face culling, limiting occupancy to the cubes volumes and using `atomicOr` instead of `atomicXor`. This would work because cubes are not arbitrary geometry. We might want to do this for point clouds too. NOTE: This was delayed and for now, volumes still use their bounding boxes. - [x] Make sure hit lists are allocated only when needed. ### Follow ups - Object raster does not follow the froxels jitter in XY dimensions (it does in Z). Needs to be fixed as part of changing the sampling scheme. - Make it possible to have more than 16 hits. ## Examples ### Fast | Complex Mesh | Manifold Geometry | Overlapping volumes | | -------- | -------- | -------- | | ![Capture d’écran du 2023-10-14 23-12-04](/attachments/b4f3011b-511e-4b25-894a-24373234aed3) | ![Capture d’écran du 2023-10-14 22-56-08](/attachments/0174b930-3ff2-4c09-98a0-59e7dd09f010) | ![image](/attachments/b22efd34-1964-4406-9dbf-d34f0c3bdf02) | | | Note: The suzanne being non-manifold by default, this one was edited to make it watertight. | Note: Here suzanne is non-manifold. Note correct intersection. | ### Accurate | Cycles | EEVEE | | -------- | -------- | |![Capture d’écran du 2023-10-17 21-30-37](/attachments/6b86af6f-f72c-4537-9535-44281c6da228)|![Capture d’écran du 2023-10-17 21-30-43](/attachments/2f8256fc-a7fc-415e-968d-9ef76f0c32b5)|
Clément Foucault added this to the 4.1 milestone 2023-10-14 23:24:22 +02:00
Clément Foucault added the
Interest
EEVEE
Module
EEVEE & Viewport
labels 2023-10-14 23:24:22 +02:00
Clément Foucault added 4 commits 2023-10-14 23:24:35 +02:00
Clément Foucault changed title from EEVEE-Next: Add object bounds estimation to EEVEE-Next: Add mesh volume bounds estimation 2023-10-14 23:44:36 +02:00
Clément Foucault added 1 commit 2023-10-15 01:28:43 +02:00
Clément Foucault added 1 commit 2023-10-15 15:16:07 +02:00
Clément Foucault added 1 commit 2023-10-15 17:15:19 +02:00
Clément Foucault added 1 commit 2023-10-15 21:44:59 +02:00
Clément Foucault changed title from EEVEE-Next: Add mesh volume bounds estimation to WIP: EEVEE-Next: Add mesh volume bounds estimation 2023-10-15 23:48:54 +02:00
Clément Foucault added 1 commit 2023-10-16 00:03:26 +02:00
Clément Foucault added 1 commit 2023-10-16 00:33:23 +02:00
Clément Foucault added 1 commit 2023-10-17 13:14:26 +02:00
Clément Foucault added 1 commit 2023-10-17 21:32:21 +02:00
Clément Foucault added 3 commits 2023-10-18 11:07:33 +02:00
Clément Foucault added 1 commit 2023-10-18 15:17:33 +02:00
158e711474 Add new geometry type for volume object bounds
This allow proper tagging of the bounding box froxels
Clément Foucault requested review from Miguel Pozo 2023-10-18 15:18:02 +02:00
Clément Foucault changed title from WIP: EEVEE-Next: Add mesh volume bounds estimation to EEVEE-Next: Add mesh volume bounds estimation 2023-10-18 15:18:12 +02:00
Clément Foucault added 1 commit 2023-10-18 15:26:13 +02:00
Author
Member

@blender-bot build

@blender-bot build
Miguel Pozo requested changes 2023-10-18 18:41:43 +02:00
Miguel Pozo left a comment
Member

I have not checked the occupancy shaders yet, but I miss some kind of overview of how they work.
(Edit: Just saw the PR explanation. I would add that to a comment)
Unless you think they could be useful for something else I would rename the files prefix to 'volume_occupancy`.

Note that with this patch applied Volume lighting is broken. And volumes don't seem to render at all in main. 😢
It's seemingly a recent regression.
Build from October 12 vs this PR:

October 12 build This PR
imagen imagen
I have not checked the occupancy shaders yet, but I miss some kind of overview of how they work. (Edit: Just saw the PR explanation. I would add that to a comment) Unless you think they could be useful for something else I would rename the files prefix to 'volume_occupancy`. Note that with this patch applied Volume lighting is broken. And volumes don't seem to render at all in main. 😢 It's seemingly a recent regression. Build from October 12 vs this PR: | October 12 build | This PR | | --- | --- | |![imagen](/attachments/e0a7b238-16c2-430c-9181-37b501ef9ff4)|![imagen](/attachments/b363515b-bb10-4a0d-b6a0-9988df3546e5)|
@ -295,13 +313,18 @@ Material &MaterialModule::material_sync(Object *ob,
mat.planar_probe_shading = material_pass_get(
ob, blender_mat, MAT_PIPE_DEFERRED, geometry_type, MAT_PROBE_PLANAR);
}
}
Member

This enables volumes for baking instances. Is that intended?
It makes sense for sphere and planar probes, which didn't exist when this code was written, but I think it still makes sense to disable them for volume probes.

This enables volumes for baking instances. Is that intended? It makes sense for sphere and planar probes, which didn't exist when this code was written, but I think it still makes sense to disable them for volume probes.
Author
Member

That wasn't intended, but that's on the roadmap :D. I'll revert for now.

That wasn't intended, but that's on the roadmap :D. I'll revert for now.
fclem marked this conversation as resolved
@ -45,1 +47,4 @@
MAT_GEOM_GPENCIL,
MAT_GEOM_VOLUME,
/* These maps to special vertex shader. */
Member

MAT_GEOM_VOLUME_WORLD is a compute shader.

`MAT_GEOM_VOLUME_WORLD` is a compute shader.
Author
Member

The goal would be to port them as vertex shader so that we could shift some computation of the material towards the vertex shader. But that's something still in design so I'll just replace it with "special shader".

The goal would be to port them as vertex shader so that we could shift some computation of the material towards the vertex shader. But that's something still in design so I'll just replace it with "special shader".
fclem marked this conversation as resolved
@ -768,1 +831,3 @@
inst_.sampling.bind_resources(volume_ps_);
enabled_ = false;
for (auto &layer : layers_) {
(*layer).sync();
Member

Why do this instead of layer->sync()?

Why do this instead of `layer->sync()`?
fclem marked this conversation as resolved
@ -769,0 +841,4 @@
for (auto &layer : layers_) {
/* TODO(fclem): We might want to skip empty layers as the clear overhead is be significant. */
/* TODO(fclem): Move this clear inside the render pass. */
occupancy_tx.clear(uint4(0u));
Member

Remainder that we saw that this kind of texture clears without a framebuffer was quite slower. Probably not something we should address in this PR, though.

Remainder that we saw that this kind of texture clears without a framebuffer was quite slower. Probably not something we should address in this PR, though.
Author
Member

Yes, but that's quite an ambiguous position. This texture is not part of any framebuffer. So we need to manually clear it.

Yes, but that's quite an ambiguous position. This texture is not part of any framebuffer. So we need to manually clear it.
pragma37 marked this conversation as resolved
@ -542,33 +644,29 @@ class PipelineModule {
case MAT_PIPE_DEFERRED_PREPASS:
return deferred.prepass_add(blender_mat, gpumat, false);
case MAT_PIPE_FORWARD_PREPASS:
if (GPU_material_flag_get(gpumat, GPU_MATFLAG_TRANSPARENT)) {
Member

I don't get the removals from this file. Do they belong to this PR?

I don't get the removals from this file. Do they belong to this PR?
Author
Member

Kind of. They are related to the way the transparent material gets added to the pipeline which is similar to the volume one. This function shouldn't add any transparent object.

Kind of. They are related to the way the transparent material gets added to the pipeline which is similar to the volume one. This function shouldn't add any transparent object.
pragma37 marked this conversation as resolved
@ -278,0 +280,4 @@
GridAABB(int3 min_, int3 max_) : min(min_), max(max_){};
/** Returns the intersection between this AABB and the \a other AABB. */
GridAABB intersect(const GridAABB &other) const
Member

I think intersection would make more sense.

I think `intersection` would make more sense.
fclem marked this conversation as resolved
@ -441,0 +444,4 @@
MAT_GEOM_VOLUME_WORLD,
MAT_GEOM_VOLUME_OBJECT,
MAT_GEOM_VOLUME,
MAT_GEOM_VOLUME);
Member

Repeated.

Repeated.
fclem marked this conversation as resolved
@ -154,3 +156,3 @@
GPUMaterial *gpu_material = material_array.gpu_materials[i];
if (material.volume.gpumat && i == 0) {
geometry_call(material.volume_occupancy.sub_pass, geom, res_handle);
Member

Shouldn't this be done only if the material has a volume output?

Shouldn't this be done only if the material has a volume output?
Author
Member

If the material has no volume, the shading group will be nullptr and this call will be a noop.

If the material has no volume, the shading group will be `nullptr` and this call will be a noop.
fclem marked this conversation as resolved
@ -315,0 +333,4 @@
/* Use bounding box tag empty spaces. */
GPUBatch *geom = DRW_cache_cube_get();
geometry_call(material.volume_occupancy.sub_pass, geom, res_handle);
Member

Why do regular Volume objects need an occupancy pass?

Why do regular Volume objects need an occupancy pass?
Author
Member

Because the material compute shader is dispatched on the BBox converted to the froxel grid AABB. This inflates the bounds quite a bit in any case. So using the occupancy map this makes sure to trim the excess. Also this will help further optimization.

Because the material compute shader is dispatched on the BBox converted to the froxel grid AABB. This inflates the bounds quite a bit in any case. So using the occupancy map this makes sure to trim the excess. Also this will help further optimization.
Clément Foucault added 3 commits 2023-10-18 21:33:35 +02:00
Author
Member

Unless you think they could be useful for something else I would rename the files prefix to 'volume_occupancy`.

I think we could reuse them for object thickness. Nothing makes them specific to volume except their current usage.

> Unless you think they could be useful for something else I would rename the files prefix to 'volume_occupancy`. I think we could reuse them for object thickness. Nothing makes them specific to volume except their current usage.
Clément Foucault added 2 commits 2023-10-18 22:10:34 +02:00
Author
Member

If that doesn't break main more than it currently is, I would propose to commit this as it is to unlock the other material pipeline refactors that needs to come after it. We can then fix the remaining issues with volumes in main.

If that doesn't break `main` more than it currently is, I would propose to commit this as it is to unlock the other material pipeline refactors that needs to come after it. We can then fix the remaining issues with volumes in `main`.
Clément Foucault added 3 commits 2023-10-19 17:00:00 +02:00
Clément Foucault requested review from Miguel Pozo 2023-10-19 17:01:04 +02:00
Clément Foucault added 1 commit 2023-10-19 17:51:00 +02:00
Miguel Pozo approved these changes 2023-10-19 18:44:29 +02:00
Clément Foucault added 1 commit 2023-10-19 18:46:07 +02:00
buildbot/vexp-code-patch-coordinator Build done. Details
9396a5a49f
Move occupancy geometry call to avoid confusion
Author
Member

@blender-bot build

@blender-bot build
Clément Foucault merged commit f79b86553a into main 2023-10-19 19:22:22 +02:00
Clément Foucault deleted branch eevee-next-volume-object-bounds 2023-10-19 19:22:23 +02:00
Sign in to join this conversation.
No reviewers
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 project
No Assignees
2 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#113731
No description provided.