godot
godot copied to clipboard
Upgrade SDFGI to HDDAGI
Supersedes #86007
This is a new global illumination system that is a full upgrade to SDFGI Key advantages are:
- Significantly faster base frame time.
- An order of magnitude faster updates (SDFGI drops frames very significantly when moving, as a consequence of having to redo its entire SDF even for a small motion).
- Higher quality (less light leaks, properly energy conservation, much better reflections, others)
- Occlusion remains the same as in SDFGI. I experimented with other systems (the one in DDGI) but everything has worse tradeoffs.
It is meant as a drop-in replacement, so games using SDFGI should get HDDAGI transparently.
TODO:
- [x] For some reason gets DEVICE LOST on Intel GPUs. Can´t figure out why.
- [x] Waiting for a PR fixing the normal buffer precision in order to fix some issues. https://github.com/godotengine/godot/pull/86316
- [x] Volumetric fog GI injection appears broken.
TODO AFTER MERGING:
- [ ] High density probes support.
- [ ] Dynamic objects support.
Improvement Screenshots
Motion performance:
By far the biggest improvement is the performance when moving the camera. This is what makes SDFGI unusable on lower end hardware and can even push down the FPS very strongly on higher end hardware. This is because SDFGI needs to regenerate the entire SDF cascade using a jump flood even if it moved just a bit. HDDAGI uses HDDA so it only does local updates to the cascade and no scrolling.
Here is what happens in SDFGI when the camera moves fast:
https://github.com/godotengine/godot/assets/6265307/2c43db90-f519-4ca2-b23c-bec9897ac722
As you can see FPS take a large dip. This really sucks for any kind of games where the camera moves fast, like a racing game, a fast shooter, etc.
In comparison, HDDAGI is unaffected by camera motion:
https://github.com/godotengine/godot/assets/6265307/7d21c3f4-80f3-431a-99d4-b055d6bb99ac
Static performance:
When rendering static (camera not moving) HDDAGI is also considerably faster than SDFGI:
This is SDFGI, the first set of dispatches is the light update, the second is the probe raytracing. On a Geforce 1650 it takes 2.43ms:
In HDDAGI, the same task takes 0.93ms. While not a great difference on a 1650, this makes a much larger difference on IGP:
Quality of Indirect Light
SDFGI does not properly do light conservation, while HDDAGI does. Here is comparison screens by @Jamsers:
SDFGI: Notice light is more uneven in general, and there are some color issues due to the use of spherical harmonics.
HDDAGI: Notice light is better, more evenly distributed:
Quality of reflections
SDFGI uses a very hacky way to obtain light from the SDF that result in very strange lighting from the reflections, plus the SDF gives it a very weird look (this is what you see in the reflections):
In contrast, HDDAGI filters voxels properly, so what is seen in reflections is more faithful to the actual geometry:
What is being reflected:
Here you can see in a more realistic scenario how close the reflections are to the actual geometry (note tonemapping is different in the reflection as this is a debug mode):
In motion
SDFGI suffers from jumping dark spots when lights or camera move. HDDAGI has a special probe filtering option (enabled by default) that gets rid of them.
SDFGI (notice the jumping dark spots):
https://github.com/godotengine/godot/assets/6265307/400cae65-fc42-46ed-a237-23a85bd18f17
HDDAGI (notice the general smoothness):
https://github.com/godotengine/godot/assets/6265307/9dfc879e-429f-41c3-b7d0-bcc4b5d75797
SDFGI (with a proper scene, note jumping dark spots on the tunnel
https://github.com/godotengine/godot/assets/6265307/47265f4c-a4dd-4ee7-a1cf-7c08fe5a4f44
HDDAGI with filter probes:
https://github.com/godotengine/godot/assets/6265307/a66ef802-7b9d-451c-ba0c-d54888ea6cfd
Production edit: closes godotengine/godot-roadmap#32, closes https://github.com/godotengine/godot/issues/41154, closes https://github.com/godotengine/godot-proposals/issues/3024
Pretty good job, performance increased when moving , and this time decided to use the default cell size , because as you said i exaggerated with that 1cm. It seem´s pretty good though the problem is still gi colliding with the geometry for me, in comparison this is with an empty scene.
Vídeo sin título - Screen Recording - 17_12_2023, 22_17_50.webm Vídeo sin título - Screen Recording - 17_12_2023, 22_20_37.webm
Vídeo sin título - Screen Recording - 17_12_2023, 22_24_17.webm Vídeo sin título - Screen Recording - 17_12_2023, 22_28_04.webm
Streaks aligned with the X axis are visible when volumetric fog is enabled and GI Inject is greater than 0.0
, even if no lights are visible in the scene:
https://github.com/godotengine/godot/assets/180032/954d339a-df2b-4191-8645-02bcd31774ba
Minimal reproduction project: test_hddagi_volumetric_fog.zip
The new Occlusion Bias setting helps solve some of the dark artifacting mentioned in the previous thread. I feel that the splotchiness of SDFGI is almost completely reduced and not an issue anymore as well. Here are the existing problems in my tests:
- Cascade shifting is far too noticeable. Default cascade 0 distance needs to be pushed back 3-4x more to prevent sudden shifts in GI as players move through the world, without reducing probe density so accuracy is not sacrificed (which causes a range of other issues).
- Reflection jitter issue mentioned in the last thread.
- Overdarkening is still a problem. Some areas go completely black when they should be receiving at least a little light. Normal maps on terrain and organic objects (rocks etc.) suffer especially badly, with extremely dark patches making some materials feel semi-metallic.
- Spherical or curved forms (especially when overlapping with other geo) are still full of artifacts. The situation is improved, but sometimes it is impossible to find a sweet spot between bias settings that doesn't screw up other areas of the environment.
- SSIL can help resolve artifacts but is far too smeary and noisy to be reliable at this point.
As mentioned in the previous thread, the ability for users to author probe positions manually in a domain (similar to Unity's Adaptive Probe Volumes or its aging Light Probes system) would allow artists to resolve most of these issues manually, and most users probably aren't making environments large enough or procedural enough to warrant a cascading solution (nor can Godot handle large streaming worlds). The option for both would be welcome.
I'm aware there are solutions in the works for these issues, just putting them here to keep record.
Cascade shifting is far too noticeable. Default cascade 0 distance needs to be pushed back 3-4x more to prevent sudden shifts in GI as players move through the world, without reducing probe density so accuracy is not sacrificed (which causes a range of other issues).
An even better solution is allowing users to set Cell Size and Cascade Distance independently, for each cascade - performance be damned. Hide it behind an advanced toggle or something if you must, but it always irked me that we never had full control over SDFGI cascades. The default, unchangeable ratios are horrendously crawly, no stability whatsoever, and make cascade 0 so close on smaller cell sizes that it becomes irrelevant for the majority of the scene.
But I suppose this merits a separate proposal.
@WickedInsignia
Cascade shifting is far too noticeable. Default cascade 0 distance needs to be pushed back 3-4x more to prevent sudden shifts in GI as players move through the world, without reducing probe density so accuracy is not sacrificed (which causes a range of other issues).
This is mostly why I want to implement the high density probes option. The main problem right now is that, on small indoors, the GI runs out of probes at a certain distance and hence it stops receiving lighting. Or, sometimes, all 4 probes are occluded at that position. With high density that problem should mostly resolve, but it is independent to this PR, which aims to replace SDFGI first.
Reflection jitter issue mentioned in the last thread.
This is dependent on work Clay is doing to fix the normal buffer resolution. I can't merge this PR until that one is done.
Overdarkening is still a problem. Some areas go completely black when they should be receiving at least a little light. Normal maps on terrain and organic objects (rocks etc.) suffer especially badly, with extremely dark patches making some materials feel semi-metallic. Spherical or curved forms (especially when overlapping with other geo) are still full of artifacts. The situation is improved, but sometimes it is impossible to find a sweet spot between bias settings that doesn't screw up other areas of the environment.
Thats kind of the same and this is the main problem with DDGI and these types of probe based GI. I am hoping the situation improves with the high density probes option.
SSIL can help resolve artifacts but is far too smeary and noisy to be reliable at this point.
My plan is to have both high density probes and also a screen space part . SSIL is not designed for this kind of GI, so I need to write a proper screen space tracing that traces the distances smaller than a single probe. With that all pixels should get proper lighting.
But then again, the plan with this PR is to supersede SDFGI, since It's pretty large and difficult to keep up to date as-is. Take it as foundation work, then I will work on the other stuff I mentioned.
@Jamsers
An even better solution is allowing users to set Cell Size and Cascade Distance independently, for each cascade - performance be damned. Hide it behind an advanced toggle or something if you must, but it always irked me that we never had full control over SDFGI cascades.
The problem is the density, not the distance. Cascades are always 16x16 regions, so customizing different cell size or cascade distance will always bite you one way or the other. This is why my plan to work on the high density probes.
The problem is the density, not the distance. Cascades are always 16x16 regions
Yes, and my idea was being able to set arbitrary probe densities by changing Cell Size and Cascade Distance independently - i.e. if you want more probe density in cascade 0, you keep Cascade Distance at the default 12.8, but set Cell Size smaller. Is the 16x16 region limitation something that can't be changed/solved?
@Jamsers that is unfortunately not possible because cascades use a ton of memory and more density scales them exponentially and make them unusable pretty quick. This is why I need a special, separate, technique to increase the density without affecting memory so much.
Vídeo sin título - Screen Recording - 17_12_2023, 22_17_50.webm Vídeo sin título - Screen Recording - 17_12_2023, 22_20_37.webm
Vídeo sin título - Screen Recording - 17_12_2023, 22_24_17.webm Vídeo sin título - Screen Recording - 17_12_2023, 22_28_04.webm
After trying I would say it in a pretty good state( literally it has more or less fps than volumetric fog in a empty scene. Also,if i decrease cascades to 1 and put the light update to 16 it might be at the same vfog level of fps in a small scene with cubes). All pretty good, now the issue is with scenes like sponza where even if geometry is simple i still find that huge fps drops( motion is not the one having the fault here as it happens statically too) when using the meshes, like the bigger, the more hddagi consumes from it. look the difference with my above videos and the images below.
Can this be sorted out ,or the only way would be with the cascade sething, because if simple scenes is like this, not sure of big ones. although maybe the issue is just my igpu(radeon vega 3), as it not as good.
@Saul2022 just so you understand better the dependency on geometry. HDDAGI performance does of course depend on the amount of geometry in the level, what it does not depend is on the geometry complexity. This means if a scene with 1 million polygons occupies the same physical space as a scene with 1500 polygons, it is pretty much the same for HDDAGI.
This means if a scene with 1 million polygons occupies the same physical space as a scene with 1500 polygons, it is pretty much the same for HDDAGI.
Alright, thank you for clearing it out.
Distant light leaking seems to have regressed compared to 4.2 SDFGI
4.2 SDFGI:
https://github.com/godotengine/godot/assets/39361911/9633af19-6913-4f79-ab44-7fe26ee2756c
gi-hdda:
https://github.com/godotengine/godot/assets/39361911/d08b69a2-c761-4749-aaef-af4e3831498b
SDFGI's "scaly" occlusion artifacts on angled/curved surfaces has been replaced with "blocky" artifacts
4.2 SDFGI:
https://github.com/godotengine/godot/assets/39361911/d94ea2b8-cda8-4e9b-b332-1051398ff9bd
gi-hdda:
https://github.com/godotengine/godot/assets/39361911/8c4886bb-7433-477f-947f-e8a34b23460c
@Jamsers Can you test the older PR to make sure this isn't a regression? I can reproduce this on https://github.com/Calinou/godot-reflection, but I don't recall seeing this with the earlier revision of this PR.
Tested the same project on a sdfgi-2.0 build and can confirm the leaking and artifacts are exactly the same as the gi-hdda build.
@Jamsers Looks like I may have broken something in the recent commits.
Perhaps, but I tested it on the older sdfgi-2.0 branch and it had the same issues, so maybe the regression's always been there but we just didn't test long range/angled geometry scenarios till now
@Jamsers May it be related to the YScale setting? maybe because its not present in HDDAGI you are seeing this.
You're right, I tested it just now. Y Scale and Cascade Format were both left on default in my initial testing.
In 4.2
, Y Scale 50% and 75% don't show the leaking, but it shows up in Y Scale 100%.
In gi-hhda
, the leaking shows up in both Cascade Format 16x8x16 and 16x16x16.
I've uploaded the level I'm using for testing here: Crater-Province-Level
Hopefully it'll be useful for testing Godot features in big levels/open worlds
I guess I will have to add the Y-Scale option again, though it may not be super useful when I implement high density probes.
I wonder why it leaks when we can see that in the voxel representation there are no leaks?
https://github.com/godotengine/godot/assets/39361911/cb02287e-be0e-45ef-9848-a7152d5d1eb0
Might be better to tackle the root cause of the leaks rather than just hoping increased probe density makes it less noticeable
HDDAGI seems to have fixed #74899 😅
4.3.dev:
https://github.com/godotengine/godot/assets/39361911/5c2c5432-67c8-4400-879a-59e8a6bb0a6d
gi-hdda:
https://github.com/godotengine/godot/assets/39361911/01a8cd4e-f684-4452-a5c7-b36ecc048c5c
I wonder why it leaks when we can see that in the voxel representation there are no leaks?
Maybe some probe bugs, you tried with the sdfgi to see if it happens the same?
Light popping has regressed in HDDAGI:
4.2:
https://github.com/godotengine/godot/assets/39361911/281768ee-1aa0-47be-935a-813b9e3410fd
https://github.com/godotengine/godot/assets/39361911/c68f159f-a2c2-4c90-86c6-4e8baccc1be4
gi-hdda:
https://github.com/godotengine/godot/assets/39361911/d263cab3-9e04-47ba-b295-a144191cf731
https://github.com/godotengine/godot/assets/39361911/3d5ac8e2-5bf6-44d1-a2cb-0d4c37b21510
Maybe some probe bugs, you tried with the sdfgi to see if it happens the same?
It's the same in SDFGI (at least at Y Scale 100%), no leaking in SDF representation, but leaking in normal render:
With occlusion:
https://github.com/godotengine/godot/assets/39361911/8a9579a4-3166-477a-aade-79319436d988
Curiously, if you disable occlusion, you can see the leaking in the SDF representation, and now it matches up with the normal render:
Without occlusion:
https://github.com/godotengine/godot/assets/39361911/e333835f-e885-4f54-8b17-f750e9451e9e
Maybe occlusion code bug then.
HDDAGI inherits #77551, dynamic omnilights/spotlights are also culled at too short ranges (although slightly longer range than static lights)
Maybe occlusion code bug then.
Oof, then i guess high density probes are the way to go, it all seem’s like so as the occlusion is the same as with the sdfgi one if i remember correctly ehat juan said.
I get a crash if I hide a VoxelGI node while HDDAGI is enabled:
================================================================
handle_crash: Program crashed with signal 11
Engine version: Godot Engine v4.3.dev.custom_build (acecf9b48114a10f2f5a66d29bae224ccd3c09a8)
Dumping the backtrace. Please include this when reporting the bug to the project developer.
[1] /lib64/libc.so.6(+0x3e9a0) [0x7fee4425c9a0] (??:0)
[2] bin/godot.linuxbsd.editor.x86_64() [0x7d952dc] (/home/hugo/Documents/Git/godotengine/godot/./core/object/ref_counted.h:105)
[3] bin/godot.linuxbsd.editor.x86_64() [0x7e3f8fc] (/home/hugo/Documents/Git/godotengine/godot/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp:1470 (discriminator 1))
[4] bin/godot.linuxbsd.editor.x86_64() [0x7e45708] (/home/hugo/Documents/Git/godotengine/godot/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp:1977 (discriminator 12))
[5] bin/godot.linuxbsd.editor.x86_64() [0x7c4bd0e] (/home/hugo/Documents/Git/godotengine/godot/./servers/rendering/renderer_rd/renderer_scene_render_rd.cpp:1110)
[6] bin/godot.linuxbsd.editor.x86_64() [0x79c3034] (/home/hugo/Documents/Git/godotengine/godot/./servers/rendering/renderer_scene_cull.cpp:3341 (discriminator 4))
[7] bin/godot.linuxbsd.editor.x86_64() [0x79ac26f] (/home/hugo/Documents/Git/godotengine/godot/./servers/rendering/renderer_scene_cull.cpp:2615 (discriminator 1))
[8] bin/godot.linuxbsd.editor.x86_64() [0x7a0ac76] (/home/hugo/Documents/Git/godotengine/godot/./servers/rendering/renderer_viewport.cpp:254 (discriminator 1))
[9] bin/godot.linuxbsd.editor.x86_64() [0x7a0b2e8] (/home/hugo/Documents/Git/godotengine/godot/./servers/rendering/renderer_viewport.cpp:322)
[10] bin/godot.linuxbsd.editor.x86_64() [0x7a1105e] (/home/hugo/Documents/Git/godotengine/godot/./servers/rendering/renderer_viewport.cpp:777)
[11] bin/godot.linuxbsd.editor.x86_64() [0x7a62e09] (/home/hugo/Documents/Git/godotengine/godot/./servers/rendering/rendering_server_default.cpp:92)
[12] bin/godot.linuxbsd.editor.x86_64() [0x7a65b8f] (/home/hugo/Documents/Git/godotengine/godot/./servers/rendering/rendering_server_default.cpp:388)
[13] bin/godot.linuxbsd.editor.x86_64() [0x2899e9f] (/home/hugo/Documents/Git/godotengine/godot/main/main.cpp:3800)
[14] bin/godot.linuxbsd.editor.x86_64() [0x27f79fc] (/home/hugo/Documents/Git/godotengine/godot/platform/linuxbsd/os_linuxbsd.cpp:933 (discriminator 1))
[15] bin/godot.linuxbsd.editor.x86_64() [0x27ecf90] (/home/hugo/Documents/Git/godotengine/godot/platform/linuxbsd/godot_linuxbsd.cpp:76)
[16] /lib64/libc.so.6(+0x2814a) [0x7fee4424614a] (??:0)
[17] /lib64/libc.so.6(__libc_start_main+0x8b) [0x7fee4424620b] (??:0)
[18] bin/godot.linuxbsd.editor.x86_64() [0x27ecd75] (??:?)
-- END OF BACKTRACE --
================================================================
[1] 48745 IOT instruction (core dumped) bin/godot.linuxbsd.editor.x86_64
Also, sparkles are occasionally visible in reflections when reflection filter is disabled (both with half-resolution GI and full-resolution GI, although it's more noticeable with half-resolution). Example with the reflections on the scene's roofs:
Testing project: test_hddagi_voxelgi.zip
While baking VoxelGI: (Please don't mind the engine version)
handle_crash: Program crashed with signal 11
Engine version: Godot Engine v5.0.stable.official (81cd2f1217ad7e6567cb89fde3db1647e6c4a0c2)
Dumping the backtrace. Please include this when reporting the bug to the project developer.
[1] /usr/lib/libc.so.6(+0x3e710) [0x7fdf670c3710] (??:0)
[2] RendererRD::GI::process_gi(Ref<RenderSceneBuffersRD>, RID const*, RID, RID, unsigned int, Projection const*, Vector3 const*, Transform3D const&, PagedArray<RID> const&) (/home/radiant/godot/servers/rendering/renderer_rd/environment/gi.cpp:3503 (discriminator 1))
[3] RendererSceneRenderImplementation::RenderForwardClustered::_pre_opaque_render(RenderDataRD*, bool, bool, bool, RID const*, RID) (/home/radiant/godot/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp:1470 (discriminator 1))
[4] RendererSceneRenderImplementation::RenderForwardClustered::_render_scene(RenderDataRD*, Color const&) (/home/radiant/godot/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp:1977 (discriminator 12))
[5] RendererSceneRenderRD::render_scene(Ref<RenderSceneBuffers> const&, RendererSceneRender::CameraData const*, RendererSceneRender::CameraData const*, PagedArray<RenderGeometryInstance*> const&, PagedArray<RID> const&, PagedArray<RID> const&, PagedArray<RID> const&, PagedArray<RID> const&, PagedArray<RID> const&, PagedArray<RID> const&, RID, RID, RID, RID, RID, RID, int, float, RendererSceneRender::RenderShadowData const*, int, RendererSceneRender::RenderHDDAGIData const*, int, RendererSceneRender::RenderHDDAGIUpdateData const*, RenderingMethod::RenderInfo*) (/home/radiant/godot/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp:1110)
[6] RendererSceneCull::_render_scene(RendererSceneRender::CameraData const*, Ref<RenderSceneBuffers> const&, RID, RID, unsigned int, RID, RID, RID, RID, int, float, bool, RenderingMethod::RenderInfo*) (/home/radiant/godot/servers/rendering/renderer_scene_cull.cpp:3341 (discriminator 4))
[7] RendererSceneCull::render_camera(Ref<RenderSceneBuffers> const&, RID, RID, RID, Vector2, unsigned int, float, RID, Ref<XRInterface>&, RenderingMethod::RenderInfo*) (/home/radiant/godot/servers/rendering/renderer_scene_cull.cpp:2615 (discriminator 1))
[8] RendererViewport::_draw_3d(RendererViewport::Viewport*) (/home/radiant/godot/servers/rendering/renderer_viewport.cpp:254 (discriminator 1))
[9] RendererViewport::_draw_viewport(RendererViewport::Viewport*) (/home/radiant/godot/servers/rendering/renderer_viewport.cpp:322)
[10] RendererViewport::draw_viewports(bool) (/home/radiant/godot/servers/rendering/renderer_viewport.cpp:777)
[11] RenderingServerDefault::_draw(bool, double) (/home/radiant/godot/servers/rendering/rendering_server_default.cpp:92)
[12] RenderingServerDefault::draw(bool, double) (/home/radiant/godot/servers/rendering/rendering_server_default.cpp:388)
[13] Main::iteration() (/home/radiant/godot/main/main.cpp:3800)
[14] OS_LinuxBSD::run() (/home/radiant/godot/platform/linuxbsd/os_linuxbsd.cpp:933 (discriminator 1))
[15] /home/radiant/godot/bin/godot.linuxbsd.editor.dev.x86_64(main+0x19b) [0x55bbdc168ea4] (/home/radiant/godot/platform/linuxbsd/godot_linuxbsd.cpp:76)
[16] /usr/lib/libc.so.6(+0x27cd0) [0x7fdf670accd0] (??:0)
[17] /usr/lib/libc.so.6(__libc_start_main+0x8a) [0x7fdf670acd8a] (??:0)
[18] /home/radiant/godot/bin/godot.linuxbsd.editor.dev.x86_64(_start+0x25) [0x55bbdc168c35] (??:?)```
I am having issues uploading the core dump with the 25 MB upload limit.