EEVEE-Next: Add horizon scan to raytracing module #114259

Merged
Clément Foucault merged 51 commits from fclem/blender:eevee-next-horizon-gi into main 2023-11-21 16:24:23 +01:00

Description

This uses the principles outlined in
Screen Space Indirect Lighting with Visibility Bitmask
to compute local and distant diffuse lighting.

This implements it inside the ray-tracing module as a fallback when the
surface is too rough. The threshold for blending between technique is
available to the user.

The implementation first setup a radiance buffer and a view normal
buffer. These buffer are tracing resolution as the lighting quality is
less important for rough surfaces. These buffers are necessary to avoid
re-projection on a per sample basis, and finding and rotating the
surface normal.

The processing phase scans the whole screen in 2 directions and outputs
local incomming lighting from neighbor pixels and the remaining
occlusion for everything that is outside the view.

The final steps filters the result of the previous phase while applying
the occlusion on the probe radiance to have an energy conserving mix.

Related #112979

Screen Trace Only Horizon Scan GI
Capture d’écran du 2023-11-02 20-15-01 Capture d’écran du 2023-11-02 20-15-26

TODOs

  • Tile base

    • Discard tiles with no influences
    • Do not load non traced tiles
  • Scalability

    • Fractional pixel rate
    • Upscaling / Filtering
  • Prepass:

    • Reproject / downsample radiance
    • Create normal buffer if needed
  • Ubiquitous

    • Diffuse
    • Reflection : 0 roughness NaN
  • Future development:

    • Performance : Group evaluation of different surface type.
    • Reflection : Fix energy preservation issue and have correct appearance.
    • Translucent : Not in raytracing pipeline yet.
    • Refraction : Not working, need to consider apparent roughness.
    • Temporal Stability: This is a bit more flickering than the ray-tracing implementation.
### Description This uses the principles outlined in [Screen Space Indirect Lighting with Visibility Bitmask](https://arxiv.org/pdf/2301.11376.pdf) to compute local and distant diffuse lighting. This implements it inside the ray-tracing module as a fallback when the surface is too rough. The threshold for blending between technique is available to the user. The implementation first setup a radiance buffer and a view normal buffer. These buffer are tracing resolution as the lighting quality is less important for rough surfaces. These buffers are necessary to avoid re-projection on a per sample basis, and finding and rotating the surface normal. The processing phase scans the whole screen in 2 directions and outputs local incomming lighting from neighbor pixels and the remaining occlusion for everything that is outside the view. The final steps filters the result of the previous phase while applying the occlusion on the probe radiance to have an energy conserving mix. Related #112979 | Screen Trace Only | Horizon Scan GI | | -------- | -------- | | ![Capture d’écran du 2023-11-02 20-15-01](/attachments/1a046ee0-e75d-43be-9c8f-e3e53f25c0ca)| ![Capture d’écran du 2023-11-02 20-15-26](/attachments/2f9eed38-f572-49e8-a0d1-420dfa7c81ad)| ### TODOs - Tile base - [x] Discard tiles with no influences - [x] Do not load non traced tiles - Scalability - [x] Fractional pixel rate - [x] Upscaling / Filtering - Prepass: - [x] Reproject / downsample radiance - [x] Create normal buffer if needed - Ubiquitous - [x] Diffuse - [x] Reflection : 0 roughness NaN - Future development: - Performance : Group evaluation of different surface type. - Reflection : Fix energy preservation issue and have correct appearance. - Translucent : Not in raytracing pipeline yet. - Refraction : Not working, need to consider apparent roughness. - Temporal Stability: This is a bit more flickering than the ray-tracing implementation.
Clément Foucault added this to the 4.1 milestone 2023-10-30 00:17:41 +01:00
Clément Foucault added the
Interest
EEVEE
Module
EEVEE & Viewport
labels 2023-10-30 00:17:41 +01:00
Clément Foucault added 24 commits 2023-10-30 00:17:53 +01:00
Clément Foucault added 3 commits 2023-11-01 15:25:33 +01:00
Clément Foucault force-pushed eevee-next-horizon-gi from 1fdf2fb546 to b5539e32ae 2023-11-02 19:03:24 +01:00 Compare
Clément Foucault added 2 commits 2023-11-02 20:22:21 +01:00
Author
Member

@blender-bot build

@blender-bot build
Clément Foucault added 2 commits 2023-11-02 20:27:01 +01:00
Author
Member

@blender-bot build

