EEVEE-Next: Fix transparent shadows convergence #119526

Merged
Miguel Pozo merged 6 commits from pragma37/blender:pull-transparent-shadow-threshold into main 2024-03-20 16:05:16 +01:00
Member

Replace the hashed alpha function in shadows for a fully random one.
(Split from #119480)

hashed_alpha_threshold hash_vec3_to_float
imagen imagen
Replace the hashed alpha function in shadows for a fully random one. (Split from #119480) | hashed_alpha_threshold | hash_vec3_to_float | | --- | --- | | ![imagen](/attachments/fdd2374d-b5c2-4977-bac5-ab441b300a60) | ![imagen](/attachments/e9799889-cd4a-411b-b7d1-f3e4f2022e85) |
Miguel Pozo added the
Interest
EEVEE
Module
EEVEE & Viewport
labels 2024-03-15 16:47:58 +01:00
Miguel Pozo added 1 commit 2024-03-15 16:48:02 +01:00
Miguel Pozo added this to the EEVEE & Viewport project 2024-03-15 16:48:08 +01:00
Miguel Pozo requested review from Clément Foucault 2024-03-15 16:48:19 +01:00
Miguel Pozo added a new dependency 2024-03-15 16:49:23 +01:00

See reference to check why it is needed to have this stable noise function.
https://casual-effects.com/research/Wyman2017Hashed/index.html

Although we should use a better noise for final image convergence, I'm not sold that this complex hash is the best option we can use.

See reference to check why it is needed to have this stable noise function. https://casual-effects.com/research/Wyman2017Hashed/index.html Although we should use a better noise for final image convergence, I'm not sold that this complex hash is the best option we can use.
Author
Member

I get the point of the transparency_hashed_alpha_threshold function for the viewport, but it has issues when applied to our shadow maps:

  • It's computed based on pixel derivatives, but since shadows mix multiple resolutions, each LOD shows a different pattern.
  • We can't have a perfect 1:1 mapping between shadow and screen texels, so the temporal coherence doesn't work anyway. This also produces weird aliasing/correlation artifacts.
    I guess it could work if we use a very large hash_scale, but I'm not sure if that would look that good.

About the hash, I've used that one just because it was already there and looked fine, but we can use anything else as long as it converges well.
For reference: http://www.jcgt.org/published/0009/03/02/

I get the point of the `transparency_hashed_alpha_threshold` function for the viewport, but it has issues when applied to our shadow maps: * It's computed based on pixel derivatives, but since shadows mix multiple resolutions, each LOD shows a different pattern. * We can't have a perfect 1:1 mapping between shadow and screen texels, so the temporal coherence doesn't work anyway. This also produces weird aliasing/correlation artifacts. I guess it could work if we use a very large `hash_scale`, but I'm not sure if that would look that good. About the hash, I've used that one just because it was already there and looked fine, but we can use anything else as long as it converges well. For reference: http://www.jcgt.org/published/0009/03/02/

I like the paper you linked. Also I was under the impression this patch affected the prepass shader too (but it doesn't). So if you replace hash_vec3_to_float by iqint3 or pcg3d and measure cost and quality of each, I see no objection to this patch.

I like the paper you linked. Also I was under the impression this patch affected the prepass shader too (but it doesn't). So if you replace `hash_vec3_to_float` by `iqint3` or `pcg3d` and measure cost and quality of each, I see no objection to this patch.
Clément Foucault requested changes 2024-03-18 18:30:30 +01:00
Dismissed
Clément Foucault left a comment
Member

Be sure to put the noise functions in eevee_sampling_lib.glsl.

Be sure to put the noise functions in `eevee_sampling_lib.glsl`.
Miguel Pozo added 3 commits 2024-03-18 20:24:13 +01:00
Author
Member

I ended up using pcg4d since we have to take the sample offset into account and doing fract(hash + noise) was giving pretty bad results for some reason:
imagen

I discarded using iqint3 since, despite the name, it takes a 2d input and the overhead and uncertainty of using it for 3/4d isn't worth it, IMO.

I have not measured performance, the difference is certainly not enough to be measurable in FPS or render times.
But looking at both implementations, I would be very surprised if this is more expensive than hashed_alpha_threshold.

I ended up using `pcg4d` since we have to take the sample offset into account and doing `fract(hash + noise)` was giving pretty bad results for some reason: ![imagen](/attachments/14da9e5e-9fdb-4de2-acc8-f4ac25503673) I discarded using `iqint3` since, despite the name, it takes a 2d input and the overhead and uncertainty of using it for 3/4d isn't worth it, IMO. I have not measured performance, the difference is certainly not enough to be measurable in FPS or render times. But looking at both implementations, I would be very surprised if this is more expensive than `hashed_alpha_threshold`.
Miguel Pozo requested review from Clément Foucault 2024-03-18 20:37:37 +01:00
Clément Foucault requested changes 2024-03-19 10:53:34 +01:00
Dismissed
@ -17,6 +17,7 @@
#pragma BLENDER_REQUIRE(eevee_transparency_lib.glsl)

You can remove that include.

You can remove that include.
pragma37 marked this conversation as resolved
@ -32,3 +35,3 @@
float noise_offset = sampling_rng_1D_get(SAMPLING_TRANSPARENCY);
float random_threshold = transparency_hashed_alpha_threshold(1.0, noise_offset, g_data.P);
float random_threshold = pcg4d(vec4(g_data.P, noise_offset)).x;

Can you try moving the noise_offset scrambling on the CPU by passing another random number instead of SAMPLING_TRANSPARENCY?

If this fixes the convergence issue you experienced with fract(rand + offset), then it means it is just correlation artifacts from other random numbers, and they should be fixed all at once using better decorrelated sequences.

If it doesn't fix it, then it does mean there is an issue withfract(rand + offset).

Can you try moving the `noise_offset` scrambling on the CPU by passing another random number instead of `SAMPLING_TRANSPARENCY`? If this fixes the convergence issue you experienced with `fract(rand + offset)`, then it means it is just correlation artifacts from other random numbers, and they should be fixed all at once using better decorrelated sequences. If it doesn't fix it, then it does mean there is an issue with`fract(rand + offset)`.
Author
Member

I tried all your suggestions and it still shows the same issue.
I don't think it's an issue with fract(rand + offset), but simply that the correlation between front and back layers stays the same between samples.

I guess for screen transparency this might be less of an issue because of the camera jitter.

I tried all your suggestions and it still shows the same issue. I don't think it's an issue with `fract(rand + offset)`, but simply that the correlation between front and back layers stays the same between samples. I guess for screen transparency this might be less of an issue because of the camera jitter.

but simply that the correlation between front and back layers stays the same between samples.

I think you are on point there.

Can you try noise_function(g_data.P + noise_offset); then?

I am also wondering if we should use some low discrepancy noise (Blue noise, IGN) for screen 2D coord and then scramble it for the depth using pcg. Might have better value distribution in 2D and improve the shadow filtering.

> but simply that the correlation between front and back layers stays the same between samples. I think you are on point there. Can you try `noise_function(g_data.P + noise_offset);` then? I am also wondering if we should use some low discrepancy noise (Blue noise, IGN) for screen 2D coord and then scramble it for the depth using `pcg`. Might have better value distribution in 2D and improve the shadow filtering.
Author
Member

Can you try noise_function(g_data.P + noise_offset); then?

That can cause troubles on planes that are aligned "just in the right way", and probably in other cases.
Using the noise_offset as the fourth component for pcg4d is a much more robust option IMO, and super unlikely to cause any measurable performance difference.

I am also wondering if we should use some low discrepancy noise (Blue noise, IGN) for screen 2D coord and then scramble it for the depth using pcg. Might have better value distribution in 2D and improve the shadow filtering.

This is something I toyed with lately, it's trickier than it seems.
If you don't quantize the depth, you essentially get a lower-quality hash based on just the depth.
And if you do, you have to deal with correlation artifacts.

I think the perfect solution may be something like a 3d blue noise where the Z is the layer depth, but that would require some sort of OIT with rasterizer ordered view support and atomics.

> Can you try noise_function(g_data.P + noise_offset); then? That can cause troubles on planes that are aligned "just in the right way", and probably in other cases. Using the `noise_offset` as the fourth component for `pcg4d` is a much more robust option IMO, and super unlikely to cause any measurable performance difference. > I am also wondering if we should use some low discrepancy noise (Blue noise, IGN) for screen 2D coord and then scramble it for the depth using pcg. Might have better value distribution in 2D and improve the shadow filtering. This is something I toyed with lately, it's trickier than it seems. If you don't quantize the depth, you essentially get a lower-quality hash based on just the depth. And if you do, you have to deal with correlation artifacts. I think the perfect solution may be something like a 3d blue noise where the Z is the layer depth, but that would require some sort of OIT with rasterizer ordered view support and atomics.

There was some 3D blue noise research by nvidia but it's patented.

In all cases, thanks for doing all this testing. I'll accept the pcg4d version.

There was some 3D blue noise research by nvidia but it's patented. In all cases, thanks for doing all this testing. I'll accept the `pcg4d` version.
fclem marked this conversation as resolved
Clément Foucault approved these changes 2024-03-19 18:59:57 +01:00
Dismissed
Clément Foucault left a comment
Member

Accepting. But there is still eevee_transparency_lib.glsl that can be removed.

Accepting. But there is still `eevee_transparency_lib.glsl` that can be removed.
Miguel Pozo added 1 commit 2024-03-19 20:10:26 +01:00
Clément Foucault approved these changes 2024-03-19 21:27:46 +01:00
Miguel Pozo added 1 commit 2024-03-20 15:59:44 +01:00
Miguel Pozo merged commit 3888bdf8b2 into main 2024-03-20 16:05:16 +01:00
Miguel Pozo deleted branch pull-transparent-shadow-threshold 2024-03-20 16:05:18 +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 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.

Reference: blender/blender#119526
No description provided.