@blender-bot build
Clément Foucault requested review from Miguel Pozo 2023-11-02 20:28:07 +01:00
Clément Foucault added 1 commit 2023-11-02 23:47:51 +01:00
Miguel Pozo requested changes 2023-11-03 18:36:52 +01:00
Miguel Pozo left a comment
Member

The results for diffuse look really good.
And I'm happy to see the probes working again. :)

The only roadblock I see is that raytracing doesn't seem to be working at all for high roughness (>0.94).
The issue only seems to happen with the Principled BSDF (Diffuse and Glossy works fine).
I'm not sure about the reason.

The results for diffuse look really good. And I'm happy to see the probes working again. :) The only roadblock I see is that raytracing doesn't seem to be working at all for high roughness (>0.94). The issue only seems to happen with the Principled BSDF (Diffuse and Glossy works fine). I'm not sure about the reason.
@ -1844,0 +1848,4 @@
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
scene->eevee.reflection_options.screen_trace_max_roughness = 0.2f;
scene->eevee.refraction_options.screen_trace_max_roughness = 0.2f;
scene->eevee.diffuse_options.screen_trace_max_roughness = 0.2f;
Member

I think 0.2 is way too low for reflections.
And I guess refractions once it's in use.
Does the diffuse_options.screen_trace_max_roughness have any actual effect?

I think 0.2 is way too low for reflections. And I guess refractions once it's in use. Does the `diffuse_options.screen_trace_max_roughness` have any actual effect?
Author
Member

diffuse_options.screen_trace_max_roughness

It is used when you set it to 1. The diffuse is considered to have roughness 1.

> diffuse_options.screen_trace_max_roughness It is used when you set it to 1. The diffuse is considered to have roughness 1.
Author
Member

Since I couldn't make it work correctly with reflections, I increased this parameter to 0.5 which fades to 0.7 which I think is a pretty good compromise for now.

Since I couldn't make it work correctly with reflections, I increased this parameter to `0.5` which fades to `0.7` which I think is a pretty good compromise for now.
fclem marked this conversation as resolved
@ -60,7 +60,9 @@ void RayTraceModule::sync()
pass.shader_set(inst_.shaders.static_shader_get(RAY_TILE_CLASSIFY));
pass.bind_image("tile_mask_img", &tile_mask_tx_);
pass.bind_ssbo("ray_dispatch_buf", &ray_dispatch_buf_);
pass.bind_ssbo("denoise_dispatch_buf", &denoise_dispatch_buf_);
Member

Maybe not for this PR, but I think this function as a whole ( RayTraceModule::sync) could really benefit from comments explaining at a high level what each pass does and how they relate to each other.

Maybe not for this PR, but I think this function as a whole (` RayTraceModule::sync`) could really benefit from comments explaining at a high level what each pass does and how they relate to each other.
@ -19,3 +20,2 @@
{
/* TODO */
return 1.0;
return saturate(roughness * raytrace.roughness_mask_scale - raytrace.roughness_mask_bias);
Member

It took me some effort to realize this is just a map_range.
Wouldn't make more sense to just do:
saturate(mask_scale * (roughness - mask_start)) ?

Note that I was looking at this because raytracing is not working for materials with high roughness, but the issue must be elsewhere.

It took me some effort to realize this is just a map_range. Wouldn't make more sense to just do: `saturate(mask_scale * (roughness - mask_start))` ? Note that I was looking at this because raytracing is not working for materials with high roughness, but the issue must be elsewhere.
Author
Member

This is made so that it is optimized as single MADD instruction. But I agree should have a map range structure/type + function that improves the semantic.

This is made so that it is optimized as single MADD instruction. But I agree should have a map range structure/type + function that improves the semantic.
fclem marked this conversation as resolved
Clément Foucault added 2 commits 2023-11-20 20:50:13 +01:00
Author
Member

I tried to accommodate the AO + Visibility bitmask for global Illumination purpose of all BxDF.
However, this proved to not be as easy as it seemed. It works great for Lambertian diffuse BSDF but the sliced nature of the algorithm make it difficult to adjust to arbitrary shaped BxDF lobe. Here is some observations:

Slice sampling

Ideally, the slice directions should be chosen based on the BxDF and not a uniform direction around the view vector. This would avoid tracing in directions that have little or no influence. However this can result in non spatially uniform noise which can be harder to denoise.

Slice Weighting

The total weight of a slice depends on how much it crosses the BxDF lobe. Using the BxDF to weight individual samples works for contributing samples but we are missing what is the missing amount of energy in the cross section of the lobe. This missing contribution is what is called the far-field visibility. Each slice needs to be weighted accordingly to avoid low energy slices to dominate in the resulting mix (this is currently the major problem since each slice is only weighted by context.N_length which is correct for diffuse).

LTC integration

One solution would be to use LTC to modify the cosine lobe into the target BxDF. To do this, we should apply the LTC to the incoming light vectors (vL_front and vL_back). This would make use of all the visibility sectors efficiently as they should cover only the LTC representation of the BxDF.
The issue is, this changes the reference frame. The elevation angles need to be computed per BxDF (acos_fast * 2 * bsdf) after the light vectors LTC transform and many vectors need to be in local LTC space and duplicated (view vector, normal vector, light vector). The N_length weighting would no longer be the normal of the BxDF but the Z axis of the LTC projected to the slice plane in the LTC space.
However, this doesn't change the fact that each sector is weighted incorrectly (using uniform weights). Using horizon_scan_bitmask_to_visibility_cosine for each sample should fix this issue.

I tried to accommodate the AO + Visibility bitmask for global Illumination purpose of all BxDF. However, this proved to not be as easy as it seemed. It works great for Lambertian diffuse BSDF but the sliced nature of the algorithm make it difficult to adjust to arbitrary shaped BxDF lobe. Here is some observations: ### Slice sampling Ideally, the slice directions should be chosen based on the BxDF and not a uniform direction around the view vector. This would avoid tracing in directions that have little or no influence. However this can result in non spatially uniform noise which can be harder to denoise. ### Slice Weighting The total weight of a slice depends on how much it crosses the BxDF lobe. Using the BxDF to weight individual samples works for contributing samples but we are missing what is the missing amount of energy in the cross section of the lobe. This missing contribution is what is called the far-field visibility. Each slice needs to be weighted accordingly to avoid low energy slices to dominate in the resulting mix (this is currently the major problem since each slice is only weighted by context.N_length which is correct for diffuse). ### LTC integration One solution would be to use LTC to modify the cosine lobe into the target BxDF. To do this, we should apply the LTC to the incoming light vectors (vL_front and vL_back). This would make use of all the visibility sectors efficiently as they should cover only the LTC representation of the BxDF. The issue is, this changes the reference frame. The elevation angles need to be computed per BxDF (`acos_fast * 2 * bsdf`) after the light vectors LTC transform and many vectors need to be in local LTC space and duplicated (view vector, normal vector, light vector). The `N_length` weighting would no longer be the normal of the BxDF but the Z axis of the LTC projected to the slice plane **in the LTC space**. However, this doesn't change the fact that each sector is weighted incorrectly (using uniform weights). Using `horizon_scan_bitmask_to_visibility_cosine` for each sample should fix this issue.
Author
Member

The only roadblock I see is that raytracing doesn't seem to be working at all for high roughness (>0.94).
The issue only seems to happen with the Principled BSDF (Diffuse and Glossy works fine).

I can't reproduce this. Can you repro with the latest version?

> The only roadblock I see is that raytracing doesn't seem to be working at all for high roughness (>0.94). The issue only seems to happen with the Principled BSDF (Diffuse and Glossy works fine). I can't reproduce this. Can you repro with the latest version?
Clément Foucault added 2 commits 2023-11-20 21:03:35 +01:00
buildbot/vexp-code-patch-coordinator Build done. Details
5863d8a085
Merge branch 'main' into eevee-next-horizon-gi
# Conflicts:
#	source/blender/blenloader/intern/versioning_400.cc
#	source/blender/draw/engines/eevee_next/shaders/eevee_horizon_scan_eval_lib.glsl
Author
Member

@blender-bot build

@blender-bot build
Author
Member

Given how R&D the LTC solution is (there is no paper or known implementation), I will delay this to 4.1 or later.

I made sure that the current implementation passes the furnace test. So this patch is good to go for me.

Given how R&D the LTC solution is (there is no paper or known implementation), I will delay this to 4.1 or later. I made sure that the current implementation passes the furnace test. So this patch is good to go for me.
Clément Foucault added 1 commit 2023-11-20 21:12:04 +01:00
Member

I can't reproduce this. Can you repro with the latest version?

Nope, not anymore. 👍

> I can't reproduce this. Can you repro with the latest version? Nope, not anymore. 👍
Miguel Pozo approved these changes 2023-11-21 16:22:09 +01:00
Clément Foucault merged commit 3097d5d821 into main 2023-11-21 16:24:23 +01:00
Clément Foucault deleted branch eevee-next-horizon-gi 2023-11-21 16:24:25 +01: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#114259
No description provided.