From 32625145c8ba20a304c1f70090c34dfe7e9be435 Mon Sep 17 00:00:00 2001 From: reduz Date: Fri, 4 Jun 2021 19:47:26 -0300 Subject: Rename GI Classes * GIProbe is now VoxelGI * BakedLightmap is now LightmapGI As godot adds more ways to provide GI (as an example, SDFGI in 4.0), the different techniques (which have different pros/cons) need to be properly named to avoid confusion. --- doc/classes/BakedLightmap.xml | 81 -- doc/classes/BakedLightmapData.xml | 65 - doc/classes/BaseMaterial3D.xml | 2 +- doc/classes/Environment.xml | 2 +- doc/classes/GIProbe.xml | 63 - doc/classes/GIProbeData.xml | 92 -- doc/classes/Light3D.xml | 2 +- doc/classes/LightmapGI.xml | 81 ++ doc/classes/LightmapGIData.xml | 65 + doc/classes/ProjectSettings.xml | 10 +- doc/classes/ReflectionProbe.xml | 2 +- doc/classes/RenderingServer.xml | 16 +- doc/classes/Viewport.xml | 12 +- doc/classes/VoxelGI.xml | 63 + doc/classes/VoxelGIData.xml | 92 ++ editor/editor_node.cpp | 12 +- editor/icons/BakedLightmap.svg | 1 - editor/icons/BakedLightmapData.svg | 1 - editor/icons/GIProbe.svg | 1 - editor/icons/GIProbeData.svg | 1 - editor/icons/LightmapGI.svg | 1 + editor/icons/LightmapGIData.svg | 1 + editor/icons/VoxelGI.svg | 1 + editor/icons/VoxelGIData.svg | 1 + editor/node_3d_editor_gizmos.cpp | 82 +- editor/node_3d_editor_gizmos.h | 12 +- editor/plugins/baked_lightmap_editor_plugin.cpp | 138 -- editor/plugins/baked_lightmap_editor_plugin.h | 69 - editor/plugins/gi_probe_editor_plugin.cpp | 173 --- editor/plugins/gi_probe_editor_plugin.h | 74 - editor/plugins/lightmap_gi_editor_plugin.cpp | 138 ++ editor/plugins/lightmap_gi_editor_plugin.h | 69 + editor/plugins/node_3d_editor_plugin.cpp | 28 +- editor/plugins/node_3d_editor_plugin.h | 6 +- editor/plugins/voxel_gi_editor_plugin.cpp | 173 +++ editor/plugins/voxel_gi_editor_plugin.h | 74 + scene/3d/baked_lightmap.cpp | 1466 -------------------- scene/3d/baked_lightmap.h | 284 ---- scene/3d/gi_probe.cpp | 549 -------- scene/3d/gi_probe.h | 176 --- scene/3d/lightmap_gi.cpp | 1466 ++++++++++++++++++++ scene/3d/lightmap_gi.h | 284 ++++ scene/3d/voxel_gi.cpp | 549 ++++++++ scene/3d/voxel_gi.h | 176 +++ scene/3d/voxelizer.cpp | 14 +- scene/3d/voxelizer.h | 12 +- scene/main/viewport.cpp | 6 +- scene/main/viewport.h | 6 +- scene/register_scene_types.cpp | 16 +- servers/rendering/rasterizer_dummy.h | 78 +- servers/rendering/renderer_rd/effects_rd.cpp | 12 +- servers/rendering/renderer_rd/effects_rd.h | 4 +- .../forward_clustered/render_forward_clustered.cpp | 146 +- .../forward_clustered/render_forward_clustered.h | 26 +- .../scene_shader_forward_clustered.cpp | 4 +- .../scene_shader_forward_clustered.h | 2 +- .../forward_mobile/render_forward_mobile.cpp | 10 +- .../forward_mobile/render_forward_mobile.h | 6 +- .../forward_mobile/scene_shader_forward_mobile.cpp | 2 +- .../rendering/renderer_rd/renderer_scene_gi_rd.cpp | 290 ++-- .../rendering/renderer_rd/renderer_scene_gi_rd.h | 118 +- .../renderer_rd/renderer_scene_render_rd.cpp | 82 +- .../renderer_rd/renderer_scene_render_rd.h | 26 +- .../rendering/renderer_rd/renderer_storage_rd.cpp | 390 +++--- .../rendering/renderer_rd/renderer_storage_rd.h | 88 +- servers/rendering/renderer_rd/shaders/gi.glsl | 76 +- servers/rendering/renderer_rd/shaders/giprobe.glsl | 779 ----------- .../renderer_rd/shaders/giprobe_debug.glsl | 229 --- .../rendering/renderer_rd/shaders/giprobe_sdf.glsl | 181 --- servers/rendering/renderer_rd/shaders/resolve.glsl | 22 +- .../shaders/scene_forward_clustered.glsl | 22 +- .../shaders/scene_forward_clustered_inc.glsl | 20 +- .../renderer_rd/shaders/scene_forward_gi_inc.glsl | 32 +- .../shaders/scene_forward_mobile_inc.glsl | 2 +- .../renderer_rd/shaders/volumetric_fog.glsl | 32 +- .../rendering/renderer_rd/shaders/voxel_gi.glsl | 779 +++++++++++ .../renderer_rd/shaders/voxel_gi_debug.glsl | 229 +++ .../renderer_rd/shaders/voxel_gi_sdf.glsl | 181 +++ servers/rendering/renderer_scene.h | 2 +- servers/rendering/renderer_scene_cull.cpp | 184 +-- servers/rendering/renderer_scene_cull.h | 24 +- servers/rendering/renderer_scene_render.h | 14 +- servers/rendering/renderer_storage.h | 64 +- servers/rendering/rendering_server_default.h | 60 +- servers/rendering_server.cpp | 62 +- servers/rendering_server.h | 76 +- 86 files changed, 5532 insertions(+), 5530 deletions(-) delete mode 100644 doc/classes/BakedLightmap.xml delete mode 100644 doc/classes/BakedLightmapData.xml delete mode 100644 doc/classes/GIProbe.xml delete mode 100644 doc/classes/GIProbeData.xml create mode 100644 doc/classes/LightmapGI.xml create mode 100644 doc/classes/LightmapGIData.xml create mode 100644 doc/classes/VoxelGI.xml create mode 100644 doc/classes/VoxelGIData.xml delete mode 100644 editor/icons/BakedLightmap.svg delete mode 100644 editor/icons/BakedLightmapData.svg delete mode 100644 editor/icons/GIProbe.svg delete mode 100644 editor/icons/GIProbeData.svg create mode 100644 editor/icons/LightmapGI.svg create mode 100644 editor/icons/LightmapGIData.svg create mode 100644 editor/icons/VoxelGI.svg create mode 100644 editor/icons/VoxelGIData.svg delete mode 100644 editor/plugins/baked_lightmap_editor_plugin.cpp delete mode 100644 editor/plugins/baked_lightmap_editor_plugin.h delete mode 100644 editor/plugins/gi_probe_editor_plugin.cpp delete mode 100644 editor/plugins/gi_probe_editor_plugin.h create mode 100644 editor/plugins/lightmap_gi_editor_plugin.cpp create mode 100644 editor/plugins/lightmap_gi_editor_plugin.h create mode 100644 editor/plugins/voxel_gi_editor_plugin.cpp create mode 100644 editor/plugins/voxel_gi_editor_plugin.h delete mode 100644 scene/3d/baked_lightmap.cpp delete mode 100644 scene/3d/baked_lightmap.h delete mode 100644 scene/3d/gi_probe.cpp delete mode 100644 scene/3d/gi_probe.h create mode 100644 scene/3d/lightmap_gi.cpp create mode 100644 scene/3d/lightmap_gi.h create mode 100644 scene/3d/voxel_gi.cpp create mode 100644 scene/3d/voxel_gi.h delete mode 100644 servers/rendering/renderer_rd/shaders/giprobe.glsl delete mode 100644 servers/rendering/renderer_rd/shaders/giprobe_debug.glsl delete mode 100644 servers/rendering/renderer_rd/shaders/giprobe_sdf.glsl create mode 100644 servers/rendering/renderer_rd/shaders/voxel_gi.glsl create mode 100644 servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl create mode 100644 servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl diff --git a/doc/classes/BakedLightmap.xml b/doc/classes/BakedLightmap.xml deleted file mode 100644 index 6fd08fc4e4..0000000000 --- a/doc/classes/BakedLightmap.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/classes/BakedLightmapData.xml b/doc/classes/BakedLightmapData.xml deleted file mode 100644 index 904555c48e..0000000000 --- a/doc/classes/BakedLightmapData.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml index 0a7b4c5dab..3b4a001f7e 100644 --- a/doc/classes/BaseMaterial3D.xml +++ b/doc/classes/BaseMaterial3D.xml @@ -199,7 +199,7 @@ The emitted light's color. See [member emission_enabled]. - If [code]true[/code], the body emits light. Emitting light makes the object appear brighter. The object can also cast light on other objects if a [GIProbe] is used and this object is used in baked lighting. + If [code]true[/code], the body emits light. Emitting light makes the object appear brighter. The object can also cast light on other objects if a [VoxelGI] is used and this object is used in baked lighting. The emitted light's strength. See [member emission_enabled]. diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml index 6909fac2b7..878535a08d 100644 --- a/doc/classes/Environment.xml +++ b/doc/classes/Environment.xml @@ -206,7 +206,7 @@ The depth tolerance for screen-space reflections. - If [code]true[/code], screen-space reflections are enabled. Screen-space reflections are more accurate than reflections from [GIProbe]s or [ReflectionProbe]s, but are slower and can't reflect surfaces occluded by others. + If [code]true[/code], screen-space reflections are enabled. Screen-space reflections are more accurate than reflections from [VoxelGI]s or [ReflectionProbe]s, but are slower and can't reflect surfaces occluded by others. The fade-in distance for screen-space reflections. Affects the area from the reflected material to the screen-space reflection). diff --git a/doc/classes/GIProbe.xml b/doc/classes/GIProbe.xml deleted file mode 100644 index 4f56d1ad3e..0000000000 --- a/doc/classes/GIProbe.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - Real-time global illumination (GI) probe. - - - [GIProbe]s are used to provide high-quality real-time indirect light to scenes. They precompute the effect of objects that emit light and the effect of static geometry to simulate the behavior of complex light in real-time. [GIProbe]s need to be baked before using, however, once baked, dynamic objects will receive light from them. Further, lights can be fully dynamic or baked. - Having [GIProbe]s in a scene can be expensive, the quality of the probe can be turned down in exchange for better performance in the [ProjectSettings] using [member ProjectSettings.rendering/global_illumination/gi_probes/quality]. - [b]Note:[/b] Meshes should have sufficiently thick walls to avoid light leaks (avoid one-sided walls). For interior levels, enclose your level geometry in a sufficiently large box and bridge the loops to close the mesh. - - - https://docs.godotengine.org/en/latest/tutorials/3d/gi_probes.html - https://godotengine.org/asset-library/asset/678 - - - - - - - - - - - Bakes the effect from all [GeometryInstance3D]s marked with [constant GeometryInstance3D.GI_MODE_BAKED] and [Light3D]s marked with either [constant Light3D.BAKE_DYNAMIC] or [constant Light3D.BAKE_STATIC]. If [code]create_visual_debug[/code] is [code]true[/code], after baking the light, this will generate a [MultiMesh] that has a cube representing each solid cell with each cube colored to the cell's albedo color. This can be used to visualize the [GIProbe]'s data and debug any issues that may be occurring. - - - - - - - Calls [method bake] with [code]create_visual_debug[/code] enabled. - - - - - - The [GIProbeData] resource that holds the data for this [GIProbe]. - - - The size of the area covered by the [GIProbe]. If you make the extents larger without increasing the subdivisions with [member subdiv], the size of each cell will increase and result in lower detailed lighting. - - - Number of times to subdivide the grid that the [GIProbe] operates on. A higher number results in finer detail and thus higher visual quality, while lower numbers result in better performance. - - - - - Use 64 subdivisions. This is the lowest quality setting, but the fastest. Use it if you can, but especially use it on lower-end hardware. - - - Use 128 subdivisions. This is the default quality setting. - - - Use 256 subdivisions. - - - Use 512 subdivisions. This is the highest quality setting, but the slowest. On lower-end hardware this could cause the GPU to stall. - - - Represents the size of the [enum Subdiv] enum. - - - diff --git a/doc/classes/GIProbeData.xml b/doc/classes/GIProbeData.xml deleted file mode 100644 index 8549011b19..0000000000 --- a/doc/classes/GIProbeData.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - https://godotengine.org/asset-library/asset/678 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/classes/Light3D.xml b/doc/classes/Light3D.xml index 6bae612c9f..42b9ed8ab4 100644 --- a/doc/classes/Light3D.xml +++ b/doc/classes/Light3D.xml @@ -52,7 +52,7 @@ The light's strength multiplier (this is not a physical unit). For [OmniLight3D] and [SpotLight3D], changing this value will only change the light color's intensity, not the light's radius. - Secondary multiplier used with indirect light (light bounces). Used with [GIProbe]. + Secondary multiplier used with indirect light (light bounces). Used with [VoxelGI]. If [code]true[/code], the light's effect is reversed, darkening areas and casting bright shadows. diff --git a/doc/classes/LightmapGI.xml b/doc/classes/LightmapGI.xml new file mode 100644 index 0000000000..d7722a83b0 --- /dev/null +++ b/doc/classes/LightmapGI.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/classes/LightmapGIData.xml b/doc/classes/LightmapGIData.xml new file mode 100644 index 0000000000..3a37c6dcb7 --- /dev/null +++ b/doc/classes/LightmapGIData.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 7d7d744c1b..b74a1f848b 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -1421,18 +1421,16 @@ - - If [code]true[/code], take additional samples when rendering objects affected by a [GIProbe] to reduce artifacts from only sampling in one direction. - - - Sets the number of cone samples taken when rendering objects affected by [GIProbe]s. - + + + + diff --git a/doc/classes/ReflectionProbe.xml b/doc/classes/ReflectionProbe.xml index cd08778c89..13df17cd22 100644 --- a/doc/classes/ReflectionProbe.xml +++ b/doc/classes/ReflectionProbe.xml @@ -5,7 +5,7 @@ Captures its surroundings as a cubemap, and stores versions of it with increasing levels of blur to simulate different material roughnesses. - The [ReflectionProbe] is used to create high-quality reflections at the cost of performance. It can be combined with [GIProbe]s and Screen Space Reflections to achieve high quality reflections. [ReflectionProbe]s render all objects within their [member cull_mask], so updating them can be quite expensive. It is best to update them once with the important static objects and then leave them. + The [ReflectionProbe] is used to create high-quality reflections at the cost of performance. It can be combined with [VoxelGI]s and Screen Space Reflections to achieve high quality reflections. [ReflectionProbe]s render all objects within their [member cull_mask], so updating them can be quite expensive. It is best to update them once with the important static objects and then leave them. https://docs.godotengine.org/en/latest/tutorials/3d/reflection_probes.html diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 02130333f9..ba19176788 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -3477,14 +3477,14 @@ Normal buffer is drawn instead of regular scene so you can see the per-pixel normals that will be used by post-processing effects. - - Objects are displayed with only the albedo value from [GIProbe]s. + + Objects are displayed with only the albedo value from [VoxelGI]s. - - Objects are displayed with only the lighting value from [GIProbe]s. + + Objects are displayed with only the lighting value from [VoxelGI]s. - - Objects are displayed with only the emission color from [GIProbe]s. + + Objects are displayed with only the emission color from [VoxelGI]s. Draws the shadow atlas that stores shadows from [OmniLight3D]s and [SpotLight3D]s in the upper left quadrant of the [Viewport]. @@ -3694,8 +3694,8 @@ The instance is a decal. - - The instance is a GI probe. + + The instance is a VoxelGI. The instance is a lightmap. diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml index 1c33274cb0..7f05b14765 100644 --- a/doc/classes/Viewport.xml +++ b/doc/classes/Viewport.xml @@ -382,14 +382,14 @@ - - Objects are displayed with only the albedo value from [GIProbe]s. + + Objects are displayed with only the albedo value from [VoxelGI]s. - - Objects are displayed with only the lighting value from [GIProbe]s. + + Objects are displayed with only the lighting value from [VoxelGI]s. - - Objects are displayed with only the emission color from [GIProbe]s. + + Objects are displayed with only the emission color from [VoxelGI]s. Draws the shadow atlas that stores shadows from [OmniLight3D]s and [SpotLight3D]s in the upper left quadrant of the [Viewport]. diff --git a/doc/classes/VoxelGI.xml b/doc/classes/VoxelGI.xml new file mode 100644 index 0000000000..fa5035349e --- /dev/null +++ b/doc/classes/VoxelGI.xml @@ -0,0 +1,63 @@ + + + + Real-time global illumination (GI) probe. + + + [VoxelGI]s are used to provide high-quality real-time indirect light to scenes. They precompute the effect of objects that emit light and the effect of static geometry to simulate the behavior of complex light in real-time. [VoxelGI]s need to be baked before using, however, once baked, dynamic objects will receive light from them. Further, lights can be fully dynamic or baked. + Having [VoxelGI]s in a scene can be expensive, the quality of the probe can be turned down in exchange for better performance in the [ProjectSettings] using [member ProjectSettings.rendering/global_illumination/voxel_gi/quality]. + [b]Note:[/b] Meshes should have sufficiently thick walls to avoid light leaks (avoid one-sided walls). For interior levels, enclose your level geometry in a sufficiently large box and bridge the loops to close the mesh. + + + https://docs.godotengine.org/en/latest/tutorials/3d/voxel_gi.html + https://godotengine.org/asset-library/asset/678 + + + + + + + + + + + Bakes the effect from all [GeometryInstance3D]s marked with [constant GeometryInstance3D.GI_MODE_BAKED] and [Light3D]s marked with either [constant Light3D.BAKE_DYNAMIC] or [constant Light3D.BAKE_STATIC]. If [code]create_visual_debug[/code] is [code]true[/code], after baking the light, this will generate a [MultiMesh] that has a cube representing each solid cell with each cube colored to the cell's albedo color. This can be used to visualize the [VoxelGI]'s data and debug any issues that may be occurring. + + + + + + + Calls [method bake] with [code]create_visual_debug[/code] enabled. + + + + + + The [VoxelGIData] resource that holds the data for this [VoxelGI]. + + + The size of the area covered by the [VoxelGI]. If you make the extents larger without increasing the subdivisions with [member subdiv], the size of each cell will increase and result in lower detailed lighting. + + + Number of times to subdivide the grid that the [VoxelGI] operates on. A higher number results in finer detail and thus higher visual quality, while lower numbers result in better performance. + + + + + Use 64 subdivisions. This is the lowest quality setting, but the fastest. Use it if you can, but especially use it on lower-end hardware. + + + Use 128 subdivisions. This is the default quality setting. + + + Use 256 subdivisions. + + + Use 512 subdivisions. This is the highest quality setting, but the slowest. On lower-end hardware this could cause the GPU to stall. + + + Represents the size of the [enum Subdiv] enum. + + + diff --git a/doc/classes/VoxelGIData.xml b/doc/classes/VoxelGIData.xml new file mode 100644 index 0000000000..88a0411e2b --- /dev/null +++ b/doc/classes/VoxelGIData.xml @@ -0,0 +1,92 @@ + + + + + + + + https://godotengine.org/asset-library/asset/678 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 85d19eb747..6cc35c7979 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -119,7 +119,6 @@ #include "editor/plugins/animation_tree_editor_plugin.h" #include "editor/plugins/asset_library_editor_plugin.h" #include "editor/plugins/audio_stream_editor_plugin.h" -#include "editor/plugins/baked_lightmap_editor_plugin.h" #include "editor/plugins/camera_3d_editor_plugin.h" #include "editor/plugins/canvas_item_editor_plugin.h" #include "editor/plugins/collision_polygon_2d_editor_plugin.h" @@ -132,13 +131,13 @@ #include "editor/plugins/editor_debugger_plugin.h" #include "editor/plugins/editor_preview_plugins.h" #include "editor/plugins/font_editor_plugin.h" -#include "editor/plugins/gi_probe_editor_plugin.h" #include "editor/plugins/gpu_particles_2d_editor_plugin.h" #include "editor/plugins/gpu_particles_3d_editor_plugin.h" #include "editor/plugins/gpu_particles_collision_sdf_editor_plugin.h" #include "editor/plugins/gradient_editor_plugin.h" #include "editor/plugins/item_list_editor_plugin.h" #include "editor/plugins/light_occluder_2d_editor_plugin.h" +#include "editor/plugins/lightmap_gi_editor_plugin.h" #include "editor/plugins/line_2d_editor_plugin.h" #include "editor/plugins/material_editor_plugin.h" #include "editor/plugins/mesh_editor_plugin.h" @@ -175,6 +174,7 @@ #include "editor/plugins/tiles/tiles_editor_plugin.h" #include "editor/plugins/version_control_editor_plugin.h" #include "editor/plugins/visual_shader_editor_plugin.h" +#include "editor/plugins/voxel_gi_editor_plugin.h" #include "editor/progress_dialog.h" #include "editor/project_export.h" #include "editor/project_settings_editor.h" @@ -484,8 +484,8 @@ void EditorNode::_update_from_settings() { RS::get_singleton()->environment_set_sdfgi_frames_to_converge(frames_to_converge); RS::EnvironmentSDFGIRayCount ray_count = RS::EnvironmentSDFGIRayCount(int(GLOBAL_GET("rendering/global_illumination/sdfgi/probe_ray_count"))); RS::get_singleton()->environment_set_sdfgi_ray_count(ray_count); - RS::GIProbeQuality gi_probe_quality = RS::GIProbeQuality(int(GLOBAL_GET("rendering/global_illumination/gi_probes/quality"))); - RS::get_singleton()->gi_probe_set_quality(gi_probe_quality); + RS::VoxelGIQuality voxel_gi_quality = RS::VoxelGIQuality(int(GLOBAL_GET("rendering/global_illumination/voxel_gi/quality"))); + RS::get_singleton()->voxel_gi_set_quality(voxel_gi_quality); RS::get_singleton()->environment_set_volumetric_fog_volume_size(GLOBAL_GET("rendering/environment/volumetric_fog/volume_size"), GLOBAL_GET("rendering/environment/volumetric_fog/volume_depth")); RS::get_singleton()->environment_set_volumetric_fog_filter_active(bool(GLOBAL_GET("rendering/environment/volumetric_fog/use_filter"))); RS::get_singleton()->canvas_set_shadow_texture_size(GLOBAL_GET("rendering/2d/shadow_atlas/size")); @@ -6818,8 +6818,8 @@ EditorNode::EditorNode() { add_editor_plugin(memnew(TilesEditorPlugin(this))); add_editor_plugin(memnew(SpriteFramesEditorPlugin(this))); add_editor_plugin(memnew(TextureRegionEditorPlugin(this))); - add_editor_plugin(memnew(GIProbeEditorPlugin(this))); - add_editor_plugin(memnew(BakedLightmapEditorPlugin(this))); + add_editor_plugin(memnew(VoxelGIEditorPlugin(this))); + add_editor_plugin(memnew(LightmapGIEditorPlugin(this))); add_editor_plugin(memnew(OccluderInstance3DEditorPlugin(this))); add_editor_plugin(memnew(Path2DEditorPlugin(this))); add_editor_plugin(memnew(Path3DEditorPlugin(this))); diff --git a/editor/icons/BakedLightmap.svg b/editor/icons/BakedLightmap.svg deleted file mode 100644 index 78f0a64a7b..0000000000 --- a/editor/icons/BakedLightmap.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/editor/icons/BakedLightmapData.svg b/editor/icons/BakedLightmapData.svg deleted file mode 100644 index f5dcfb618b..0000000000 --- a/editor/icons/BakedLightmapData.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/editor/icons/GIProbe.svg b/editor/icons/GIProbe.svg deleted file mode 100644 index f5e1025260..0000000000 --- a/editor/icons/GIProbe.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/editor/icons/GIProbeData.svg b/editor/icons/GIProbeData.svg deleted file mode 100644 index 5975115f4c..0000000000 --- a/editor/icons/GIProbeData.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/editor/icons/LightmapGI.svg b/editor/icons/LightmapGI.svg new file mode 100644 index 0000000000..78f0a64a7b --- /dev/null +++ b/editor/icons/LightmapGI.svg @@ -0,0 +1 @@ + diff --git a/editor/icons/LightmapGIData.svg b/editor/icons/LightmapGIData.svg new file mode 100644 index 0000000000..f5dcfb618b --- /dev/null +++ b/editor/icons/LightmapGIData.svg @@ -0,0 +1 @@ + diff --git a/editor/icons/VoxelGI.svg b/editor/icons/VoxelGI.svg new file mode 100644 index 0000000000..f5e1025260 --- /dev/null +++ b/editor/icons/VoxelGI.svg @@ -0,0 +1 @@ + diff --git a/editor/icons/VoxelGIData.svg b/editor/icons/VoxelGIData.svg new file mode 100644 index 0000000000..5975115f4c --- /dev/null +++ b/editor/icons/VoxelGIData.svg @@ -0,0 +1 @@ + diff --git a/editor/node_3d_editor_gizmos.cpp b/editor/node_3d_editor_gizmos.cpp index 92feb343c6..5dd8c8f9fb 100644 --- a/editor/node_3d_editor_gizmos.cpp +++ b/editor/node_3d_editor_gizmos.cpp @@ -34,15 +34,14 @@ #include "core/math/geometry_2d.h" #include "core/math/geometry_3d.h" #include "scene/3d/audio_stream_player_3d.h" -#include "scene/3d/baked_lightmap.h" #include "scene/3d/collision_polygon_3d.h" #include "scene/3d/collision_shape_3d.h" #include "scene/3d/cpu_particles_3d.h" #include "scene/3d/decal.h" -#include "scene/3d/gi_probe.h" #include "scene/3d/gpu_particles_3d.h" #include "scene/3d/gpu_particles_collision_3d.h" #include "scene/3d/light_3d.h" +#include "scene/3d/lightmap_gi.h" #include "scene/3d/lightmap_probe.h" #include "scene/3d/listener_3d.h" #include "scene/3d/mesh_instance_3d.h" @@ -57,6 +56,7 @@ #include "scene/3d/sprite_3d.h" #include "scene/3d/vehicle_body_3d.h" #include "scene/3d/visibility_notifier_3d.h" +#include "scene/3d/voxel_gi.h" #include "scene/resources/box_shape_3d.h" #include "scene/resources/capsule_shape_3d.h" #include "scene/resources/concave_polygon_shape_3d.h" @@ -3086,35 +3086,35 @@ void DecalGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { } /////////////////////////////// -GIProbeGizmoPlugin::GIProbeGizmoPlugin() { - Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/gi_probe", Color(0.5, 1, 0.6)); +VoxelGIGizmoPlugin::VoxelGIGizmoPlugin() { + Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/voxel_gi", Color(0.5, 1, 0.6)); - create_material("gi_probe_material", gizmo_color); + create_material("voxel_gi_material", gizmo_color); // This gizmo draws a lot of lines. Use a low opacity to make it not too intrusive. gizmo_color.a = 0.1; - create_material("gi_probe_internal_material", gizmo_color); + create_material("voxel_gi_internal_material", gizmo_color); gizmo_color.a = 0.05; - create_material("gi_probe_solid_material", gizmo_color); + create_material("voxel_gi_solid_material", gizmo_color); - create_icon_material("gi_probe_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoGIProbe", "EditorIcons")); + create_icon_material("voxel_gi_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoVoxelGI", "EditorIcons")); create_handle_material("handles"); } -bool GIProbeGizmoPlugin::has_gizmo(Node3D *p_spatial) { - return Object::cast_to(p_spatial) != nullptr; +bool VoxelGIGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to(p_spatial) != nullptr; } -String GIProbeGizmoPlugin::get_gizmo_name() const { - return "GIProbe"; +String VoxelGIGizmoPlugin::get_gizmo_name() const { + return "VoxelGI"; } -int GIProbeGizmoPlugin::get_priority() const { +int VoxelGIGizmoPlugin::get_priority() const { return -1; } -String GIProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const { +String VoxelGIGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const { switch (p_idx) { case 0: return "Extents X"; @@ -3127,13 +3127,13 @@ String GIProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int return ""; } -Variant GIProbeGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { - GIProbe *probe = Object::cast_to(p_gizmo->get_spatial_node()); +Variant VoxelGIGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { + VoxelGI *probe = Object::cast_to(p_gizmo->get_spatial_node()); return probe->get_extents(); } -void GIProbeGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) { - GIProbe *probe = Object::cast_to(p_gizmo->get_spatial_node()); +void VoxelGIGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) { + VoxelGI *probe = Object::cast_to(p_gizmo->get_spatial_node()); Transform3D gt = probe->get_global_transform(); Transform3D gi = gt.affine_inverse(); @@ -3163,8 +3163,8 @@ void GIProbeGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camer probe->set_extents(extents); } -void GIProbeGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { - GIProbe *probe = Object::cast_to(p_gizmo->get_spatial_node()); +void VoxelGIGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { + VoxelGI *probe = Object::cast_to(p_gizmo->get_spatial_node()); Vector3 restore = p_restore; @@ -3180,19 +3180,19 @@ void GIProbeGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, co ur->commit_action(); } -void GIProbeGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { - GIProbe *probe = Object::cast_to(p_gizmo->get_spatial_node()); +void VoxelGIGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { + VoxelGI *probe = Object::cast_to(p_gizmo->get_spatial_node()); - Ref material = get_material("gi_probe_material", p_gizmo); - Ref icon = get_material("gi_probe_icon", p_gizmo); - Ref material_internal = get_material("gi_probe_internal_material", p_gizmo); + Ref material = get_material("voxel_gi_material", p_gizmo); + Ref icon = get_material("voxel_gi_icon", p_gizmo); + Ref material_internal = get_material("voxel_gi_internal_material", p_gizmo); p_gizmo->clear(); Vector lines; Vector3 extents = probe->get_extents(); - static const int subdivs[GIProbe::SUBDIV_MAX] = { 64, 128, 256, 512 }; + static const int subdivs[VoxelGI::SUBDIV_MAX] = { 64, 128, 256, 512 }; AABB aabb = AABB(-extents, extents * 2); int subdiv = subdivs[probe->get_subdiv()]; @@ -3256,7 +3256,7 @@ void GIProbeGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { } if (p_gizmo->is_selected()) { - Ref solid_material = get_material("gi_probe_solid_material", p_gizmo); + Ref solid_material = get_material("voxel_gi_solid_material", p_gizmo); p_gizmo->add_solid_box(solid_material, aabb.get_size()); } @@ -3266,7 +3266,7 @@ void GIProbeGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { //// -BakedLightmapGizmoPlugin::BakedLightmapGizmoPlugin() { +LightmapGIGizmoPlugin::LightmapGIGizmoPlugin() { Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/lightmap_lines", Color(0.5, 0.6, 1)); gizmo_color.a = 0.1; @@ -3280,39 +3280,39 @@ BakedLightmapGizmoPlugin::BakedLightmapGizmoPlugin() { add_material("lightmap_probe_material", mat); - create_icon_material("baked_indirect_light_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoBakedLightmap", "EditorIcons")); + create_icon_material("baked_indirect_light_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoLightmapGI", "EditorIcons")); } -String BakedLightmapGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const { +String LightmapGIGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const { return ""; } -Variant BakedLightmapGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { +Variant LightmapGIGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { return Variant(); } -void BakedLightmapGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) { +void LightmapGIGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) { } -void BakedLightmapGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { +void LightmapGIGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { } -bool BakedLightmapGizmoPlugin::has_gizmo(Node3D *p_spatial) { - return Object::cast_to(p_spatial) != nullptr; +bool LightmapGIGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to(p_spatial) != nullptr; } -String BakedLightmapGizmoPlugin::get_gizmo_name() const { - return "BakedLightmap"; +String LightmapGIGizmoPlugin::get_gizmo_name() const { + return "LightmapGI"; } -int BakedLightmapGizmoPlugin::get_priority() const { +int LightmapGIGizmoPlugin::get_priority() const { return -1; } -void BakedLightmapGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { +void LightmapGIGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Ref icon = get_material("baked_indirect_light_icon", p_gizmo); - BakedLightmap *baker = Object::cast_to(p_gizmo->get_spatial_node()); - Ref data = baker->get_light_data(); + LightmapGI *baker = Object::cast_to(p_gizmo->get_spatial_node()); + Ref data = baker->get_light_data(); p_gizmo->add_unscaled_billboard(icon, 0.05); diff --git a/editor/node_3d_editor_gizmos.h b/editor/node_3d_editor_gizmos.h index 25958d1ad7..8a0e10241a 100644 --- a/editor/node_3d_editor_gizmos.h +++ b/editor/node_3d_editor_gizmos.h @@ -316,8 +316,8 @@ public: DecalGizmoPlugin(); }; -class GIProbeGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(GIProbeGizmoPlugin, EditorNode3DGizmoPlugin); +class VoxelGIGizmoPlugin : public EditorNode3DGizmoPlugin { + GDCLASS(VoxelGIGizmoPlugin, EditorNode3DGizmoPlugin); public: bool has_gizmo(Node3D *p_spatial) override; @@ -330,11 +330,11 @@ public: void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override; void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override; - GIProbeGizmoPlugin(); + VoxelGIGizmoPlugin(); }; -class BakedLightmapGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(BakedLightmapGizmoPlugin, EditorNode3DGizmoPlugin); +class LightmapGIGizmoPlugin : public EditorNode3DGizmoPlugin { + GDCLASS(LightmapGIGizmoPlugin, EditorNode3DGizmoPlugin); public: bool has_gizmo(Node3D *p_spatial) override; @@ -347,7 +347,7 @@ public: void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override; void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override; - BakedLightmapGizmoPlugin(); + LightmapGIGizmoPlugin(); }; class LightmapProbeGizmoPlugin : public EditorNode3DGizmoPlugin { diff --git a/editor/plugins/baked_lightmap_editor_plugin.cpp b/editor/plugins/baked_lightmap_editor_plugin.cpp deleted file mode 100644 index 470b61bf40..0000000000 --- a/editor/plugins/baked_lightmap_editor_plugin.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/*************************************************************************/ -/* baked_lightmap_editor_plugin.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "baked_lightmap_editor_plugin.h" - -void BakedLightmapEditorPlugin::_bake_select_file(const String &p_file) { - if (lightmap) { - BakedLightmap::BakeError err; - if (get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root() == lightmap) { - err = lightmap->bake(lightmap, p_file, bake_func_step); - } else { - err = lightmap->bake(lightmap->get_parent(), p_file, bake_func_step); - } - - bake_func_end(); - - switch (err) { - case BakedLightmap::BAKE_ERROR_NO_SAVE_PATH: { - String scene_path = lightmap->get_filename(); - if (scene_path == String()) { - scene_path = lightmap->get_owner()->get_filename(); - } - if (scene_path == String()) { - EditorNode::get_singleton()->show_warning(TTR("Can't determine a save path for lightmap images.\nSave your scene and try again.")); - break; - } - scene_path = scene_path.get_basename() + ".lmbake"; - - file_dialog->set_current_path(scene_path); - file_dialog->popup_file_dialog(); - - } break; - case BakedLightmap::BAKE_ERROR_NO_MESHES: - EditorNode::get_singleton()->show_warning(TTR("No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake Light' flag is on.")); - break; - case BakedLightmap::BAKE_ERROR_CANT_CREATE_IMAGE: - EditorNode::get_singleton()->show_warning(TTR("Failed creating lightmap images, make sure path is writable.")); - break; - default: { - } - } - } -} - -void BakedLightmapEditorPlugin::_bake() { - _bake_select_file(""); -} - -void BakedLightmapEditorPlugin::edit(Object *p_object) { - BakedLightmap *s = Object::cast_to(p_object); - if (!s) { - return; - } - - lightmap = s; -} - -bool BakedLightmapEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("BakedLightmap"); -} - -void BakedLightmapEditorPlugin::make_visible(bool p_visible) { - if (p_visible) { - bake->show(); - } else { - bake->hide(); - } -} - -EditorProgress *BakedLightmapEditorPlugin::tmp_progress = nullptr; - -bool BakedLightmapEditorPlugin::bake_func_step(float p_progress, const String &p_description, void *, bool p_refresh) { - if (!tmp_progress) { - tmp_progress = memnew(EditorProgress("bake_lightmaps", TTR("Bake Lightmaps"), 1000, false)); - ERR_FAIL_COND_V(tmp_progress == nullptr, false); - } - return tmp_progress->step(p_description, p_progress * 1000, p_refresh); -} - -void BakedLightmapEditorPlugin::bake_func_end() { - if (tmp_progress != nullptr) { - memdelete(tmp_progress); - tmp_progress = nullptr; - } -} - -void BakedLightmapEditorPlugin::_bind_methods() { - ClassDB::bind_method("_bake", &BakedLightmapEditorPlugin::_bake); -} - -BakedLightmapEditorPlugin::BakedLightmapEditorPlugin(EditorNode *p_node) { - editor = p_node; - bake = memnew(Button); - bake->set_flat(true); - bake->set_icon(editor->get_gui_base()->get_theme_icon("Bake", "EditorIcons")); - bake->set_text(TTR("Bake Lightmaps")); - bake->hide(); - bake->connect("pressed", Callable(this, "_bake")); - add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, bake); - lightmap = nullptr; - - file_dialog = memnew(EditorFileDialog); - file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); - file_dialog->add_filter("*.lmbake ; LightMap Bake"); - file_dialog->set_title(TTR("Select lightmap bake file:")); - file_dialog->connect("file_selected", callable_mp(this, &BakedLightmapEditorPlugin::_bake_select_file)); - bake->add_child(file_dialog); -} - -BakedLightmapEditorPlugin::~BakedLightmapEditorPlugin() { -} diff --git a/editor/plugins/baked_lightmap_editor_plugin.h b/editor/plugins/baked_lightmap_editor_plugin.h deleted file mode 100644 index d291c377d9..0000000000 --- a/editor/plugins/baked_lightmap_editor_plugin.h +++ /dev/null @@ -1,69 +0,0 @@ -/*************************************************************************/ -/* baked_lightmap_editor_plugin.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef BAKED_LIGHTMAP_EDITOR_PLUGIN_H -#define BAKED_LIGHTMAP_EDITOR_PLUGIN_H - -#include "editor/editor_node.h" -#include "editor/editor_plugin.h" -#include "scene/3d/baked_lightmap.h" -#include "scene/resources/material.h" - -class BakedLightmapEditorPlugin : public EditorPlugin { - GDCLASS(BakedLightmapEditorPlugin, EditorPlugin); - - BakedLightmap *lightmap; - - Button *bake; - EditorNode *editor; - - EditorFileDialog *file_dialog; - static EditorProgress *tmp_progress; - static bool bake_func_step(float p_progress, const String &p_description, void *, bool p_refresh); - static void bake_func_end(); - - void _bake_select_file(const String &p_file); - void _bake(); - -protected: - static void _bind_methods(); - -public: - virtual String get_name() const override { return "BakedLightmap"; } - bool has_main_screen() const override { return false; } - virtual void edit(Object *p_object) override; - virtual bool handles(Object *p_object) const override; - virtual void make_visible(bool p_visible) override; - - BakedLightmapEditorPlugin(EditorNode *p_node); - ~BakedLightmapEditorPlugin(); -}; - -#endif diff --git a/editor/plugins/gi_probe_editor_plugin.cpp b/editor/plugins/gi_probe_editor_plugin.cpp deleted file mode 100644 index f309c5da01..0000000000 --- a/editor/plugins/gi_probe_editor_plugin.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/*************************************************************************/ -/* gi_probe_editor_plugin.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "gi_probe_editor_plugin.h" - -void GIProbeEditorPlugin::_bake() { - if (gi_probe) { - if (gi_probe->get_probe_data().is_null()) { - String path = get_tree()->get_edited_scene_root()->get_filename(); - if (path == String()) { - path = "res://" + gi_probe->get_name() + "_data.res"; - } else { - String ext = path.get_extension(); - path = path.get_basename() + "." + gi_probe->get_name() + "_data.res"; - } - probe_file->set_current_path(path); - probe_file->popup_file_dialog(); - return; - } - gi_probe->bake(); - } -} - -void GIProbeEditorPlugin::edit(Object *p_object) { - GIProbe *s = Object::cast_to(p_object); - if (!s) { - return; - } - - gi_probe = s; -} - -bool GIProbeEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("GIProbe"); -} - -void GIProbeEditorPlugin::_notification(int p_what) { - if (p_what == NOTIFICATION_PROCESS) { - if (!gi_probe) { - return; - } - - const Vector3i size = gi_probe->get_estimated_cell_size(); - String text = vformat(String::utf8("%d × %d × %d"), size.x, size.y, size.z); - int data_size = 4; - if (GLOBAL_GET("rendering/quality/gi_probes/anisotropic")) { - data_size += 4; - } - const double size_mb = size.x * size.y * size.z * data_size / (1024.0 * 1024.0); - text += " - " + vformat(TTR("VRAM Size: %s MB"), String::num(size_mb, 2)); - - if (bake_info->get_text() == text) { - return; - } - - // Color the label depending on the estimated performance level. - Color color; - if (size_mb <= 16.0 + CMP_EPSILON) { - // Fast. - color = bake_info->get_theme_color("success_color", "Editor"); - } else if (size_mb <= 64.0 + CMP_EPSILON) { - // Medium. - color = bake_info->get_theme_color("warning_color", "Editor"); - } else { - // Slow. - color = bake_info->get_theme_color("error_color", "Editor"); - } - bake_info->add_theme_color_override("font_color", color); - - bake_info->set_text(text); - } -} - -void GIProbeEditorPlugin::make_visible(bool p_visible) { - if (p_visible) { - bake_hb->show(); - set_process(true); - } else { - bake_hb->hide(); - set_process(false); - } -} - -EditorProgress *GIProbeEditorPlugin::tmp_progress = nullptr; - -void GIProbeEditorPlugin::bake_func_begin(int p_steps) { - ERR_FAIL_COND(tmp_progress != nullptr); - - tmp_progress = memnew(EditorProgress("bake_gi", TTR("Bake GI Probe"), p_steps)); -} - -void GIProbeEditorPlugin::bake_func_step(int p_step, const String &p_description) { - ERR_FAIL_COND(tmp_progress == nullptr); - tmp_progress->step(p_description, p_step, false); -} - -void GIProbeEditorPlugin::bake_func_end() { - ERR_FAIL_COND(tmp_progress == nullptr); - memdelete(tmp_progress); - tmp_progress = nullptr; -} - -void GIProbeEditorPlugin::_giprobe_save_path_and_bake(const String &p_path) { - probe_file->hide(); - if (gi_probe) { - gi_probe->bake(); - ERR_FAIL_COND(gi_probe->get_probe_data().is_null()); - ResourceSaver::save(p_path, gi_probe->get_probe_data(), ResourceSaver::FLAG_CHANGE_PATH); - } -} - -void GIProbeEditorPlugin::_bind_methods() { -} - -GIProbeEditorPlugin::GIProbeEditorPlugin(EditorNode *p_node) { - editor = p_node; - bake_hb = memnew(HBoxContainer); - bake_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL); - bake_hb->hide(); - bake = memnew(Button); - bake->set_flat(true); - bake->set_icon(editor->get_gui_base()->get_theme_icon("Bake", "EditorIcons")); - bake->set_text(TTR("Bake GI Probe")); - bake->connect("pressed", callable_mp(this, &GIProbeEditorPlugin::_bake)); - bake_hb->add_child(bake); - bake_info = memnew(Label); - bake_info->set_h_size_flags(Control::SIZE_EXPAND_FILL); - bake_info->set_clip_text(true); - bake_hb->add_child(bake_info); - - add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, bake_hb); - gi_probe = nullptr; - probe_file = memnew(EditorFileDialog); - probe_file->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); - probe_file->add_filter("*.res"); - probe_file->connect("file_selected", callable_mp(this, &GIProbeEditorPlugin::_giprobe_save_path_and_bake)); - get_editor_interface()->get_base_control()->add_child(probe_file); - probe_file->set_title(TTR("Select path for GIProbe Data File")); - - GIProbe::bake_begin_function = bake_func_begin; - GIProbe::bake_step_function = bake_func_step; - GIProbe::bake_end_function = bake_func_end; -} - -GIProbeEditorPlugin::~GIProbeEditorPlugin() { -} diff --git a/editor/plugins/gi_probe_editor_plugin.h b/editor/plugins/gi_probe_editor_plugin.h deleted file mode 100644 index fdf0623561..0000000000 --- a/editor/plugins/gi_probe_editor_plugin.h +++ /dev/null @@ -1,74 +0,0 @@ -/*************************************************************************/ -/* gi_probe_editor_plugin.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef GIPROBEEDITORPLUGIN_H -#define GIPROBEEDITORPLUGIN_H - -#include "editor/editor_node.h" -#include "editor/editor_plugin.h" -#include "scene/3d/gi_probe.h" -#include "scene/resources/material.h" - -class GIProbeEditorPlugin : public EditorPlugin { - GDCLASS(GIProbeEditorPlugin, EditorPlugin); - - GIProbe *gi_probe; - - HBoxContainer *bake_hb; - Label *bake_info; - Button *bake; - EditorNode *editor; - - EditorFileDialog *probe_file; - - static EditorProgress *tmp_progress; - static void bake_func_begin(int p_steps); - static void bake_func_step(int p_step, const String &p_description); - static void bake_func_end(); - - void _bake(); - void _giprobe_save_path_and_bake(const String &p_path); - -protected: - static void _bind_methods(); - void _notification(int p_what); - -public: - virtual String get_name() const override { return "GIProbe"; } - bool has_main_screen() const override { return false; } - virtual void edit(Object *p_object) override; - virtual bool handles(Object *p_object) const override; - virtual void make_visible(bool p_visible) override; - - GIProbeEditorPlugin(EditorNode *p_node); - ~GIProbeEditorPlugin(); -}; - -#endif // GIPROBEEDITORPLUGIN_H diff --git a/editor/plugins/lightmap_gi_editor_plugin.cpp b/editor/plugins/lightmap_gi_editor_plugin.cpp new file mode 100644 index 0000000000..484fdabfe1 --- /dev/null +++ b/editor/plugins/lightmap_gi_editor_plugin.cpp @@ -0,0 +1,138 @@ +/*************************************************************************/ +/* lightmap_gi_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "lightmap_gi_editor_plugin.h" + +void LightmapGIEditorPlugin::_bake_select_file(const String &p_file) { + if (lightmap) { + LightmapGI::BakeError err; + if (get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root() == lightmap) { + err = lightmap->bake(lightmap, p_file, bake_func_step); + } else { + err = lightmap->bake(lightmap->get_parent(), p_file, bake_func_step); + } + + bake_func_end(); + + switch (err) { + case LightmapGI::BAKE_ERROR_NO_SAVE_PATH: { + String scene_path = lightmap->get_filename(); + if (scene_path == String()) { + scene_path = lightmap->get_owner()->get_filename(); + } + if (scene_path == String()) { + EditorNode::get_singleton()->show_warning(TTR("Can't determine a save path for lightmap images.\nSave your scene and try again.")); + break; + } + scene_path = scene_path.get_basename() + ".lmbake"; + + file_dialog->set_current_path(scene_path); + file_dialog->popup_file_dialog(); + + } break; + case LightmapGI::BAKE_ERROR_NO_MESHES: + EditorNode::get_singleton()->show_warning(TTR("No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake Light' flag is on.")); + break; + case LightmapGI::BAKE_ERROR_CANT_CREATE_IMAGE: + EditorNode::get_singleton()->show_warning(TTR("Failed creating lightmap images, make sure path is writable.")); + break; + default: { + } + } + } +} + +void LightmapGIEditorPlugin::_bake() { + _bake_select_file(""); +} + +void LightmapGIEditorPlugin::edit(Object *p_object) { + LightmapGI *s = Object::cast_to(p_object); + if (!s) { + return; + } + + lightmap = s; +} + +bool LightmapGIEditorPlugin::handles(Object *p_object) const { + return p_object->is_class("LightmapGI"); +} + +void LightmapGIEditorPlugin::make_visible(bool p_visible) { + if (p_visible) { + bake->show(); + } else { + bake->hide(); + } +} + +EditorProgress *LightmapGIEditorPlugin::tmp_progress = nullptr; + +bool LightmapGIEditorPlugin::bake_func_step(float p_progress, const String &p_description, void *, bool p_refresh) { + if (!tmp_progress) { + tmp_progress = memnew(EditorProgress("bake_lightmaps", TTR("Bake Lightmaps"), 1000, false)); + ERR_FAIL_COND_V(tmp_progress == nullptr, false); + } + return tmp_progress->step(p_description, p_progress * 1000, p_refresh); +} + +void LightmapGIEditorPlugin::bake_func_end() { + if (tmp_progress != nullptr) { + memdelete(tmp_progress); + tmp_progress = nullptr; + } +} + +void LightmapGIEditorPlugin::_bind_methods() { + ClassDB::bind_method("_bake", &LightmapGIEditorPlugin::_bake); +} + +LightmapGIEditorPlugin::LightmapGIEditorPlugin(EditorNode *p_node) { + editor = p_node; + bake = memnew(Button); + bake->set_flat(true); + bake->set_icon(editor->get_gui_base()->get_theme_icon("Bake", "EditorIcons")); + bake->set_text(TTR("Bake Lightmaps")); + bake->hide(); + bake->connect("pressed", Callable(this, "_bake")); + add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, bake); + lightmap = nullptr; + + file_dialog = memnew(EditorFileDialog); + file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); + file_dialog->add_filter("*.lmbake ; LightMap Bake"); + file_dialog->set_title(TTR("Select lightmap bake file:")); + file_dialog->connect("file_selected", callable_mp(this, &LightmapGIEditorPlugin::_bake_select_file)); + bake->add_child(file_dialog); +} + +LightmapGIEditorPlugin::~LightmapGIEditorPlugin() { +} diff --git a/editor/plugins/lightmap_gi_editor_plugin.h b/editor/plugins/lightmap_gi_editor_plugin.h new file mode 100644 index 0000000000..12d080d6be --- /dev/null +++ b/editor/plugins/lightmap_gi_editor_plugin.h @@ -0,0 +1,69 @@ +/*************************************************************************/ +/* lightmap_gi_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef BAKED_LIGHTMAP_EDITOR_PLUGIN_H +#define BAKED_LIGHTMAP_EDITOR_PLUGIN_H + +#include "editor/editor_node.h" +#include "editor/editor_plugin.h" +#include "scene/3d/lightmap_gi.h" +#include "scene/resources/material.h" + +class LightmapGIEditorPlugin : public EditorPlugin { + GDCLASS(LightmapGIEditorPlugin, EditorPlugin); + + LightmapGI *lightmap; + + Button *bake; + EditorNode *editor; + + EditorFileDialog *file_dialog; + static EditorProgress *tmp_progress; + static bool bake_func_step(float p_progress, const String &p_description, void *, bool p_refresh); + static void bake_func_end(); + + void _bake_select_file(const String &p_file); + void _bake(); + +protected: + static void _bind_methods(); + +public: + virtual String get_name() const override { return "LightmapGI"; } + bool has_main_screen() const override { return false; } + virtual void edit(Object *p_object) override; + virtual bool handles(Object *p_object) const override; + virtual void make_visible(bool p_visible) override; + + LightmapGIEditorPlugin(EditorNode *p_node); + ~LightmapGIEditorPlugin(); +}; + +#endif diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index dbda020346..6ab15f763f 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -3060,9 +3060,9 @@ void Node3DEditorViewport::_menu_option(int p_option) { case VIEW_DISPLAY_NORMAL_BUFFER: case VIEW_DISPLAY_DEBUG_SHADOW_ATLAS: case VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS: - case VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO: - case VIEW_DISPLAY_DEBUG_GIPROBE_LIGHTING: - case VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION: + case VIEW_DISPLAY_DEBUG_VOXEL_GI_ALBEDO: + case VIEW_DISPLAY_DEBUG_VOXEL_GI_LIGHTING: + case VIEW_DISPLAY_DEBUG_VOXEL_GI_EMISSION: case VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE: case VIEW_DISPLAY_DEBUG_SSAO: case VIEW_DISPLAY_DEBUG_PSSM_SPLITS: @@ -3086,9 +3086,9 @@ void Node3DEditorViewport::_menu_option(int p_option) { VIEW_DISPLAY_WIREFRAME, VIEW_DISPLAY_DEBUG_SHADOW_ATLAS, VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS, - VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO, - VIEW_DISPLAY_DEBUG_GIPROBE_LIGHTING, - VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION, + VIEW_DISPLAY_DEBUG_VOXEL_GI_ALBEDO, + VIEW_DISPLAY_DEBUG_VOXEL_GI_LIGHTING, + VIEW_DISPLAY_DEBUG_VOXEL_GI_EMISSION, VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE, VIEW_DISPLAY_DEBUG_SSAO, VIEW_DISPLAY_DEBUG_GI_BUFFER, @@ -3114,9 +3114,9 @@ void Node3DEditorViewport::_menu_option(int p_option) { Viewport::DEBUG_DRAW_WIREFRAME, Viewport::DEBUG_DRAW_SHADOW_ATLAS, Viewport::DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS, - Viewport::DEBUG_DRAW_GI_PROBE_ALBEDO, - Viewport::DEBUG_DRAW_GI_PROBE_LIGHTING, - Viewport::DEBUG_DRAW_GI_PROBE_EMISSION, + Viewport::DEBUG_DRAW_VOXEL_GI_ALBEDO, + Viewport::DEBUG_DRAW_VOXEL_GI_LIGHTING, + Viewport::DEBUG_DRAW_VOXEL_GI_EMISSION, Viewport::DEBUG_DRAW_SCENE_LUMINANCE, Viewport::DEBUG_DRAW_SSAO, Viewport::DEBUG_DRAW_GI_BUFFER, @@ -4036,9 +4036,9 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito display_submenu->add_separator(); display_submenu->add_radio_check_item(TTR("Decal Atlas"), VIEW_DISPLAY_DEBUG_DECAL_ATLAS); display_submenu->add_separator(); - display_submenu->add_radio_check_item(TTR("GIProbe Lighting"), VIEW_DISPLAY_DEBUG_GIPROBE_LIGHTING); - display_submenu->add_radio_check_item(TTR("GIProbe Albedo"), VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO); - display_submenu->add_radio_check_item(TTR("GIProbe Emission"), VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION); + display_submenu->add_radio_check_item(TTR("VoxelGI Lighting"), VIEW_DISPLAY_DEBUG_VOXEL_GI_LIGHTING); + display_submenu->add_radio_check_item(TTR("VoxelGI Albedo"), VIEW_DISPLAY_DEBUG_VOXEL_GI_ALBEDO); + display_submenu->add_radio_check_item(TTR("VoxelGI Emission"), VIEW_DISPLAY_DEBUG_VOXEL_GI_EMISSION); display_submenu->add_separator(); display_submenu->add_radio_check_item(TTR("SDFGI Cascades"), VIEW_DISPLAY_DEBUG_SDFGI); display_submenu->add_radio_check_item(TTR("SDFGI Probes"), VIEW_DISPLAY_DEBUG_SDFGI_PROBES); @@ -6496,8 +6496,8 @@ void Node3DEditor::_register_all_gizmos() { add_gizmo_plugin(Ref(memnew(CPUParticles3DGizmoPlugin))); add_gizmo_plugin(Ref(memnew(ReflectionProbeGizmoPlugin))); add_gizmo_plugin(Ref(memnew(DecalGizmoPlugin))); - add_gizmo_plugin(Ref(memnew(GIProbeGizmoPlugin))); - add_gizmo_plugin(Ref(memnew(BakedLightmapGizmoPlugin))); + add_gizmo_plugin(Ref(memnew(VoxelGIGizmoPlugin))); + add_gizmo_plugin(Ref(memnew(LightmapGIGizmoPlugin))); add_gizmo_plugin(Ref(memnew(LightmapProbeGizmoPlugin))); add_gizmo_plugin(Ref(memnew(CollisionObject3DGizmoPlugin))); add_gizmo_plugin(Ref(memnew(CollisionShape3DGizmoPlugin))); diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index 186e97fd15..c68857cd7e 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -206,9 +206,9 @@ class Node3DEditorViewport : public Control { VIEW_DISPLAY_NORMAL_BUFFER, VIEW_DISPLAY_DEBUG_SHADOW_ATLAS, VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS, - VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO, - VIEW_DISPLAY_DEBUG_GIPROBE_LIGHTING, - VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION, + VIEW_DISPLAY_DEBUG_VOXEL_GI_ALBEDO, + VIEW_DISPLAY_DEBUG_VOXEL_GI_LIGHTING, + VIEW_DISPLAY_DEBUG_VOXEL_GI_EMISSION, VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE, VIEW_DISPLAY_DEBUG_SSAO, VIEW_DISPLAY_DEBUG_PSSM_SPLITS, diff --git a/editor/plugins/voxel_gi_editor_plugin.cpp b/editor/plugins/voxel_gi_editor_plugin.cpp new file mode 100644 index 0000000000..d30cc7ad17 --- /dev/null +++ b/editor/plugins/voxel_gi_editor_plugin.cpp @@ -0,0 +1,173 @@ +/*************************************************************************/ +/* voxel_gi_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "voxel_gi_editor_plugin.h" + +void VoxelGIEditorPlugin::_bake() { + if (voxel_gi) { + if (voxel_gi->get_probe_data().is_null()) { + String path = get_tree()->get_edited_scene_root()->get_filename(); + if (path == String()) { + path = "res://" + voxel_gi->get_name() + "_data.res"; + } else { + String ext = path.get_extension(); + path = path.get_basename() + "." + voxel_gi->get_name() + "_data.res"; + } + probe_file->set_current_path(path); + probe_file->popup_file_dialog(); + return; + } + voxel_gi->bake(); + } +} + +void VoxelGIEditorPlugin::edit(Object *p_object) { + VoxelGI *s = Object::cast_to(p_object); + if (!s) { + return; + } + + voxel_gi = s; +} + +bool VoxelGIEditorPlugin::handles(Object *p_object) const { + return p_object->is_class("VoxelGI"); +} + +void VoxelGIEditorPlugin::_notification(int p_what) { + if (p_what == NOTIFICATION_PROCESS) { + if (!voxel_gi) { + return; + } + + const Vector3i size = voxel_gi->get_estimated_cell_size(); + String text = vformat(String::utf8("%d × %d × %d"), size.x, size.y, size.z); + int data_size = 4; + if (GLOBAL_GET("rendering/quality/voxel_gi/anisotropic")) { + data_size += 4; + } + const double size_mb = size.x * size.y * size.z * data_size / (1024.0 * 1024.0); + text += " - " + vformat(TTR("VRAM Size: %s MB"), String::num(size_mb, 2)); + + if (bake_info->get_text() == text) { + return; + } + + // Color the label depending on the estimated performance level. + Color color; + if (size_mb <= 16.0 + CMP_EPSILON) { + // Fast. + color = bake_info->get_theme_color("success_color", "Editor"); + } else if (size_mb <= 64.0 + CMP_EPSILON) { + // Medium. + color = bake_info->get_theme_color("warning_color", "Editor"); + } else { + // Slow. + color = bake_info->get_theme_color("error_color", "Editor"); + } + bake_info->add_theme_color_override("font_color", color); + + bake_info->set_text(text); + } +} + +void VoxelGIEditorPlugin::make_visible(bool p_visible) { + if (p_visible) { + bake_hb->show(); + set_process(true); + } else { + bake_hb->hide(); + set_process(false); + } +} + +EditorProgress *VoxelGIEditorPlugin::tmp_progress = nullptr; + +void VoxelGIEditorPlugin::bake_func_begin(int p_steps) { + ERR_FAIL_COND(tmp_progress != nullptr); + + tmp_progress = memnew(EditorProgress("bake_gi", TTR("Bake GI Probe"), p_steps)); +} + +void VoxelGIEditorPlugin::bake_func_step(int p_step, const String &p_description) { + ERR_FAIL_COND(tmp_progress == nullptr); + tmp_progress->step(p_description, p_step, false); +} + +void VoxelGIEditorPlugin::bake_func_end() { + ERR_FAIL_COND(tmp_progress == nullptr); + memdelete(tmp_progress); + tmp_progress = nullptr; +} + +void VoxelGIEditorPlugin::_voxel_gi_save_path_and_bake(const String &p_path) { + probe_file->hide(); + if (voxel_gi) { + voxel_gi->bake(); + ERR_FAIL_COND(voxel_gi->get_probe_data().is_null()); + ResourceSaver::save(p_path, voxel_gi->get_probe_data(), ResourceSaver::FLAG_CHANGE_PATH); + } +} + +void VoxelGIEditorPlugin::_bind_methods() { +} + +VoxelGIEditorPlugin::VoxelGIEditorPlugin(EditorNode *p_node) { + editor = p_node; + bake_hb = memnew(HBoxContainer); + bake_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL); + bake_hb->hide(); + bake = memnew(Button); + bake->set_flat(true); + bake->set_icon(editor->get_gui_base()->get_theme_icon("Bake", "EditorIcons")); + bake->set_text(TTR("Bake GI Probe")); + bake->connect("pressed", callable_mp(this, &VoxelGIEditorPlugin::_bake)); + bake_hb->add_child(bake); + bake_info = memnew(Label); + bake_info->set_h_size_flags(Control::SIZE_EXPAND_FILL); + bake_info->set_clip_text(true); + bake_hb->add_child(bake_info); + + add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, bake_hb); + voxel_gi = nullptr; + probe_file = memnew(EditorFileDialog); + probe_file->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); + probe_file->add_filter("*.res"); + probe_file->connect("file_selected", callable_mp(this, &VoxelGIEditorPlugin::_voxel_gi_save_path_and_bake)); + get_editor_interface()->get_base_control()->add_child(probe_file); + probe_file->set_title(TTR("Select path for VoxelGI Data File")); + + VoxelGI::bake_begin_function = bake_func_begin; + VoxelGI::bake_step_function = bake_func_step; + VoxelGI::bake_end_function = bake_func_end; +} + +VoxelGIEditorPlugin::~VoxelGIEditorPlugin() { +} diff --git a/editor/plugins/voxel_gi_editor_plugin.h b/editor/plugins/voxel_gi_editor_plugin.h new file mode 100644 index 0000000000..4d3cfe90f6 --- /dev/null +++ b/editor/plugins/voxel_gi_editor_plugin.h @@ -0,0 +1,74 @@ +/*************************************************************************/ +/* voxel_gi_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef VOXEL_GIEDITORPLUGIN_H +#define VOXEL_GIEDITORPLUGIN_H + +#include "editor/editor_node.h" +#include "editor/editor_plugin.h" +#include "scene/3d/voxel_gi.h" +#include "scene/resources/material.h" + +class VoxelGIEditorPlugin : public EditorPlugin { + GDCLASS(VoxelGIEditorPlugin, EditorPlugin); + + VoxelGI *voxel_gi; + + HBoxContainer *bake_hb; + Label *bake_info; + Button *bake; + EditorNode *editor; + + EditorFileDialog *probe_file; + + static EditorProgress *tmp_progress; + static void bake_func_begin(int p_steps); + static void bake_func_step(int p_step, const String &p_description); + static void bake_func_end(); + + void _bake(); + void _voxel_gi_save_path_and_bake(const String &p_path); + +protected: + static void _bind_methods(); + void _notification(int p_what); + +public: + virtual String get_name() const override { return "VoxelGI"; } + bool has_main_screen() const override { return false; } + virtual void edit(Object *p_object) override; + virtual bool handles(Object *p_object) const override; + virtual void make_visible(bool p_visible) override; + + VoxelGIEditorPlugin(EditorNode *p_node); + ~VoxelGIEditorPlugin(); +}; + +#endif // VOXEL_GIEDITORPLUGIN_H diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp deleted file mode 100644 index 6208b1a1dc..0000000000 --- a/scene/3d/baked_lightmap.cpp +++ /dev/null @@ -1,1466 +0,0 @@ -/*************************************************************************/ -/* baked_lightmap.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "baked_lightmap.h" - -#include "core/io/config_file.h" -#include "core/io/resource_saver.h" -#include "core/math/camera_matrix.h" -#include "core/math/delaunay_3d.h" -#include "core/os/dir_access.h" -#include "core/os/file_access.h" -#include "core/os/os.h" -#include "core/templates/sort_array.h" -#include "lightmap_probe.h" - -void BakedLightmapData::add_user(const NodePath &p_path, const Rect2 &p_uv_scale, int p_slice_index, int32_t p_sub_instance) { - User user; - user.path = p_path; - user.uv_scale = p_uv_scale; - user.slice_index = p_slice_index; - user.sub_instance = p_sub_instance; - users.push_back(user); -} - -int BakedLightmapData::get_user_count() const { - return users.size(); -} - -NodePath BakedLightmapData::get_user_path(int p_user) const { - ERR_FAIL_INDEX_V(p_user, users.size(), NodePath()); - return users[p_user].path; -} - -int32_t BakedLightmapData::get_user_sub_instance(int p_user) const { - ERR_FAIL_INDEX_V(p_user, users.size(), -1); - return users[p_user].sub_instance; -} - -Rect2 BakedLightmapData::get_user_lightmap_uv_scale(int p_user) const { - ERR_FAIL_INDEX_V(p_user, users.size(), Rect2()); - return users[p_user].uv_scale; -} - -int BakedLightmapData::get_user_lightmap_slice_index(int p_user) const { - ERR_FAIL_INDEX_V(p_user, users.size(), -1); - return users[p_user].slice_index; -} - -void BakedLightmapData::clear_users() { - users.clear(); -} - -void BakedLightmapData::_set_user_data(const Array &p_data) { - ERR_FAIL_COND(p_data.size() <= 0); - ERR_FAIL_COND((p_data.size() % 4) != 0); - - for (int i = 0; i < p_data.size(); i += 4) { - add_user(p_data[i + 0], p_data[i + 1], p_data[i + 2], p_data[i + 3]); - } -} - -Array BakedLightmapData::_get_user_data() const { - Array ret; - for (int i = 0; i < users.size(); i++) { - ret.push_back(users[i].path); - ret.push_back(users[i].uv_scale); - ret.push_back(users[i].slice_index); - ret.push_back(users[i].sub_instance); - } - return ret; -} - -RID BakedLightmapData::get_rid() const { - return lightmap; -} - -void BakedLightmapData::clear() { - users.clear(); -} - -void BakedLightmapData::set_light_texture(const Ref &p_light_texture) { - light_texture = p_light_texture; - RS::get_singleton()->lightmap_set_textures(lightmap, light_texture.is_valid() ? light_texture->get_rid() : RID(), uses_spherical_harmonics); -} - -Ref BakedLightmapData::get_light_texture() const { - return light_texture; -} - -void BakedLightmapData::set_uses_spherical_harmonics(bool p_enable) { - uses_spherical_harmonics = p_enable; - RS::get_singleton()->lightmap_set_textures(lightmap, light_texture.is_valid() ? light_texture->get_rid() : RID(), uses_spherical_harmonics); -} - -bool BakedLightmapData::is_using_spherical_harmonics() const { - return uses_spherical_harmonics; -} - -void BakedLightmapData::set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) { - if (p_points.size()) { - int pc = p_points.size(); - ERR_FAIL_COND(pc * 9 != p_point_sh.size()); - ERR_FAIL_COND((p_tetrahedra.size() % 4) != 0); - ERR_FAIL_COND((p_bsp_tree.size() % 6) != 0); - RS::get_singleton()->lightmap_set_probe_capture_data(lightmap, p_points, p_point_sh, p_tetrahedra, p_bsp_tree); - RS::get_singleton()->lightmap_set_probe_bounds(lightmap, p_bounds); - RS::get_singleton()->lightmap_set_probe_interior(lightmap, p_interior); - } else { - RS::get_singleton()->lightmap_set_probe_capture_data(lightmap, PackedVector3Array(), PackedColorArray(), PackedInt32Array(), PackedInt32Array()); - RS::get_singleton()->lightmap_set_probe_bounds(lightmap, AABB()); - RS::get_singleton()->lightmap_set_probe_interior(lightmap, false); - } - interior = p_interior; - bounds = p_bounds; -} - -PackedVector3Array BakedLightmapData::get_capture_points() const { - return RS::get_singleton()->lightmap_get_probe_capture_points(lightmap); -} - -PackedColorArray BakedLightmapData::get_capture_sh() const { - return RS::get_singleton()->lightmap_get_probe_capture_sh(lightmap); -} - -PackedInt32Array BakedLightmapData::get_capture_tetrahedra() const { - return RS::get_singleton()->lightmap_get_probe_capture_tetrahedra(lightmap); -} - -PackedInt32Array BakedLightmapData::get_capture_bsp_tree() const { - return RS::get_singleton()->lightmap_get_probe_capture_bsp_tree(lightmap); -} - -AABB BakedLightmapData::get_capture_bounds() const { - return bounds; -} - -bool BakedLightmapData::is_interior() const { - return interior; -} - -void BakedLightmapData::_set_probe_data(const Dictionary &p_data) { - ERR_FAIL_COND(!p_data.has("bounds")); - ERR_FAIL_COND(!p_data.has("points")); - ERR_FAIL_COND(!p_data.has("tetrahedra")); - ERR_FAIL_COND(!p_data.has("bsp")); - ERR_FAIL_COND(!p_data.has("sh")); - ERR_FAIL_COND(!p_data.has("interior")); - set_capture_data(p_data["bounds"], p_data["interior"], p_data["points"], p_data["sh"], p_data["tetrahedra"], p_data["bsp"]); -} - -Dictionary BakedLightmapData::_get_probe_data() const { - Dictionary d; - d["bounds"] = get_capture_bounds(); - d["points"] = get_capture_points(); - d["tetrahedra"] = get_capture_tetrahedra(); - d["bsp"] = get_capture_bsp_tree(); - d["sh"] = get_capture_sh(); - d["interior"] = is_interior(); - return d; -} - -void BakedLightmapData::_bind_methods() { - ClassDB::bind_method(D_METHOD("_set_user_data", "data"), &BakedLightmapData::_set_user_data); - ClassDB::bind_method(D_METHOD("_get_user_data"), &BakedLightmapData::_get_user_data); - - ClassDB::bind_method(D_METHOD("set_light_texture", "light_texture"), &BakedLightmapData::set_light_texture); - ClassDB::bind_method(D_METHOD("get_light_texture"), &BakedLightmapData::get_light_texture); - - ClassDB::bind_method(D_METHOD("set_uses_spherical_harmonics", "uses_spherical_harmonics"), &BakedLightmapData::set_uses_spherical_harmonics); - ClassDB::bind_method(D_METHOD("is_using_spherical_harmonics"), &BakedLightmapData::is_using_spherical_harmonics); - - ClassDB::bind_method(D_METHOD("add_user", "path", "uv_scale", "slice_index", "sub_instance"), &BakedLightmapData::add_user); - ClassDB::bind_method(D_METHOD("get_user_count"), &BakedLightmapData::get_user_count); - ClassDB::bind_method(D_METHOD("get_user_path", "user_idx"), &BakedLightmapData::get_user_path); - ClassDB::bind_method(D_METHOD("clear_users"), &BakedLightmapData::clear_users); - - ClassDB::bind_method(D_METHOD("_set_probe_data", "data"), &BakedLightmapData::_set_probe_data); - ClassDB::bind_method(D_METHOD("_get_probe_data"), &BakedLightmapData::_get_probe_data); - - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_texture", PROPERTY_HINT_RESOURCE_TYPE, "TextureLayered"), "set_light_texture", "get_light_texture"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uses_spherical_harmonics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_uses_spherical_harmonics", "is_using_spherical_harmonics"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "user_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_user_data", "_get_user_data"); - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "probe_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_probe_data", "_get_probe_data"); -} - -BakedLightmapData::BakedLightmapData() { - lightmap = RS::get_singleton()->lightmap_create(); -} - -BakedLightmapData::~BakedLightmapData() { - RS::get_singleton()->free(lightmap); -} - -/////////////////////////// - -void BakedLightmap::_find_meshes_and_lights(Node *p_at_node, Vector &meshes, Vector &lights, Vector &probes) { - MeshInstance3D *mi = Object::cast_to(p_at_node); - if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_BAKED && mi->is_visible_in_tree()) { - Ref mesh = mi->get_mesh(); - if (mesh.is_valid()) { - bool all_have_uv2_and_normal = true; - bool surfaces_found = false; - for (int i = 0; i < mesh->get_surface_count(); i++) { - if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { - continue; - } - if (!(mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_TEX_UV2)) { - all_have_uv2_and_normal = false; - break; - } - if (!(mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_NORMAL)) { - all_have_uv2_and_normal = false; - break; - } - surfaces_found = true; - } - - if (surfaces_found && all_have_uv2_and_normal) { - //READY TO BAKE! size hint could be computed if not found, actually.. - - MeshesFound mf; - mf.xform = get_global_transform().affine_inverse() * mi->get_global_transform(); - mf.node_path = get_path_to(mi); - mf.subindex = -1; - mf.mesh = mesh; - - static const int lightmap_scale[GeometryInstance3D::LIGHTMAP_SCALE_MAX] = { 1, 2, 4, 8 }; - mf.lightmap_scale = lightmap_scale[mi->get_lightmap_scale()]; - - Ref all_override = mi->get_material_override(); - for (int i = 0; i < mesh->get_surface_count(); i++) { - if (all_override.is_valid()) { - mf.overrides.push_back(all_override); - } else { - mf.overrides.push_back(mi->get_surface_override_material(i)); - } - } - - meshes.push_back(mf); - } - } - } - - Node3D *s = Object::cast_to(p_at_node); - - if (!mi && s) { - Array bmeshes = p_at_node->call("get_bake_bmeshes"); - if (bmeshes.size() && (bmeshes.size() & 1) == 0) { - Transform3D xf = get_global_transform().affine_inverse() * s->get_global_transform(); - for (int i = 0; i < bmeshes.size(); i += 2) { - Ref mesh = bmeshes[i]; - if (!mesh.is_valid()) { - continue; - } - - MeshesFound mf; - - Transform3D mesh_xf = bmeshes[i + 1]; - mf.xform = xf * mesh_xf; - mf.node_path = get_path_to(s); - mf.subindex = i / 2; - mf.lightmap_scale = 1; - mf.mesh = mesh; - - meshes.push_back(mf); - } - } - } - - Light3D *light = Object::cast_to(p_at_node); - - if (light && light->get_bake_mode() != Light3D::BAKE_DISABLED) { - LightsFound lf; - lf.xform = get_global_transform().affine_inverse() * light->get_global_transform(); - lf.light = light; - lights.push_back(lf); - } - - LightmapProbe *probe = Object::cast_to(p_at_node); - - if (probe) { - Transform3D xf = get_global_transform().affine_inverse() * probe->get_global_transform(); - probes.push_back(xf.origin); - } - - for (int i = 0; i < p_at_node->get_child_count(); i++) { - Node *child = p_at_node->get_child(i); - if (!child->get_owner()) { - continue; //maybe a helper - } - - _find_meshes_and_lights(child, meshes, lights, probes); - } -} - -int BakedLightmap::_bsp_get_simplex_side(const Vector &p_points, const LocalVector &p_simplices, const Plane &p_plane, uint32_t p_simplex) const { - int over = 0; - int under = 0; - int coplanar = 0; - const BSPSimplex &s = p_simplices[p_simplex]; - for (int i = 0; i < 4; i++) { - const Vector3 v = p_points[s.vertices[i]]; - if (p_plane.has_point(v)) { //coplanar - coplanar++; - } else if (p_plane.is_point_over(v)) { - over++; - } else { - under++; - } - } - - ERR_FAIL_COND_V(under == 0 && over == 0, -2); //should never happen, we discarded flat simplices before, but in any case drop it from the bsp tree and throw an error - if (under == 0) { - return 1; // all over - } else if (over == 0) { - return -1; // all under - } else { - return 0; // crossing - } -} - -//#define DEBUG_BSP - -int32_t BakedLightmap::_compute_bsp_tree(const Vector &p_points, const LocalVector &p_planes, LocalVector &planes_tested, const LocalVector &p_simplices, const LocalVector &p_simplex_indices, LocalVector &bsp_nodes) { - //if we reach here, it means there is more than one simplex - int32_t node_index = (int32_t)bsp_nodes.size(); - bsp_nodes.push_back(BSPNode()); - - //test with all the simplex planes - Plane best_plane; - float best_plane_score = -1.0; - - for (uint32_t i = 0; i < p_simplex_indices.size(); i++) { - const BSPSimplex &s = p_simplices[p_simplex_indices[i]]; - for (int j = 0; j < 4; j++) { - uint32_t plane_index = s.planes[j]; - if (planes_tested[plane_index] == node_index) { - continue; //tested this plane already - } - - planes_tested[plane_index] = node_index; - - static const int face_order[4][3] = { - { 0, 1, 2 }, - { 0, 2, 3 }, - { 0, 1, 3 }, - { 1, 2, 3 } - }; - - // despite getting rid of plane duplicates, we should still use here the actual plane to avoid numerical error - // from thinking this same simplex is intersecting rather than on a side - Vector3 v0 = p_points[s.vertices[face_order[j][0]]]; - Vector3 v1 = p_points[s.vertices[face_order[j][1]]]; - Vector3 v2 = p_points[s.vertices[face_order[j][2]]]; - - Plane plane(v0, v1, v2); - - //test with all the simplices - int over_count = 0; - int under_count = 0; - - for (uint32_t k = 0; k < p_simplex_indices.size(); k++) { - int side = _bsp_get_simplex_side(p_points, p_simplices, plane, p_simplex_indices[k]); - if (side == -2) { - continue; //this simplex is invalid, skip for now - } else if (side < 0) { - under_count++; - } else if (side > 0) { - over_count++; - } - } - - if (under_count == 0 && over_count == 0) { - continue; //most likely precision issue with a flat simplex, do not try this plane - } - - if (under_count > over_count) { //make sure under is always less than over, so we can compute the same ratio - SWAP(under_count, over_count); - } - - float score = 0; //by default, score is 0 (worst) - if (over_count > 0) { - //give score mainly based on ratio (under / over), this means that this plane is splitting simplices a lot, but its balanced - score = float(under_count) / over_count; - } - - //adjusting priority over least splits, probably not a great idea - //score *= Math::sqrt(float(over_count + under_count) / p_simplex_indices.size()); //also multiply score - - if (score > best_plane_score) { - best_plane = plane; - best_plane_score = score; - } - } - } - - LocalVector indices_over; - LocalVector indices_under; - - //split again, but add to list - for (uint32_t i = 0; i < p_simplex_indices.size(); i++) { - uint32_t index = p_simplex_indices[i]; - int side = _bsp_get_simplex_side(p_points, p_simplices, best_plane, index); - - if (side == -2) { - continue; //simplex sits on the plane, does not make sense to use it - } - if (side <= 0) { - indices_under.push_back(index); - } - - if (side >= 0) { - indices_over.push_back(index); - } - } - -#ifdef DEBUG_BSP - print_line("node " + itos(node_index) + " found plane: " + best_plane + " score:" + rtos(best_plane_score) + " - over " + itos(indices_over.size()) + " under " + itos(indices_under.size()) + " intersecting " + itos(intersecting)); -#endif - - if (best_plane_score < 0.0 || indices_over.size() == p_simplex_indices.size() || indices_under.size() == p_simplex_indices.size()) { - ERR_FAIL_COND_V(p_simplex_indices.size() <= 1, 0); //should not happen, this is a bug - - // Failed to separate the tetrahedrons using planes - // this means Delaunay broke at some point. - // Luckily, because we are using tetrahedrons, we can resort to - // less precise but still working ways to generate the separating plane - // this will most likely look bad when interpolating, but at least it will not crash. - // and the arctifact will most likely also be very small, so too difficult to notice. - - //find the longest axis - - WARN_PRINT("Inconsistency found in triangulation while building BSP, probe interpolation quality may degrade a bit."); - - LocalVector centers; - AABB bounds_all; - for (uint32_t i = 0; i < p_simplex_indices.size(); i++) { - AABB bounds; - for (uint32_t j = 0; j < 4; j++) { - Vector3 p = p_points[p_simplices[p_simplex_indices[i]].vertices[j]]; - if (j == 0) { - bounds.position = p; - } else { - bounds.expand_to(p); - } - } - if (i == 0) { - centers.push_back(bounds.position + bounds.size * 0.5); - } else { - bounds_all.merge_with(bounds); - } - } - Vector3::Axis longest_axis = Vector3::Axis(bounds_all.get_longest_axis_index()); - - //find the simplex that will go under - uint32_t min_d_idx = 0xFFFFFFFF; - float min_d_dist = 1e20; - - for (uint32_t i = 0; i < centers.size(); i++) { - if (centers[i][longest_axis] < min_d_dist) { - min_d_idx = i; - min_d_dist = centers[i][longest_axis]; - } - } - //rebuild best_plane and over/under arrays - best_plane = Plane(); - best_plane.normal[longest_axis] = 1.0; - best_plane.d = min_d_dist; - - indices_under.clear(); - indices_under.push_back(min_d_idx); - - indices_over.clear(); - - for (uint32_t i = 0; i < p_simplex_indices.size(); i++) { - if (i == min_d_idx) { - continue; - } - indices_over.push_back(p_simplex_indices[i]); - } - } - - BSPNode node; - node.plane = best_plane; - - if (indices_under.size() == 0) { - //nothing to do here - node.under = BSPNode::EMPTY_LEAF; - } else if (indices_under.size() == 1) { - node.under = -(indices_under[0] + 1); - } else { - node.under = _compute_bsp_tree(p_points, p_planes, planes_tested, p_simplices, indices_under, bsp_nodes); - } - - if (indices_over.size() == 0) { - //nothing to do here - node.over = BSPNode::EMPTY_LEAF; - } else if (indices_over.size() == 1) { - node.over = -(indices_over[0] + 1); - } else { - node.over = _compute_bsp_tree(p_points, p_planes, planes_tested, p_simplices, indices_over, bsp_nodes); - } - - bsp_nodes[node_index] = node; - - return node_index; -} - -bool BakedLightmap::_lightmap_bake_step_function(float p_completion, const String &p_text, void *ud, bool p_refresh) { - BakeStepUD *bsud = (BakeStepUD *)ud; - bool ret = false; - if (bsud->func) { - ret = bsud->func(bsud->from_percent + p_completion * (bsud->to_percent - bsud->from_percent), p_text, bsud->ud, p_refresh); - } - return ret; -} - -void BakedLightmap::_plot_triangle_into_octree(GenProbesOctree *p_cell, float p_cell_size, const Vector3 *p_triangle) { - for (int i = 0; i < 8; i++) { - Vector3i pos = p_cell->offset; - uint32_t half_size = p_cell->size / 2; - if (i & 1) { - pos.x += half_size; - } - if (i & 2) { - pos.y += half_size; - } - if (i & 4) { - pos.z += half_size; - } - - AABB subcell; - subcell.position = Vector3(pos) * p_cell_size; - subcell.size = Vector3(half_size, half_size, half_size) * p_cell_size; - - if (!Geometry3D::triangle_box_overlap(subcell.position + subcell.size * 0.5, subcell.size * 0.5, p_triangle)) { - continue; - } - - if (p_cell->children[i] == nullptr) { - GenProbesOctree *child = memnew(GenProbesOctree); - child->offset = pos; - child->size = half_size; - p_cell->children[i] = child; - } - - if (half_size > 1) { - //still levels missing - _plot_triangle_into_octree(p_cell->children[i], p_cell_size, p_triangle); - } - } -} - -void BakedLightmap::_gen_new_positions_from_octree(const GenProbesOctree *p_cell, float p_cell_size, const Vector &probe_positions, LocalVector &new_probe_positions, HashMap &positions_used, const AABB &p_bounds) { - for (int i = 0; i < 8; i++) { - Vector3i pos = p_cell->offset; - if (i & 1) { - pos.x += p_cell->size; - } - if (i & 2) { - pos.y += p_cell->size; - } - if (i & 4) { - pos.z += p_cell->size; - } - - if (p_cell->size == 1 && !positions_used.has(pos)) { - //new position to insert! - Vector3 real_pos = p_bounds.position + Vector3(pos) * p_cell_size; - //see if a user submitted probe is too close - int ppcount = probe_positions.size(); - const Vector3 *pp = probe_positions.ptr(); - bool exists = false; - for (int j = 0; j < ppcount; j++) { - if (pp[j].distance_to(real_pos) < CMP_EPSILON) { - exists = true; - break; - } - } - - if (!exists) { - new_probe_positions.push_back(real_pos); - } - - positions_used[pos] = true; - } - - if (p_cell->children[i] != nullptr) { - _gen_new_positions_from_octree(p_cell->children[i], p_cell_size, probe_positions, new_probe_positions, positions_used, p_bounds); - } - } -} - -BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, String p_image_data_path, Lightmapper::BakeStepFunc p_bake_step, void *p_bake_userdata) { - if (p_image_data_path == "") { - if (get_light_data().is_null()) { - return BAKE_ERROR_NO_SAVE_PATH; - } - - p_image_data_path = get_light_data()->get_path(); - if (!p_image_data_path.is_resource_file()) { - return BAKE_ERROR_NO_SAVE_PATH; - } - } - - Ref lightmapper = Lightmapper::create(); - ERR_FAIL_COND_V(lightmapper.is_null(), BAKE_ERROR_NO_LIGHTMAPPER); - - BakeStepUD bsud; - bsud.func = p_bake_step; - bsud.ud = p_bake_userdata; - bsud.from_percent = 0.2; - bsud.to_percent = 0.8; - - if (p_bake_step) { - p_bake_step(0.0, TTR("Finding meshes, lights and probes"), p_bake_userdata, true); - } - /* STEP 1, FIND MESHES, LIGHTS AND PROBES */ - Vector mesh_data; - Vector lights_found; - Vector probes_found; - AABB bounds; - { - Vector meshes_found; - _find_meshes_and_lights(p_from_node ? p_from_node : get_parent(), meshes_found, lights_found, probes_found); - - if (meshes_found.size() == 0) { - return BAKE_ERROR_NO_MESHES; - } - // create mesh data for insert - - //get the base material textures, help compute atlas size and bounds - for (int m_i = 0; m_i < meshes_found.size(); m_i++) { - if (p_bake_step) { - float p = (float)(m_i) / meshes_found.size(); - p_bake_step(p * 0.1, vformat(TTR("Preparing geometry %d/%d"), m_i, meshes_found.size()), p_bake_userdata, false); - } - - MeshesFound &mf = meshes_found.write[m_i]; - - Size2i lightmap_size = mf.mesh->get_lightmap_size_hint() * mf.lightmap_scale; - Vector overrides; - overrides.resize(mf.overrides.size()); - for (int i = 0; i < mf.overrides.size(); i++) { - if (mf.overrides[i].is_valid()) { - overrides.write[i] = mf.overrides[i]->get_rid(); - } - } - TypedArray images = RS::get_singleton()->bake_render_uv2(mf.mesh->get_rid(), overrides, lightmap_size); - - ERR_FAIL_COND_V(images.is_empty(), BAKE_ERROR_CANT_CREATE_IMAGE); - - Ref albedo = images[RS::BAKE_CHANNEL_ALBEDO_ALPHA]; - Ref orm = images[RS::BAKE_CHANNEL_ORM]; - - //multiply albedo by metal - - Lightmapper::MeshData md; - - { - Dictionary d; - d["path"] = mf.node_path; - if (mf.subindex >= 0) { - d["subindex"] = mf.subindex; - } - md.userdata = d; - } - - { - if (albedo->get_format() != Image::FORMAT_RGBA8) { - albedo->convert(Image::FORMAT_RGBA8); - } - if (orm->get_format() != Image::FORMAT_RGBA8) { - orm->convert(Image::FORMAT_RGBA8); - } - Vector albedo_alpha = albedo->get_data(); - Vector orm_data = orm->get_data(); - - Vector albedom; - uint32_t len = albedo_alpha.size(); - albedom.resize(len); - const uint8_t *r_aa = albedo_alpha.ptr(); - const uint8_t *r_orm = orm_data.ptr(); - uint8_t *w_albedo = albedom.ptrw(); - - for (uint32_t i = 0; i < len; i += 4) { - w_albedo[i + 0] = uint8_t(CLAMP(float(r_aa[i + 0]) * (1.0 - float(r_orm[i + 2] / 255.0)), 0, 255)); - w_albedo[i + 1] = uint8_t(CLAMP(float(r_aa[i + 1]) * (1.0 - float(r_orm[i + 2] / 255.0)), 0, 255)); - w_albedo[i + 2] = uint8_t(CLAMP(float(r_aa[i + 2]) * (1.0 - float(r_orm[i + 2] / 255.0)), 0, 255)); - w_albedo[i + 3] = 255; - } - - md.albedo_on_uv2.instance(); - md.albedo_on_uv2->create(lightmap_size.width, lightmap_size.height, false, Image::FORMAT_RGBA8, albedom); - } - - md.emission_on_uv2 = images[RS::BAKE_CHANNEL_EMISSION]; - if (md.emission_on_uv2->get_format() != Image::FORMAT_RGBAH) { - md.emission_on_uv2->convert(Image::FORMAT_RGBAH); - } - - //get geometry - - Basis normal_xform = mf.xform.basis.inverse().transposed(); - - for (int i = 0; i < mf.mesh->get_surface_count(); i++) { - if (mf.mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { - continue; - } - Array a = mf.mesh->surface_get_arrays(i); - - Vector vertices = a[Mesh::ARRAY_VERTEX]; - const Vector3 *vr = vertices.ptr(); - Vector uv = a[Mesh::ARRAY_TEX_UV2]; - const Vector2 *uvr = nullptr; - Vector normals = a[Mesh::ARRAY_NORMAL]; - const Vector3 *nr = nullptr; - Vector index = a[Mesh::ARRAY_INDEX]; - - ERR_CONTINUE(uv.size() == 0); - ERR_CONTINUE(normals.size() == 0); - - uvr = uv.ptr(); - nr = normals.ptr(); - - int facecount; - const int *ir = nullptr; - - if (index.size()) { - facecount = index.size() / 3; - ir = index.ptr(); - } else { - facecount = vertices.size() / 3; - } - - for (int j = 0; j < facecount; j++) { - uint32_t vidx[3]; - - if (ir) { - for (int k = 0; k < 3; k++) { - vidx[k] = ir[j * 3 + k]; - } - } else { - for (int k = 0; k < 3; k++) { - vidx[k] = j * 3 + k; - } - } - - for (int k = 0; k < 3; k++) { - Vector3 v = mf.xform.xform(vr[vidx[k]]); - if (bounds == AABB()) { - bounds.position = v; - } else { - bounds.expand_to(v); - } - md.points.push_back(v); - - md.uv2.push_back(uvr[vidx[k]]); - md.normal.push_back(normal_xform.xform(nr[vidx[k]]).normalized()); - } - } - } - - mesh_data.push_back(md); - } - } - - /* STEP 2, CREATE PROBES */ - - if (p_bake_step) { - p_bake_step(0.3, TTR("Creating probes"), p_bake_userdata, true); - } - - //bounds need to include the user probes - for (int i = 0; i < probes_found.size(); i++) { - bounds.expand_to(probes_found[i]); - } - - bounds.grow_by(bounds.size.length() * 0.001); - - if (gen_probes == GENERATE_PROBES_DISABLED) { - // generate 8 probes on bound endpoints - for (int i = 0; i < 8; i++) { - probes_found.push_back(bounds.get_endpoint(i)); - } - } else { - // detect probes from geometry - static const int subdiv_values[6] = { 0, 4, 8, 16, 32 }; - int subdiv = subdiv_values[gen_probes]; - - float subdiv_cell_size; - Vector3i bound_limit; - { - int longest_axis = bounds.get_longest_axis_index(); - subdiv_cell_size = bounds.size[longest_axis] / subdiv; - int axis_n1 = (longest_axis + 1) % 3; - int axis_n2 = (longest_axis + 2) % 3; - - bound_limit[longest_axis] = subdiv; - bound_limit[axis_n1] = int(Math::ceil(bounds.size[axis_n1] / subdiv_cell_size)); - bound_limit[axis_n2] = int(Math::ceil(bounds.size[axis_n2] / subdiv_cell_size)); - //compensate bounds - bounds.size[axis_n1] = bound_limit[axis_n1] * subdiv_cell_size; - bounds.size[axis_n2] = bound_limit[axis_n2] * subdiv_cell_size; - } - - GenProbesOctree octree; - octree.size = subdiv; - - for (int i = 0; i < mesh_data.size(); i++) { - if (p_bake_step) { - float p = (float)(i) / mesh_data.size(); - p_bake_step(0.3 + p * 0.1, vformat(TTR("Creating probes from mesh %d/%d"), i, mesh_data.size()), p_bake_userdata, false); - } - - for (int j = 0; j < mesh_data[i].points.size(); j += 3) { - Vector3 points[3] = { mesh_data[i].points[j + 0] - bounds.position, mesh_data[i].points[j + 1] - bounds.position, mesh_data[i].points[j + 2] - bounds.position }; - _plot_triangle_into_octree(&octree, subdiv_cell_size, points); - } - } - - LocalVector new_probe_positions; - HashMap positions_used; - for (uint32_t i = 0; i < 8; i++) { //insert bounding endpoints - Vector3i pos; - if (i & 1) { - pos.x += bound_limit.x; - } - if (i & 2) { - pos.y += bound_limit.y; - } - if (i & 4) { - pos.z += bound_limit.z; - } - - positions_used[pos] = true; - Vector3 real_pos = bounds.position + Vector3(pos) * subdiv_cell_size; //use same formula for numerical stability - new_probe_positions.push_back(real_pos); - } - //skip first level, since probes are always added at bounds endpoints anyway (code above this) - for (int i = 0; i < 8; i++) { - if (octree.children[i]) { - _gen_new_positions_from_octree(octree.children[i], subdiv_cell_size, probes_found, new_probe_positions, positions_used, bounds); - } - } - - for (uint32_t i = 0; i < new_probe_positions.size(); i++) { - probes_found.push_back(new_probe_positions[i]); - } - } - - // Add everything to lightmapper - if (p_bake_step) { - p_bake_step(0.4, TTR("Preparing Lightmapper"), p_bake_userdata, true); - } - - { - for (int i = 0; i < mesh_data.size(); i++) { - lightmapper->add_mesh(mesh_data[i]); - } - for (int i = 0; i < lights_found.size(); i++) { - Light3D *light = lights_found[i].light; - Transform3D xf = lights_found[i].xform; - - if (Object::cast_to(light)) { - DirectionalLight3D *l = Object::cast_to(light); - lightmapper->add_directional_light(light->get_bake_mode() == Light3D::BAKE_STATIC, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_SIZE)); - } else if (Object::cast_to(light)) { - OmniLight3D *l = Object::cast_to(light); - lightmapper->add_omni_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SIZE)); - } else if (Object::cast_to(light)) { - SpotLight3D *l = Object::cast_to(light); - lightmapper->add_spot_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SPOT_ANGLE), l->get_param(Light3D::PARAM_SPOT_ATTENUATION), l->get_param(Light3D::PARAM_SIZE)); - } - } - for (int i = 0; i < probes_found.size(); i++) { - lightmapper->add_probe(probes_found[i]); - } - } - - Ref environment_image; - Basis environment_transform; - - // Add everything to lightmapper - if (environment_mode != ENVIRONMENT_MODE_DISABLED) { - if (p_bake_step) { - p_bake_step(4.1, TTR("Preparing Environment"), p_bake_userdata, true); - } - - environment_transform = get_global_transform().basis; - - switch (environment_mode) { - case ENVIRONMENT_MODE_DISABLED: { - //nothing - } break; - case ENVIRONMENT_MODE_SCENE: { - Ref world = get_world_3d(); - if (world.is_valid()) { - Ref env = world->get_environment(); - if (env.is_null()) { - env = world->get_fallback_environment(); - } - - if (env.is_valid()) { - environment_image = RS::get_singleton()->environment_bake_panorama(env->get_rid(), true, Size2i(128, 64)); - } - } - } break; - case ENVIRONMENT_MODE_CUSTOM_SKY: { - if (environment_custom_sky.is_valid()) { - environment_image = RS::get_singleton()->sky_bake_panorama(environment_custom_sky->get_rid(), environment_custom_energy, true, Size2i(128, 64)); - } - - } break; - case ENVIRONMENT_MODE_CUSTOM_COLOR: { - environment_image.instance(); - environment_image->create(128, 64, false, Image::FORMAT_RGBAF); - Color c = environment_custom_color; - c.r *= environment_custom_energy; - c.g *= environment_custom_energy; - c.b *= environment_custom_energy; - for (int i = 0; i < 128; i++) { - for (int j = 0; j < 64; j++) { - environment_image->set_pixel(i, j, c); - } - } - - } break; - } - } - - Lightmapper::BakeError bake_err = lightmapper->bake(Lightmapper::BakeQuality(bake_quality), use_denoiser, bounces, bias, max_texture_size, directional, Lightmapper::GenerateProbes(gen_probes), environment_image, environment_transform, _lightmap_bake_step_function, &bsud); - - if (bake_err == Lightmapper::BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES) { - return BAKE_ERROR_MESHES_INVALID; - } - - /* POSTBAKE: Save Textures */ - - Ref texture; - { - Vector> images; - for (int i = 0; i < lightmapper->get_bake_texture_count(); i++) { - images.push_back(lightmapper->get_bake_texture(i)); - } - //we assume they are all the same, so let's create a large one for saving - Ref large_image; - large_image.instance(); - - large_image->create(images[0]->get_width(), images[0]->get_height() * images.size(), false, images[0]->get_format()); - - for (int i = 0; i < lightmapper->get_bake_texture_count(); i++) { - large_image->blit_rect(images[i], Rect2(0, 0, images[i]->get_width(), images[i]->get_height()), Point2(0, images[i]->get_height() * i)); - } - - String base_path = p_image_data_path.get_basename() + ".exr"; - - Ref config; - - config.instance(); - if (FileAccess::exists(base_path + ".import")) { - config->load(base_path + ".import"); - } - - config->set_value("remap", "importer", "2d_array_texture"); - config->set_value("remap", "type", "StreamTexture2DArray"); - if (!config->has_section_key("params", "compress/mode")) { - config->set_value("params", "compress/mode", 2); //user may want another compression, so leave it be - } - config->set_value("params", "compress/channel_pack", 1); - config->set_value("params", "mipmaps/generate", false); - config->set_value("params", "slices/horizontal", 1); - config->set_value("params", "slices/vertical", images.size()); - - config->save(base_path + ".import"); - - Error err = large_image->save_exr(base_path, false); - ERR_FAIL_COND_V(err, BAKE_ERROR_CANT_CREATE_IMAGE); - ResourceLoader::import(base_path); - Ref t = ResourceLoader::load(base_path); //if already loaded, it will be updated on refocus? - ERR_FAIL_COND_V(t.is_null(), BAKE_ERROR_CANT_CREATE_IMAGE); - texture = t; - } - - /* POSTBAKE: Save Light Data */ - - Ref data; - if (get_light_data().is_valid()) { - data = get_light_data(); - set_light_data(Ref()); //clear - data->clear(); - } else { - data.instance(); - } - - data->set_light_texture(texture); - data->set_uses_spherical_harmonics(directional); - - for (int i = 0; i < lightmapper->get_bake_mesh_count(); i++) { - Dictionary d = lightmapper->get_bake_mesh_userdata(i); - NodePath np = d["path"]; - int32_t subindex = -1; - if (d.has("subindex")) { - subindex = d["subindex"]; - } - - Rect2 uv_scale = lightmapper->get_bake_mesh_uv_scale(i); - int slice_index = lightmapper->get_bake_mesh_texture_slice(i); - data->add_user(np, uv_scale, slice_index, subindex); - } - - { - // create tetrahedrons - Vector points; - Vector sh; - points.resize(lightmapper->get_bake_probe_count()); - sh.resize(lightmapper->get_bake_probe_count() * 9); - for (int i = 0; i < lightmapper->get_bake_probe_count(); i++) { - points.write[i] = lightmapper->get_bake_probe_point(i); - Vector colors = lightmapper->get_bake_probe_sh(i); - ERR_CONTINUE(colors.size() != 9); - for (int j = 0; j < 9; j++) { - sh.write[i * 9 + j] = colors[j]; - } - } - - //Obtain solved simplices - - if (p_bake_step) { - p_bake_step(0.8, TTR("Generating Probe Volumes"), p_bake_userdata, true); - } - Vector solved_simplices = Delaunay3D::tetrahedralize(points); - - LocalVector bsp_simplices; - LocalVector bsp_planes; - LocalVector bsp_simplex_indices; - PackedInt32Array tetrahedrons; - - for (int i = 0; i < solved_simplices.size(); i++) { - //Prepare a special representation of the simplex, which uses a BSP Tree - BSPSimplex bsp_simplex; - for (int j = 0; j < 4; j++) { - bsp_simplex.vertices[j] = solved_simplices[i].points[j]; - } - for (int j = 0; j < 4; j++) { - static const int face_order[4][3] = { - { 0, 1, 2 }, - { 0, 2, 3 }, - { 0, 1, 3 }, - { 1, 2, 3 } - }; - Vector3 a = points[solved_simplices[i].points[face_order[j][0]]]; - Vector3 b = points[solved_simplices[i].points[face_order[j][1]]]; - Vector3 c = points[solved_simplices[i].points[face_order[j][2]]]; - - //store planes in an array, but ensure they are reused, to speed up processing - - Plane p(a, b, c); - int plane_index = -1; - for (uint32_t k = 0; k < bsp_planes.size(); k++) { - if (bsp_planes[k].is_equal_approx_any_side(p)) { - plane_index = k; - break; - } - } - - if (plane_index == -1) { - plane_index = bsp_planes.size(); - bsp_planes.push_back(p); - } - - bsp_simplex.planes[j] = plane_index; - - //also fill simplex array - tetrahedrons.push_back(solved_simplices[i].points[j]); - } - - bsp_simplex_indices.push_back(bsp_simplices.size()); - bsp_simplices.push_back(bsp_simplex); - } - -//#define DEBUG_SIMPLICES_AS_OBJ_FILE -#ifdef DEBUG_SIMPLICES_AS_OBJ_FILE - { - FileAccessRef f = FileAccess::open("res://bsp.obj", FileAccess::WRITE); - for (uint32_t i = 0; i < bsp_simplices.size(); i++) { - f->store_line("o Simplex" + itos(i)); - for (int j = 0; j < 4; j++) { - f->store_line(vformat("v %f %f %f", points[bsp_simplices[i].vertices[j]].x, points[bsp_simplices[i].vertices[j]].y, points[bsp_simplices[i].vertices[j]].z)); - } - static const int face_order[4][3] = { - { 1, 2, 3 }, - { 1, 3, 4 }, - { 1, 2, 4 }, - { 2, 3, 4 } - }; - - for (int j = 0; j < 4; j++) { - f->store_line(vformat("f %d %d %d", 4 * i + face_order[j][0], 4 * i + face_order[j][1], 4 * i + face_order[j][2])); - } - } - f->close(); - } -#endif - - LocalVector bsp_nodes; - LocalVector planes_tested; - planes_tested.resize(bsp_planes.size()); - for (uint32_t i = 0; i < planes_tested.size(); i++) { - planes_tested[i] = 0x7FFFFFFF; - } - - if (p_bake_step) { - p_bake_step(0.9, TTR("Generating Probe Acceleration Structures"), p_bake_userdata, true); - } - - _compute_bsp_tree(points, bsp_planes, planes_tested, bsp_simplices, bsp_simplex_indices, bsp_nodes); - - PackedInt32Array bsp_array; - bsp_array.resize(bsp_nodes.size() * 6); // six 32 bits values used for each BSP node - { - float *fptr = (float *)bsp_array.ptrw(); - int32_t *iptr = (int32_t *)bsp_array.ptrw(); - for (uint32_t i = 0; i < bsp_nodes.size(); i++) { - fptr[i * 6 + 0] = bsp_nodes[i].plane.normal.x; - fptr[i * 6 + 1] = bsp_nodes[i].plane.normal.y; - fptr[i * 6 + 2] = bsp_nodes[i].plane.normal.z; - fptr[i * 6 + 3] = bsp_nodes[i].plane.d; - iptr[i * 6 + 4] = bsp_nodes[i].over; - iptr[i * 6 + 5] = bsp_nodes[i].under; - } -//#define DEBUG_BSP_TREE -#ifdef DEBUG_BSP_TREE - FileAccessRef f = FileAccess::open("res://bsp.txt", FileAccess::WRITE); - for (uint32_t i = 0; i < bsp_nodes.size(); i++) { - f->store_line(itos(i) + " - plane: " + bsp_nodes[i].plane + " over: " + itos(bsp_nodes[i].over) + " under: " + itos(bsp_nodes[i].under)); - } -#endif - } - - /* Obtain the colors from the images, they will be re-created as cubemaps on the server, depending on the driver */ - - data->set_capture_data(bounds, interior, points, sh, tetrahedrons, bsp_array); - /* Compute a BSP tree of the simplices, so it's easy to find the exact one */ - } - - Error err = ResourceSaver::save(p_image_data_path, data); - data->set_path(p_image_data_path); - - if (err != OK) { - return BAKE_ERROR_CANT_CREATE_IMAGE; - } - - set_light_data(data); - - return BAKE_ERROR_OK; -} - -void BakedLightmap::_notification(int p_what) { - if (p_what == NOTIFICATION_POST_ENTER_TREE) { - if (light_data.is_valid()) { - _assign_lightmaps(); - } - } - - if (p_what == NOTIFICATION_EXIT_TREE) { - if (light_data.is_valid()) { - _clear_lightmaps(); - } - } -} - -void BakedLightmap::_assign_lightmaps() { - ERR_FAIL_COND(!light_data.is_valid()); - - for (int i = 0; i < light_data->get_user_count(); i++) { - Node *node = get_node(light_data->get_user_path(i)); - int instance_idx = light_data->get_user_sub_instance(i); - if (instance_idx >= 0) { - RID instance = node->call("get_bake_mesh_instance", instance_idx); - if (instance.is_valid()) { - RS::get_singleton()->instance_geometry_set_lightmap(instance, get_instance(), light_data->get_user_lightmap_uv_scale(i), light_data->get_user_lightmap_slice_index(i)); - } - } else { - VisualInstance3D *vi = Object::cast_to(node); - ERR_CONTINUE(!vi); - RS::get_singleton()->instance_geometry_set_lightmap(vi->get_instance(), get_instance(), light_data->get_user_lightmap_uv_scale(i), light_data->get_user_lightmap_slice_index(i)); - } - } -} - -void BakedLightmap::_clear_lightmaps() { - ERR_FAIL_COND(!light_data.is_valid()); - for (int i = 0; i < light_data->get_user_count(); i++) { - Node *node = get_node(light_data->get_user_path(i)); - int instance_idx = light_data->get_user_sub_instance(i); - if (instance_idx >= 0) { - RID instance = node->call("get_bake_mesh_instance", instance_idx); - if (instance.is_valid()) { - RS::get_singleton()->instance_geometry_set_lightmap(instance, RID(), Rect2(), 0); - } - } else { - VisualInstance3D *vi = Object::cast_to(node); - ERR_CONTINUE(!vi); - RS::get_singleton()->instance_geometry_set_lightmap(vi->get_instance(), RID(), Rect2(), 0); - } - } -} - -void BakedLightmap::set_light_data(const Ref &p_data) { - if (light_data.is_valid()) { - if (is_inside_tree()) { - _clear_lightmaps(); - } - set_base(RID()); - } - light_data = p_data; - - if (light_data.is_valid()) { - set_base(light_data->get_rid()); - if (is_inside_tree()) { - _assign_lightmaps(); - } - } - - update_gizmo(); -} - -Ref BakedLightmap::get_light_data() const { - return light_data; -} - -void BakedLightmap::set_bake_quality(BakeQuality p_quality) { - bake_quality = p_quality; -} - -BakedLightmap::BakeQuality BakedLightmap::get_bake_quality() const { - return bake_quality; -} - -AABB BakedLightmap::get_aabb() const { - return AABB(); -} - -Vector BakedLightmap::get_faces(uint32_t p_usage_flags) const { - return Vector(); -} - -void BakedLightmap::set_use_denoiser(bool p_enable) { - use_denoiser = p_enable; -} - -bool BakedLightmap::is_using_denoiser() const { - return use_denoiser; -} - -void BakedLightmap::set_directional(bool p_enable) { - directional = p_enable; -} - -bool BakedLightmap::is_directional() const { - return directional; -} - -void BakedLightmap::set_interior(bool p_enable) { - interior = p_enable; -} - -bool BakedLightmap::is_interior() const { - return interior; -} - -void BakedLightmap::set_environment_mode(EnvironmentMode p_mode) { - environment_mode = p_mode; - notify_property_list_changed(); -} - -BakedLightmap::EnvironmentMode BakedLightmap::get_environment_mode() const { - return environment_mode; -} - -void BakedLightmap::set_environment_custom_sky(const Ref &p_sky) { - environment_custom_sky = p_sky; -} - -Ref BakedLightmap::get_environment_custom_sky() const { - return environment_custom_sky; -} - -void BakedLightmap::set_environment_custom_color(const Color &p_color) { - environment_custom_color = p_color; -} - -Color BakedLightmap::get_environment_custom_color() const { - return environment_custom_color; -} - -void BakedLightmap::set_environment_custom_energy(float p_energy) { - environment_custom_energy = p_energy; -} - -float BakedLightmap::get_environment_custom_energy() const { - return environment_custom_energy; -} - -void BakedLightmap::set_bounces(int p_bounces) { - ERR_FAIL_COND(p_bounces < 0 || p_bounces > 16); - bounces = p_bounces; -} - -int BakedLightmap::get_bounces() const { - return bounces; -} - -void BakedLightmap::set_bias(float p_bias) { - ERR_FAIL_COND(p_bias < 0.00001); - bias = p_bias; -} - -float BakedLightmap::get_bias() const { - return bias; -} - -void BakedLightmap::set_max_texture_size(int p_size) { - ERR_FAIL_COND(p_size < 2048); - max_texture_size = p_size; -} - -int BakedLightmap::get_max_texture_size() const { - return max_texture_size; -} - -void BakedLightmap::set_generate_probes(GenerateProbes p_generate_probes) { - gen_probes = p_generate_probes; -} - -BakedLightmap::GenerateProbes BakedLightmap::get_generate_probes() const { - return gen_probes; -} - -void BakedLightmap::_validate_property(PropertyInfo &property) const { - if (property.name == "environment_custom_sky" && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) { - property.usage = 0; - } - if (property.name == "environment_custom_color" && environment_mode != ENVIRONMENT_MODE_CUSTOM_COLOR) { - property.usage = 0; - } - if (property.name == "environment_custom_energy" && environment_mode != ENVIRONMENT_MODE_CUSTOM_COLOR && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) { - property.usage = 0; - } -} - -void BakedLightmap::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_light_data", "data"), &BakedLightmap::set_light_data); - ClassDB::bind_method(D_METHOD("get_light_data"), &BakedLightmap::get_light_data); - - ClassDB::bind_method(D_METHOD("set_bake_quality", "bake_quality"), &BakedLightmap::set_bake_quality); - ClassDB::bind_method(D_METHOD("get_bake_quality"), &BakedLightmap::get_bake_quality); - - ClassDB::bind_method(D_METHOD("set_bounces", "bounces"), &BakedLightmap::set_bounces); - ClassDB::bind_method(D_METHOD("get_bounces"), &BakedLightmap::get_bounces); - - ClassDB::bind_method(D_METHOD("set_generate_probes", "subdivision"), &BakedLightmap::set_generate_probes); - ClassDB::bind_method(D_METHOD("get_generate_probes"), &BakedLightmap::get_generate_probes); - - ClassDB::bind_method(D_METHOD("set_bias", "bias"), &BakedLightmap::set_bias); - ClassDB::bind_method(D_METHOD("get_bias"), &BakedLightmap::get_bias); - - ClassDB::bind_method(D_METHOD("set_environment_mode", "mode"), &BakedLightmap::set_environment_mode); - ClassDB::bind_method(D_METHOD("get_environment_mode"), &BakedLightmap::get_environment_mode); - - ClassDB::bind_method(D_METHOD("set_environment_custom_sky", "sky"), &BakedLightmap::set_environment_custom_sky); - ClassDB::bind_method(D_METHOD("get_environment_custom_sky"), &BakedLightmap::get_environment_custom_sky); - - ClassDB::bind_method(D_METHOD("set_environment_custom_color", "color"), &BakedLightmap::set_environment_custom_color); - ClassDB::bind_method(D_METHOD("get_environment_custom_color"), &BakedLightmap::get_environment_custom_color); - - ClassDB::bind_method(D_METHOD("set_environment_custom_energy", "energy"), &BakedLightmap::set_environment_custom_energy); - ClassDB::bind_method(D_METHOD("get_environment_custom_energy"), &BakedLightmap::get_environment_custom_energy); - - ClassDB::bind_method(D_METHOD("set_max_texture_size", "max_texture_size"), &BakedLightmap::set_max_texture_size); - ClassDB::bind_method(D_METHOD("get_max_texture_size"), &BakedLightmap::get_max_texture_size); - - ClassDB::bind_method(D_METHOD("set_use_denoiser", "use_denoiser"), &BakedLightmap::set_use_denoiser); - ClassDB::bind_method(D_METHOD("is_using_denoiser"), &BakedLightmap::is_using_denoiser); - - ClassDB::bind_method(D_METHOD("set_interior", "enable"), &BakedLightmap::set_interior); - ClassDB::bind_method(D_METHOD("is_interior"), &BakedLightmap::is_interior); - - ClassDB::bind_method(D_METHOD("set_directional", "directional"), &BakedLightmap::set_directional); - ClassDB::bind_method(D_METHOD("is_directional"), &BakedLightmap::is_directional); - - // ClassDB::bind_method(D_METHOD("bake", "from_node"), &BakedLightmap::bake, DEFVAL(Variant())); - - ADD_GROUP("Tweaks", ""); - ADD_PROPERTY(PropertyInfo(Variant::INT, "quality", PROPERTY_HINT_ENUM, "Low,Medium,High,Ultra"), "set_bake_quality", "get_bake_quality"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "bounces", PROPERTY_HINT_RANGE, "0,16,1"), "set_bounces", "get_bounces"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "directional"), "set_directional", "is_directional"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_denoiser"), "set_use_denoiser", "is_using_denoiser"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0.00001,0.1,0.00001,or_greater"), "set_bias", "get_bias"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "max_texture_size"), "set_max_texture_size", "get_max_texture_size"); - ADD_GROUP("Environment", "environment_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "environment_mode", PROPERTY_HINT_ENUM, "Disabled,Scene,Custom Sky,Custom Color"), "set_environment_mode", "get_environment_mode"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment_custom_sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_environment_custom_sky", "get_environment_custom_sky"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "environment_custom_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_environment_custom_color", "get_environment_custom_color"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "environment_custom_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_environment_custom_energy", "get_environment_custom_energy"); - ADD_GROUP("Gen Probes", "generate_probes_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "generate_probes_subdiv", PROPERTY_HINT_ENUM, "Disabled,4,8,16,32"), "set_generate_probes", "get_generate_probes"); - ADD_GROUP("Data", ""); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_data", PROPERTY_HINT_RESOURCE_TYPE, "BakedLightmapData"), "set_light_data", "get_light_data"); - - BIND_ENUM_CONSTANT(BAKE_QUALITY_LOW); - BIND_ENUM_CONSTANT(BAKE_QUALITY_MEDIUM); - BIND_ENUM_CONSTANT(BAKE_QUALITY_HIGH); - BIND_ENUM_CONSTANT(BAKE_QUALITY_ULTRA); - - BIND_ENUM_CONSTANT(GENERATE_PROBES_DISABLED); - BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_4); - BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_8); - BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_16); - BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_32); - - BIND_ENUM_CONSTANT(BAKE_ERROR_OK); - BIND_ENUM_CONSTANT(BAKE_ERROR_NO_LIGHTMAPPER); - BIND_ENUM_CONSTANT(BAKE_ERROR_NO_SAVE_PATH); - BIND_ENUM_CONSTANT(BAKE_ERROR_NO_MESHES); - BIND_ENUM_CONSTANT(BAKE_ERROR_MESHES_INVALID); - BIND_ENUM_CONSTANT(BAKE_ERROR_CANT_CREATE_IMAGE); - BIND_ENUM_CONSTANT(BAKE_ERROR_USER_ABORTED); - - BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_DISABLED); - BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_SCENE); - BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_CUSTOM_SKY); - BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_CUSTOM_COLOR); -} - -BakedLightmap::BakedLightmap() { -} diff --git a/scene/3d/baked_lightmap.h b/scene/3d/baked_lightmap.h deleted file mode 100644 index 690896f2e9..0000000000 --- a/scene/3d/baked_lightmap.h +++ /dev/null @@ -1,284 +0,0 @@ -/*************************************************************************/ -/* baked_lightmap.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef BAKED_LIGHTMAP_H -#define BAKED_LIGHTMAP_H - -#include "core/templates/local_vector.h" -#include "scene/3d/light_3d.h" -#include "scene/3d/lightmapper.h" -#include "scene/3d/mesh_instance_3d.h" -#include "scene/3d/multimesh_instance_3d.h" -#include "scene/3d/visual_instance_3d.h" -#include "scene/resources/sky.h" - -class BakedLightmapData : public Resource { - GDCLASS(BakedLightmapData, Resource); - RES_BASE_EXTENSION("lmbake") - - Ref light_texture; - - bool uses_spherical_harmonics = false; - bool interior = false; - - RID lightmap; - AABB bounds; - - struct User { - NodePath path; - int32_t sub_instance = 0; - Rect2 uv_scale; - int slice_index = 0; - }; - - Vector users; - - void _set_user_data(const Array &p_data); - Array _get_user_data() const; - void _set_probe_data(const Dictionary &p_data); - Dictionary _get_probe_data() const; - -protected: - static void _bind_methods(); - -public: - void add_user(const NodePath &p_path, const Rect2 &p_uv_scale, int p_slice_index, int32_t p_sub_instance = -1); - int get_user_count() const; - NodePath get_user_path(int p_user) const; - int32_t get_user_sub_instance(int p_user) const; - Rect2 get_user_lightmap_uv_scale(int p_user) const; - int get_user_lightmap_slice_index(int p_user) const; - void clear_users(); - - void set_light_texture(const Ref &p_light_texture); - Ref get_light_texture() const; - - void set_uses_spherical_harmonics(bool p_enable); - bool is_using_spherical_harmonics() const; - - bool is_interior() const; - - void set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree); - PackedVector3Array get_capture_points() const; - PackedColorArray get_capture_sh() const; - PackedInt32Array get_capture_tetrahedra() const; - PackedInt32Array get_capture_bsp_tree() const; - AABB get_capture_bounds() const; - - void clear(); - - virtual RID get_rid() const override; - BakedLightmapData(); - ~BakedLightmapData(); -}; - -class BakedLightmap : public VisualInstance3D { - GDCLASS(BakedLightmap, VisualInstance3D); - -public: - enum BakeQuality { - BAKE_QUALITY_LOW, - BAKE_QUALITY_MEDIUM, - BAKE_QUALITY_HIGH, - BAKE_QUALITY_ULTRA, - }; - - enum GenerateProbes { - GENERATE_PROBES_DISABLED, - GENERATE_PROBES_SUBDIV_4, - GENERATE_PROBES_SUBDIV_8, - GENERATE_PROBES_SUBDIV_16, - GENERATE_PROBES_SUBDIV_32, - }; - - enum BakeError { - BAKE_ERROR_OK, - BAKE_ERROR_NO_LIGHTMAPPER, - BAKE_ERROR_NO_SAVE_PATH, - BAKE_ERROR_NO_MESHES, - BAKE_ERROR_MESHES_INVALID, - BAKE_ERROR_CANT_CREATE_IMAGE, - BAKE_ERROR_USER_ABORTED, - }; - - enum EnvironmentMode { - ENVIRONMENT_MODE_DISABLED, - ENVIRONMENT_MODE_SCENE, - ENVIRONMENT_MODE_CUSTOM_SKY, - ENVIRONMENT_MODE_CUSTOM_COLOR, - }; - -private: - BakeQuality bake_quality = BAKE_QUALITY_MEDIUM; - bool use_denoiser = true; - int bounces = 1; - float bias = 0.0005; - int max_texture_size = 16384; - bool interior = false; - EnvironmentMode environment_mode = ENVIRONMENT_MODE_DISABLED; - Ref environment_custom_sky; - Color environment_custom_color = Color(0.2, 0.7, 1.0); - float environment_custom_energy = 1.0; - bool directional = false; - GenerateProbes gen_probes = GENERATE_PROBES_DISABLED; - - Ref light_data; - - struct LightsFound { - Transform3D xform; - Light3D *light = nullptr; - }; - - struct MeshesFound { - Transform3D xform; - NodePath node_path; - int32_t subindex = 0; - Ref mesh; - int32_t lightmap_scale = 0; - Vector> overrides; - }; - - void _find_meshes_and_lights(Node *p_at_node, Vector &meshes, Vector &lights, Vector &probes); - - void _assign_lightmaps(); - void _clear_lightmaps(); - - struct BakeTimeData { - String text; - int pass = 0; - uint64_t last_step = 0; - }; - - struct BSPSimplex { - int vertices[4] = {}; - int planes[4] = {}; - }; - - struct BSPNode { - static const int32_t EMPTY_LEAF = INT32_MIN; - Plane plane; - int32_t over = EMPTY_LEAF; - int32_t under = EMPTY_LEAF; - }; - - int _bsp_get_simplex_side(const Vector &p_points, const LocalVector &p_simplices, const Plane &p_plane, uint32_t p_simplex) const; - int32_t _compute_bsp_tree(const Vector &p_points, const LocalVector &p_planes, LocalVector &planes_tested, const LocalVector &p_simplices, const LocalVector &p_simplex_indices, LocalVector &bsp_nodes); - - struct BakeStepUD { - Lightmapper::BakeStepFunc func; - void *ud = nullptr; - float from_percent = 0.0; - float to_percent = 0.0; - }; - - static bool _lightmap_bake_step_function(float p_completion, const String &p_text, void *ud, bool p_refresh); - - struct GenProbesOctree { - Vector3i offset; - uint32_t size = 0; - GenProbesOctree *children[8] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; - ~GenProbesOctree() { - for (int i = 0; i < 8; i++) { - if (children[i] != nullptr) { - memdelete(children[i]); - } - } - } - }; - - struct Vector3iHash { - _FORCE_INLINE_ static uint32_t hash(const Vector3i &p_vtx) { - uint32_t h = hash_djb2_one_32(p_vtx.x); - h = hash_djb2_one_32(p_vtx.y, h); - return hash_djb2_one_32(p_vtx.z, h); - } - }; - - void _plot_triangle_into_octree(GenProbesOctree *p_cell, float p_cell_size, const Vector3 *p_triangle); - void _gen_new_positions_from_octree(const GenProbesOctree *p_cell, float p_cell_size, const Vector &probe_positions, LocalVector &new_probe_positions, HashMap &positions_used, const AABB &p_bounds); - -protected: - void _validate_property(PropertyInfo &property) const override; - static void _bind_methods(); - void _notification(int p_what); - -public: - void set_light_data(const Ref &p_data); - Ref get_light_data() const; - - void set_bake_quality(BakeQuality p_quality); - BakeQuality get_bake_quality() const; - - void set_use_denoiser(bool p_enable); - bool is_using_denoiser() const; - - void set_directional(bool p_enable); - bool is_directional() const; - - void set_interior(bool p_interior); - bool is_interior() const; - - void set_environment_mode(EnvironmentMode p_mode); - EnvironmentMode get_environment_mode() const; - - void set_environment_custom_sky(const Ref &p_sky); - Ref get_environment_custom_sky() const; - - void set_environment_custom_color(const Color &p_color); - Color get_environment_custom_color() const; - - void set_environment_custom_energy(float p_energy); - float get_environment_custom_energy() const; - - void set_bounces(int p_bounces); - int get_bounces() const; - - void set_bias(float p_bias); - float get_bias() const; - - void set_max_texture_size(int p_size); - int get_max_texture_size() const; - - void set_generate_probes(GenerateProbes p_generate_probes); - GenerateProbes get_generate_probes() const; - - AABB get_aabb() const override; - Vector get_faces(uint32_t p_usage_flags) const override; - - BakeError bake(Node *p_from_node, String p_image_data_path = "", Lightmapper::BakeStepFunc p_bake_step = nullptr, void *p_bake_userdata = nullptr); - BakedLightmap(); -}; - -VARIANT_ENUM_CAST(BakedLightmap::BakeQuality); -VARIANT_ENUM_CAST(BakedLightmap::GenerateProbes); -VARIANT_ENUM_CAST(BakedLightmap::BakeError); -VARIANT_ENUM_CAST(BakedLightmap::EnvironmentMode); - -#endif // BAKED_LIGHTMAP_H diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp deleted file mode 100644 index c31997ecaf..0000000000 --- a/scene/3d/gi_probe.cpp +++ /dev/null @@ -1,549 +0,0 @@ -/*************************************************************************/ -/* gi_probe.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "gi_probe.h" - -#include "core/os/os.h" - -#include "mesh_instance_3d.h" -#include "voxelizer.h" - -void GIProbeData::_set_data(const Dictionary &p_data) { - ERR_FAIL_COND(!p_data.has("bounds")); - ERR_FAIL_COND(!p_data.has("octree_size")); - ERR_FAIL_COND(!p_data.has("octree_cells")); - ERR_FAIL_COND(!p_data.has("octree_data")); - ERR_FAIL_COND(!p_data.has("octree_df") && !p_data.has("octree_df_png")); - ERR_FAIL_COND(!p_data.has("level_counts")); - ERR_FAIL_COND(!p_data.has("to_cell_xform")); - - AABB bounds = p_data["bounds"]; - Vector3 octree_size = p_data["octree_size"]; - Vector octree_cells = p_data["octree_cells"]; - Vector octree_data = p_data["octree_data"]; - - Vector octree_df; - if (p_data.has("octree_df")) { - octree_df = p_data["octree_df"]; - } else if (p_data.has("octree_df_png")) { - Vector octree_df_png = p_data["octree_df_png"]; - Ref img; - img.instance(); - Error err = img->load_png_from_buffer(octree_df_png); - ERR_FAIL_COND(err != OK); - ERR_FAIL_COND(img->get_format() != Image::FORMAT_L8); - octree_df = img->get_data(); - } - Vector octree_levels = p_data["level_counts"]; - Transform3D to_cell_xform = p_data["to_cell_xform"]; - - allocate(to_cell_xform, bounds, octree_size, octree_cells, octree_data, octree_df, octree_levels); -} - -Dictionary GIProbeData::_get_data() const { - Dictionary d; - d["bounds"] = get_bounds(); - Vector3i otsize = get_octree_size(); - d["octree_size"] = Vector3(otsize); - d["octree_cells"] = get_octree_cells(); - d["octree_data"] = get_data_cells(); - if (otsize != Vector3i()) { - Ref img; - img.instance(); - img->create(otsize.x * otsize.y, otsize.z, false, Image::FORMAT_L8, get_distance_field()); - Vector df_png = img->save_png_to_buffer(); - ERR_FAIL_COND_V(df_png.size() == 0, Dictionary()); - d["octree_df_png"] = df_png; - } else { - d["octree_df"] = Vector(); - } - - d["level_counts"] = get_level_counts(); - d["to_cell_xform"] = get_to_cell_xform(); - return d; -} - -void GIProbeData::allocate(const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3 &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts) { - RS::get_singleton()->gi_probe_allocate_data(probe, p_to_cell_xform, p_aabb, p_octree_size, p_octree_cells, p_data_cells, p_distance_field, p_level_counts); - bounds = p_aabb; - to_cell_xform = p_to_cell_xform; - octree_size = p_octree_size; -} - -AABB GIProbeData::get_bounds() const { - return bounds; -} - -Vector3 GIProbeData::get_octree_size() const { - return octree_size; -} - -Vector GIProbeData::get_octree_cells() const { - return RS::get_singleton()->gi_probe_get_octree_cells(probe); -} - -Vector GIProbeData::get_data_cells() const { - return RS::get_singleton()->gi_probe_get_data_cells(probe); -} - -Vector GIProbeData::get_distance_field() const { - return RS::get_singleton()->gi_probe_get_distance_field(probe); -} - -Vector GIProbeData::get_level_counts() const { - return RS::get_singleton()->gi_probe_get_level_counts(probe); -} - -Transform3D GIProbeData::get_to_cell_xform() const { - return to_cell_xform; -} - -void GIProbeData::set_dynamic_range(float p_range) { - RS::get_singleton()->gi_probe_set_dynamic_range(probe, p_range); - dynamic_range = p_range; -} - -float GIProbeData::get_dynamic_range() const { - return dynamic_range; -} - -void GIProbeData::set_propagation(float p_propagation) { - RS::get_singleton()->gi_probe_set_propagation(probe, p_propagation); - propagation = p_propagation; -} - -float GIProbeData::get_propagation() const { - return propagation; -} - -void GIProbeData::set_anisotropy_strength(float p_anisotropy_strength) { - RS::get_singleton()->gi_probe_set_anisotropy_strength(probe, p_anisotropy_strength); - anisotropy_strength = p_anisotropy_strength; -} - -float GIProbeData::get_anisotropy_strength() const { - return anisotropy_strength; -} - -void GIProbeData::set_energy(float p_energy) { - RS::get_singleton()->gi_probe_set_energy(probe, p_energy); - energy = p_energy; -} - -float GIProbeData::get_energy() const { - return energy; -} - -void GIProbeData::set_ao(float p_ao) { - RS::get_singleton()->gi_probe_set_ao(probe, p_ao); - ao = p_ao; -} - -float GIProbeData::get_ao() const { - return ao; -} - -void GIProbeData::set_ao_size(float p_ao_size) { - RS::get_singleton()->gi_probe_set_ao_size(probe, p_ao_size); - ao_size = p_ao_size; -} - -float GIProbeData::get_ao_size() const { - return ao_size; -} - -void GIProbeData::set_bias(float p_bias) { - RS::get_singleton()->gi_probe_set_bias(probe, p_bias); - bias = p_bias; -} - -float GIProbeData::get_bias() const { - return bias; -} - -void GIProbeData::set_normal_bias(float p_normal_bias) { - RS::get_singleton()->gi_probe_set_normal_bias(probe, p_normal_bias); - normal_bias = p_normal_bias; -} - -float GIProbeData::get_normal_bias() const { - return normal_bias; -} - -void GIProbeData::set_interior(bool p_enable) { - RS::get_singleton()->gi_probe_set_interior(probe, p_enable); - interior = p_enable; -} - -bool GIProbeData::is_interior() const { - return interior; -} - -void GIProbeData::set_use_two_bounces(bool p_enable) { - RS::get_singleton()->gi_probe_set_use_two_bounces(probe, p_enable); - use_two_bounces = p_enable; -} - -bool GIProbeData::is_using_two_bounces() const { - return use_two_bounces; -} - -RID GIProbeData::get_rid() const { - return probe; -} - -void GIProbeData::_validate_property(PropertyInfo &property) const { - if (property.name == "anisotropy_strength") { - bool anisotropy_enabled = ProjectSettings::get_singleton()->get("rendering/global_illumination/gi_probes/anisotropic"); - if (!anisotropy_enabled) { - property.usage = PROPERTY_USAGE_NOEDITOR; - } - } -} - -void GIProbeData::_bind_methods() { - ClassDB::bind_method(D_METHOD("allocate", "to_cell_xform", "aabb", "octree_size", "octree_cells", "data_cells", "distance_field", "level_counts"), &GIProbeData::allocate); - - ClassDB::bind_method(D_METHOD("get_bounds"), &GIProbeData::get_bounds); - ClassDB::bind_method(D_METHOD("get_octree_size"), &GIProbeData::get_octree_size); - ClassDB::bind_method(D_METHOD("get_to_cell_xform"), &GIProbeData::get_to_cell_xform); - ClassDB::bind_method(D_METHOD("get_octree_cells"), &GIProbeData::get_octree_cells); - ClassDB::bind_method(D_METHOD("get_data_cells"), &GIProbeData::get_data_cells); - ClassDB::bind_method(D_METHOD("get_level_counts"), &GIProbeData::get_level_counts); - - ClassDB::bind_method(D_METHOD("set_dynamic_range", "dynamic_range"), &GIProbeData::set_dynamic_range); - ClassDB::bind_method(D_METHOD("get_dynamic_range"), &GIProbeData::get_dynamic_range); - - ClassDB::bind_method(D_METHOD("set_energy", "energy"), &GIProbeData::set_energy); - ClassDB::bind_method(D_METHOD("get_energy"), &GIProbeData::get_energy); - - ClassDB::bind_method(D_METHOD("set_bias", "bias"), &GIProbeData::set_bias); - ClassDB::bind_method(D_METHOD("get_bias"), &GIProbeData::get_bias); - - ClassDB::bind_method(D_METHOD("set_normal_bias", "bias"), &GIProbeData::set_normal_bias); - ClassDB::bind_method(D_METHOD("get_normal_bias"), &GIProbeData::get_normal_bias); - - ClassDB::bind_method(D_METHOD("set_propagation", "propagation"), &GIProbeData::set_propagation); - ClassDB::bind_method(D_METHOD("get_propagation"), &GIProbeData::get_propagation); - - ClassDB::bind_method(D_METHOD("set_anisotropy_strength", "strength"), &GIProbeData::set_anisotropy_strength); - ClassDB::bind_method(D_METHOD("get_anisotropy_strength"), &GIProbeData::get_anisotropy_strength); - - ClassDB::bind_method(D_METHOD("set_ao", "ao"), &GIProbeData::set_ao); - ClassDB::bind_method(D_METHOD("get_ao"), &GIProbeData::get_ao); - - ClassDB::bind_method(D_METHOD("set_ao_size", "strength"), &GIProbeData::set_ao_size); - ClassDB::bind_method(D_METHOD("get_ao_size"), &GIProbeData::get_ao_size); - - ClassDB::bind_method(D_METHOD("set_interior", "interior"), &GIProbeData::set_interior); - ClassDB::bind_method(D_METHOD("is_interior"), &GIProbeData::is_interior); - - ClassDB::bind_method(D_METHOD("set_use_two_bounces", "enable"), &GIProbeData::set_use_two_bounces); - ClassDB::bind_method(D_METHOD("is_using_two_bounces"), &GIProbeData::is_using_two_bounces); - - ClassDB::bind_method(D_METHOD("_set_data", "data"), &GIProbeData::_set_data); - ClassDB::bind_method(D_METHOD("_get_data"), &GIProbeData::_get_data); - - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); - - ADD_PROPERTY(PropertyInfo(Variant::INT, "dynamic_range", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_dynamic_range", "get_dynamic_range"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_energy", "get_energy"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_bias", "get_bias"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "normal_bias", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_normal_bias", "get_normal_bias"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "propagation", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_propagation", "get_propagation"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "anisotropy_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_anisotropy_strength", "get_anisotropy_strength"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ao", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ao", "get_ao"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ao_size", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ao_size", "get_ao_size"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_two_bounces"), "set_use_two_bounces", "is_using_two_bounces"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior"); -} - -GIProbeData::GIProbeData() { - probe = RS::get_singleton()->gi_probe_create(); -} - -GIProbeData::~GIProbeData() { - RS::get_singleton()->free(probe); -} - -////////////////////// -////////////////////// - -void GIProbe::set_probe_data(const Ref &p_data) { - if (p_data.is_valid()) { - RS::get_singleton()->instance_set_base(get_instance(), p_data->get_rid()); - } else { - RS::get_singleton()->instance_set_base(get_instance(), RID()); - } - - probe_data = p_data; -} - -Ref GIProbe::get_probe_data() const { - return probe_data; -} - -void GIProbe::set_subdiv(Subdiv p_subdiv) { - ERR_FAIL_INDEX(p_subdiv, SUBDIV_MAX); - subdiv = p_subdiv; - update_gizmo(); -} - -GIProbe::Subdiv GIProbe::get_subdiv() const { - return subdiv; -} - -void GIProbe::set_extents(const Vector3 &p_extents) { - extents = p_extents; - update_gizmo(); -} - -Vector3 GIProbe::get_extents() const { - return extents; -} - -void GIProbe::_find_meshes(Node *p_at_node, List &plot_meshes) { - MeshInstance3D *mi = Object::cast_to(p_at_node); - if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_BAKED && mi->is_visible_in_tree()) { - Ref mesh = mi->get_mesh(); - if (mesh.is_valid()) { - AABB aabb = mesh->get_aabb(); - - Transform3D xf = get_global_transform().affine_inverse() * mi->get_global_transform(); - - if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) { - PlotMesh pm; - pm.local_xform = xf; - pm.mesh = mesh; - for (int i = 0; i < mesh->get_surface_count(); i++) { - pm.instance_materials.push_back(mi->get_surface_override_material(i)); - } - pm.override_material = mi->get_material_override(); - plot_meshes.push_back(pm); - } - } - } - - Node3D *s = Object::cast_to(p_at_node); - if (s) { - if (s->is_visible_in_tree()) { - Array meshes = p_at_node->call("get_meshes"); - for (int i = 0; i < meshes.size(); i += 2) { - Transform3D mxf = meshes[i]; - Ref mesh = meshes[i + 1]; - if (!mesh.is_valid()) { - continue; - } - - AABB aabb = mesh->get_aabb(); - - Transform3D xf = get_global_transform().affine_inverse() * (s->get_global_transform() * mxf); - - if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) { - PlotMesh pm; - pm.local_xform = xf; - pm.mesh = mesh; - plot_meshes.push_back(pm); - } - } - } - } - - for (int i = 0; i < p_at_node->get_child_count(); i++) { - Node *child = p_at_node->get_child(i); - _find_meshes(child, plot_meshes); - } -} - -GIProbe::BakeBeginFunc GIProbe::bake_begin_function = nullptr; -GIProbe::BakeStepFunc GIProbe::bake_step_function = nullptr; -GIProbe::BakeEndFunc GIProbe::bake_end_function = nullptr; - -Vector3i GIProbe::get_estimated_cell_size() const { - static const int subdiv_value[SUBDIV_MAX] = { 6, 7, 8, 9 }; - int cell_subdiv = subdiv_value[subdiv]; - int axis_cell_size[3]; - AABB bounds = AABB(-extents, extents * 2.0); - int longest_axis = bounds.get_longest_axis_index(); - axis_cell_size[longest_axis] = 1 << cell_subdiv; - - for (int i = 0; i < 3; i++) { - if (i == longest_axis) { - continue; - } - - axis_cell_size[i] = axis_cell_size[longest_axis]; - float axis_size = bounds.size[longest_axis]; - - //shrink until fit subdiv - while (axis_size / 2.0 >= bounds.size[i]) { - axis_size /= 2.0; - axis_cell_size[i] >>= 1; - } - } - - return Vector3i(axis_cell_size[0], axis_cell_size[1], axis_cell_size[2]); -} - -void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) { - static const int subdiv_value[SUBDIV_MAX] = { 6, 7, 8, 9 }; - - p_from_node = p_from_node ? p_from_node : get_parent(); - ERR_FAIL_NULL(p_from_node); - - Voxelizer baker; - - baker.begin_bake(subdiv_value[subdiv], AABB(-extents, extents * 2.0)); - - List mesh_list; - - _find_meshes(p_from_node, mesh_list); - - if (bake_begin_function) { - bake_begin_function(mesh_list.size() + 1); - } - - int pmc = 0; - - for (List::Element *E = mesh_list.front(); E; E = E->next()) { - if (bake_step_function) { - bake_step_function(pmc, RTR("Plotting Meshes") + " " + itos(pmc) + "/" + itos(mesh_list.size())); - } - - pmc++; - - baker.plot_mesh(E->get().local_xform, E->get().mesh, E->get().instance_materials, E->get().override_material); - } - if (bake_step_function) { - bake_step_function(pmc++, RTR("Finishing Plot")); - } - - baker.end_bake(); - - //create the data for visual server - - if (p_create_visual_debug) { - MultiMeshInstance3D *mmi = memnew(MultiMeshInstance3D); - mmi->set_multimesh(baker.create_debug_multimesh()); - add_child(mmi); -#ifdef TOOLS_ENABLED - if (is_inside_tree() && get_tree()->get_edited_scene_root() == this) { - mmi->set_owner(this); - } else { - mmi->set_owner(get_owner()); - } -#else - mmi->set_owner(get_owner()); -#endif - - } else { - Ref probe_data = get_probe_data(); - - if (probe_data.is_null()) { - probe_data.instance(); - } - - if (bake_step_function) { - bake_step_function(pmc++, RTR("Generating Distance Field")); - } - - Vector df = baker.get_sdf_3d_image(); - - probe_data->allocate(baker.get_to_cell_space_xform(), AABB(-extents, extents * 2.0), baker.get_giprobe_octree_size(), baker.get_giprobe_octree_cells(), baker.get_giprobe_data_cells(), df, baker.get_giprobe_level_cell_count()); - - set_probe_data(probe_data); -#ifdef TOOLS_ENABLED - probe_data->set_edited(true); //so it gets saved -#endif - } - - if (bake_end_function) { - bake_end_function(); - } - - notify_property_list_changed(); //bake property may have changed -} - -void GIProbe::_debug_bake() { - bake(nullptr, true); -} - -AABB GIProbe::get_aabb() const { - return AABB(-extents, extents * 2); -} - -Vector GIProbe::get_faces(uint32_t p_usage_flags) const { - return Vector(); -} - -TypedArray GIProbe::get_configuration_warnings() const { - TypedArray warnings = Node::get_configuration_warnings(); - - if (RenderingServer::get_singleton()->is_low_end()) { - warnings.push_back(TTR("GIProbes are not supported by the GLES2 video driver.\nUse a BakedLightmap instead.")); - } else if (probe_data.is_null()) { - warnings.push_back(TTR("No GIProbe data set, so this node is disabled. Bake static objects to enable GI.")); - } - return warnings; -} - -void GIProbe::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_probe_data", "data"), &GIProbe::set_probe_data); - ClassDB::bind_method(D_METHOD("get_probe_data"), &GIProbe::get_probe_data); - - ClassDB::bind_method(D_METHOD("set_subdiv", "subdiv"), &GIProbe::set_subdiv); - ClassDB::bind_method(D_METHOD("get_subdiv"), &GIProbe::get_subdiv); - - ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GIProbe::set_extents); - ClassDB::bind_method(D_METHOD("get_extents"), &GIProbe::get_extents); - - ClassDB::bind_method(D_METHOD("bake", "from_node", "create_visual_debug"), &GIProbe::bake, DEFVAL(Variant()), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("debug_bake"), &GIProbe::_debug_bake); - ClassDB::set_method_flags(get_class_static(), _scs_create("debug_bake"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); - - ADD_PROPERTY(PropertyInfo(Variant::INT, "subdiv", PROPERTY_HINT_ENUM, "64,128,256,512"), "set_subdiv", "get_subdiv"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "data", PROPERTY_HINT_RESOURCE_TYPE, "GIProbeData", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE), "set_probe_data", "get_probe_data"); - - BIND_ENUM_CONSTANT(SUBDIV_64); - BIND_ENUM_CONSTANT(SUBDIV_128); - BIND_ENUM_CONSTANT(SUBDIV_256); - BIND_ENUM_CONSTANT(SUBDIV_512); - BIND_ENUM_CONSTANT(SUBDIV_MAX); -} - -GIProbe::GIProbe() { - gi_probe = RS::get_singleton()->gi_probe_create(); - set_disable_scale(true); -} - -GIProbe::~GIProbe() { - RS::get_singleton()->free(gi_probe); -} diff --git a/scene/3d/gi_probe.h b/scene/3d/gi_probe.h deleted file mode 100644 index 6d922e28f6..0000000000 --- a/scene/3d/gi_probe.h +++ /dev/null @@ -1,176 +0,0 @@ -/*************************************************************************/ -/* gi_probe.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef GIPROBE_H -#define GIPROBE_H - -#include "multimesh_instance_3d.h" -#include "scene/3d/visual_instance_3d.h" - -class GIProbeData : public Resource { - GDCLASS(GIProbeData, Resource); - - RID probe; - - void _set_data(const Dictionary &p_data); - Dictionary _get_data() const; - - Transform3D to_cell_xform; - AABB bounds; - Vector3 octree_size; - - float dynamic_range = 4.0; - float energy = 1.0; - float bias = 1.5; - float normal_bias = 0.0; - float propagation = 0.7; - float anisotropy_strength = 0.5; - float ao = 0.0; - float ao_size = 0.5; - bool interior = false; - bool use_two_bounces = false; - -protected: - static void _bind_methods(); - void _validate_property(PropertyInfo &property) const override; - -public: - void allocate(const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3 &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts); - AABB get_bounds() const; - Vector3 get_octree_size() const; - Vector get_octree_cells() const; - Vector get_data_cells() const; - Vector get_distance_field() const; - Vector get_level_counts() const; - Transform3D get_to_cell_xform() const; - - void set_dynamic_range(float p_range); - float get_dynamic_range() const; - - void set_propagation(float p_propagation); - float get_propagation() const; - - void set_anisotropy_strength(float p_anisotropy_strength); - float get_anisotropy_strength() const; - - void set_ao(float p_ao); - float get_ao() const; - - void set_ao_size(float p_ao_size); - float get_ao_size() const; - - void set_energy(float p_energy); - float get_energy() const; - - void set_bias(float p_bias); - float get_bias() const; - - void set_normal_bias(float p_normal_bias); - float get_normal_bias() const; - - void set_interior(bool p_enable); - bool is_interior() const; - - void set_use_two_bounces(bool p_enable); - bool is_using_two_bounces() const; - - virtual RID get_rid() const override; - - GIProbeData(); - ~GIProbeData(); -}; - -class GIProbe : public VisualInstance3D { - GDCLASS(GIProbe, VisualInstance3D); - -public: - enum Subdiv { - SUBDIV_64, - SUBDIV_128, - SUBDIV_256, - SUBDIV_512, - SUBDIV_MAX - - }; - - typedef void (*BakeBeginFunc)(int); - typedef void (*BakeStepFunc)(int, const String &); - typedef void (*BakeEndFunc)(); - -private: - Ref probe_data; - - RID gi_probe; - - Subdiv subdiv = SUBDIV_128; - Vector3 extents = Vector3(10, 10, 10); - - struct PlotMesh { - Ref override_material; - Vector> instance_materials; - Ref mesh; - Transform3D local_xform; - }; - - void _find_meshes(Node *p_at_node, List &plot_meshes); - void _debug_bake(); - -protected: - static void _bind_methods(); - -public: - static BakeBeginFunc bake_begin_function; - static BakeStepFunc bake_step_function; - static BakeEndFunc bake_end_function; - - void set_probe_data(const Ref &p_data); - Ref get_probe_data() const; - - void set_subdiv(Subdiv p_subdiv); - Subdiv get_subdiv() const; - - void set_extents(const Vector3 &p_extents); - Vector3 get_extents() const; - Vector3i get_estimated_cell_size() const; - - void bake(Node *p_from_node = nullptr, bool p_create_visual_debug = false); - - virtual AABB get_aabb() const override; - virtual Vector get_faces(uint32_t p_usage_flags) const override; - - TypedArray get_configuration_warnings() const override; - - GIProbe(); - ~GIProbe(); -}; - -VARIANT_ENUM_CAST(GIProbe::Subdiv) - -#endif // GIPROBE_H diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp new file mode 100644 index 0000000000..cc1177d541 --- /dev/null +++ b/scene/3d/lightmap_gi.cpp @@ -0,0 +1,1466 @@ +/*************************************************************************/ +/* lightmap_gi.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "lightmap_gi.h" + +#include "core/io/config_file.h" +#include "core/io/resource_saver.h" +#include "core/math/camera_matrix.h" +#include "core/math/delaunay_3d.h" +#include "core/os/dir_access.h" +#include "core/os/file_access.h" +#include "core/os/os.h" +#include "core/templates/sort_array.h" +#include "lightmap_probe.h" + +void LightmapGIData::add_user(const NodePath &p_path, const Rect2 &p_uv_scale, int p_slice_index, int32_t p_sub_instance) { + User user; + user.path = p_path; + user.uv_scale = p_uv_scale; + user.slice_index = p_slice_index; + user.sub_instance = p_sub_instance; + users.push_back(user); +} + +int LightmapGIData::get_user_count() const { + return users.size(); +} + +NodePath LightmapGIData::get_user_path(int p_user) const { + ERR_FAIL_INDEX_V(p_user, users.size(), NodePath()); + return users[p_user].path; +} + +int32_t LightmapGIData::get_user_sub_instance(int p_user) const { + ERR_FAIL_INDEX_V(p_user, users.size(), -1); + return users[p_user].sub_instance; +} + +Rect2 LightmapGIData::get_user_lightmap_uv_scale(int p_user) const { + ERR_FAIL_INDEX_V(p_user, users.size(), Rect2()); + return users[p_user].uv_scale; +} + +int LightmapGIData::get_user_lightmap_slice_index(int p_user) const { + ERR_FAIL_INDEX_V(p_user, users.size(), -1); + return users[p_user].slice_index; +} + +void LightmapGIData::clear_users() { + users.clear(); +} + +void LightmapGIData::_set_user_data(const Array &p_data) { + ERR_FAIL_COND(p_data.size() <= 0); + ERR_FAIL_COND((p_data.size() % 4) != 0); + + for (int i = 0; i < p_data.size(); i += 4) { + add_user(p_data[i + 0], p_data[i + 1], p_data[i + 2], p_data[i + 3]); + } +} + +Array LightmapGIData::_get_user_data() const { + Array ret; + for (int i = 0; i < users.size(); i++) { + ret.push_back(users[i].path); + ret.push_back(users[i].uv_scale); + ret.push_back(users[i].slice_index); + ret.push_back(users[i].sub_instance); + } + return ret; +} + +RID LightmapGIData::get_rid() const { + return lightmap; +} + +void LightmapGIData::clear() { + users.clear(); +} + +void LightmapGIData::set_light_texture(const Ref &p_light_texture) { + light_texture = p_light_texture; + RS::get_singleton()->lightmap_set_textures(lightmap, light_texture.is_valid() ? light_texture->get_rid() : RID(), uses_spherical_harmonics); +} + +Ref LightmapGIData::get_light_texture() const { + return light_texture; +} + +void LightmapGIData::set_uses_spherical_harmonics(bool p_enable) { + uses_spherical_harmonics = p_enable; + RS::get_singleton()->lightmap_set_textures(lightmap, light_texture.is_valid() ? light_texture->get_rid() : RID(), uses_spherical_harmonics); +} + +bool LightmapGIData::is_using_spherical_harmonics() const { + return uses_spherical_harmonics; +} + +void LightmapGIData::set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) { + if (p_points.size()) { + int pc = p_points.size(); + ERR_FAIL_COND(pc * 9 != p_point_sh.size()); + ERR_FAIL_COND((p_tetrahedra.size() % 4) != 0); + ERR_FAIL_COND((p_bsp_tree.size() % 6) != 0); + RS::get_singleton()->lightmap_set_probe_capture_data(lightmap, p_points, p_point_sh, p_tetrahedra, p_bsp_tree); + RS::get_singleton()->lightmap_set_probe_bounds(lightmap, p_bounds); + RS::get_singleton()->lightmap_set_probe_interior(lightmap, p_interior); + } else { + RS::get_singleton()->lightmap_set_probe_capture_data(lightmap, PackedVector3Array(), PackedColorArray(), PackedInt32Array(), PackedInt32Array()); + RS::get_singleton()->lightmap_set_probe_bounds(lightmap, AABB()); + RS::get_singleton()->lightmap_set_probe_interior(lightmap, false); + } + interior = p_interior; + bounds = p_bounds; +} + +PackedVector3Array LightmapGIData::get_capture_points() const { + return RS::get_singleton()->lightmap_get_probe_capture_points(lightmap); +} + +PackedColorArray LightmapGIData::get_capture_sh() const { + return RS::get_singleton()->lightmap_get_probe_capture_sh(lightmap); +} + +PackedInt32Array LightmapGIData::get_capture_tetrahedra() const { + return RS::get_singleton()->lightmap_get_probe_capture_tetrahedra(lightmap); +} + +PackedInt32Array LightmapGIData::get_capture_bsp_tree() const { + return RS::get_singleton()->lightmap_get_probe_capture_bsp_tree(lightmap); +} + +AABB LightmapGIData::get_capture_bounds() const { + return bounds; +} + +bool LightmapGIData::is_interior() const { + return interior; +} + +void LightmapGIData::_set_probe_data(const Dictionary &p_data) { + ERR_FAIL_COND(!p_data.has("bounds")); + ERR_FAIL_COND(!p_data.has("points")); + ERR_FAIL_COND(!p_data.has("tetrahedra")); + ERR_FAIL_COND(!p_data.has("bsp")); + ERR_FAIL_COND(!p_data.has("sh")); + ERR_FAIL_COND(!p_data.has("interior")); + set_capture_data(p_data["bounds"], p_data["interior"], p_data["points"], p_data["sh"], p_data["tetrahedra"], p_data["bsp"]); +} + +Dictionary LightmapGIData::_get_probe_data() const { + Dictionary d; + d["bounds"] = get_capture_bounds(); + d["points"] = get_capture_points(); + d["tetrahedra"] = get_capture_tetrahedra(); + d["bsp"] = get_capture_bsp_tree(); + d["sh"] = get_capture_sh(); + d["interior"] = is_interior(); + return d; +} + +void LightmapGIData::_bind_methods() { + ClassDB::bind_method(D_METHOD("_set_user_data", "data"), &LightmapGIData::_set_user_data); + ClassDB::bind_method(D_METHOD("_get_user_data"), &LightmapGIData::_get_user_data); + + ClassDB::bind_method(D_METHOD("set_light_texture", "light_texture"), &LightmapGIData::set_light_texture); + ClassDB::bind_method(D_METHOD("get_light_texture"), &LightmapGIData::get_light_texture); + + ClassDB::bind_method(D_METHOD("set_uses_spherical_harmonics", "uses_spherical_harmonics"), &LightmapGIData::set_uses_spherical_harmonics); + ClassDB::bind_method(D_METHOD("is_using_spherical_harmonics"), &LightmapGIData::is_using_spherical_harmonics); + + ClassDB::bind_method(D_METHOD("add_user", "path", "uv_scale", "slice_index", "sub_instance"), &LightmapGIData::add_user); + ClassDB::bind_method(D_METHOD("get_user_count"), &LightmapGIData::get_user_count); + ClassDB::bind_method(D_METHOD("get_user_path", "user_idx"), &LightmapGIData::get_user_path); + ClassDB::bind_method(D_METHOD("clear_users"), &LightmapGIData::clear_users); + + ClassDB::bind_method(D_METHOD("_set_probe_data", "data"), &LightmapGIData::_set_probe_data); + ClassDB::bind_method(D_METHOD("_get_probe_data"), &LightmapGIData::_get_probe_data); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_texture", PROPERTY_HINT_RESOURCE_TYPE, "TextureLayered"), "set_light_texture", "get_light_texture"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uses_spherical_harmonics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_uses_spherical_harmonics", "is_using_spherical_harmonics"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "user_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_user_data", "_get_user_data"); + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "probe_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_probe_data", "_get_probe_data"); +} + +LightmapGIData::LightmapGIData() { + lightmap = RS::get_singleton()->lightmap_create(); +} + +LightmapGIData::~LightmapGIData() { + RS::get_singleton()->free(lightmap); +} + +/////////////////////////// + +void LightmapGI::_find_meshes_and_lights(Node *p_at_node, Vector &meshes, Vector &lights, Vector &probes) { + MeshInstance3D *mi = Object::cast_to(p_at_node); + if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_BAKED && mi->is_visible_in_tree()) { + Ref mesh = mi->get_mesh(); + if (mesh.is_valid()) { + bool all_have_uv2_and_normal = true; + bool surfaces_found = false; + for (int i = 0; i < mesh->get_surface_count(); i++) { + if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { + continue; + } + if (!(mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_TEX_UV2)) { + all_have_uv2_and_normal = false; + break; + } + if (!(mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_NORMAL)) { + all_have_uv2_and_normal = false; + break; + } + surfaces_found = true; + } + + if (surfaces_found && all_have_uv2_and_normal) { + //READY TO BAKE! size hint could be computed if not found, actually.. + + MeshesFound mf; + mf.xform = get_global_transform().affine_inverse() * mi->get_global_transform(); + mf.node_path = get_path_to(mi); + mf.subindex = -1; + mf.mesh = mesh; + + static const int lightmap_scale[GeometryInstance3D::LIGHTMAP_SCALE_MAX] = { 1, 2, 4, 8 }; + mf.lightmap_scale = lightmap_scale[mi->get_lightmap_scale()]; + + Ref all_override = mi->get_material_override(); + for (int i = 0; i < mesh->get_surface_count(); i++) { + if (all_override.is_valid()) { + mf.overrides.push_back(all_override); + } else { + mf.overrides.push_back(mi->get_surface_override_material(i)); + } + } + + meshes.push_back(mf); + } + } + } + + Node3D *s = Object::cast_to(p_at_node); + + if (!mi && s) { + Array bmeshes = p_at_node->call("get_bake_bmeshes"); + if (bmeshes.size() && (bmeshes.size() & 1) == 0) { + Transform3D xf = get_global_transform().affine_inverse() * s->get_global_transform(); + for (int i = 0; i < bmeshes.size(); i += 2) { + Ref mesh = bmeshes[i]; + if (!mesh.is_valid()) { + continue; + } + + MeshesFound mf; + + Transform3D mesh_xf = bmeshes[i + 1]; + mf.xform = xf * mesh_xf; + mf.node_path = get_path_to(s); + mf.subindex = i / 2; + mf.lightmap_scale = 1; + mf.mesh = mesh; + + meshes.push_back(mf); + } + } + } + + Light3D *light = Object::cast_to(p_at_node); + + if (light && light->get_bake_mode() != Light3D::BAKE_DISABLED) { + LightsFound lf; + lf.xform = get_global_transform().affine_inverse() * light->get_global_transform(); + lf.light = light; + lights.push_back(lf); + } + + LightmapProbe *probe = Object::cast_to(p_at_node); + + if (probe) { + Transform3D xf = get_global_transform().affine_inverse() * probe->get_global_transform(); + probes.push_back(xf.origin); + } + + for (int i = 0; i < p_at_node->get_child_count(); i++) { + Node *child = p_at_node->get_child(i); + if (!child->get_owner()) { + continue; //maybe a helper + } + + _find_meshes_and_lights(child, meshes, lights, probes); + } +} + +int LightmapGI::_bsp_get_simplex_side(const Vector &p_points, const LocalVector &p_simplices, const Plane &p_plane, uint32_t p_simplex) const { + int over = 0; + int under = 0; + int coplanar = 0; + const BSPSimplex &s = p_simplices[p_simplex]; + for (int i = 0; i < 4; i++) { + const Vector3 v = p_points[s.vertices[i]]; + if (p_plane.has_point(v)) { //coplanar + coplanar++; + } else if (p_plane.is_point_over(v)) { + over++; + } else { + under++; + } + } + + ERR_FAIL_COND_V(under == 0 && over == 0, -2); //should never happen, we discarded flat simplices before, but in any case drop it from the bsp tree and throw an error + if (under == 0) { + return 1; // all over + } else if (over == 0) { + return -1; // all under + } else { + return 0; // crossing + } +} + +//#define DEBUG_BSP + +int32_t LightmapGI::_compute_bsp_tree(const Vector &p_points, const LocalVector &p_planes, LocalVector &planes_tested, const LocalVector &p_simplices, const LocalVector &p_simplex_indices, LocalVector &bsp_nodes) { + //if we reach here, it means there is more than one simplex + int32_t node_index = (int32_t)bsp_nodes.size(); + bsp_nodes.push_back(BSPNode()); + + //test with all the simplex planes + Plane best_plane; + float best_plane_score = -1.0; + + for (uint32_t i = 0; i < p_simplex_indices.size(); i++) { + const BSPSimplex &s = p_simplices[p_simplex_indices[i]]; + for (int j = 0; j < 4; j++) { + uint32_t plane_index = s.planes[j]; + if (planes_tested[plane_index] == node_index) { + continue; //tested this plane already + } + + planes_tested[plane_index] = node_index; + + static const int face_order[4][3] = { + { 0, 1, 2 }, + { 0, 2, 3 }, + { 0, 1, 3 }, + { 1, 2, 3 } + }; + + // despite getting rid of plane duplicates, we should still use here the actual plane to avoid numerical error + // from thinking this same simplex is intersecting rather than on a side + Vector3 v0 = p_points[s.vertices[face_order[j][0]]]; + Vector3 v1 = p_points[s.vertices[face_order[j][1]]]; + Vector3 v2 = p_points[s.vertices[face_order[j][2]]]; + + Plane plane(v0, v1, v2); + + //test with all the simplices + int over_count = 0; + int under_count = 0; + + for (uint32_t k = 0; k < p_simplex_indices.size(); k++) { + int side = _bsp_get_simplex_side(p_points, p_simplices, plane, p_simplex_indices[k]); + if (side == -2) { + continue; //this simplex is invalid, skip for now + } else if (side < 0) { + under_count++; + } else if (side > 0) { + over_count++; + } + } + + if (under_count == 0 && over_count == 0) { + continue; //most likely precision issue with a flat simplex, do not try this plane + } + + if (under_count > over_count) { //make sure under is always less than over, so we can compute the same ratio + SWAP(under_count, over_count); + } + + float score = 0; //by default, score is 0 (worst) + if (over_count > 0) { + //give score mainly based on ratio (under / over), this means that this plane is splitting simplices a lot, but its balanced + score = float(under_count) / over_count; + } + + //adjusting priority over least splits, probably not a great idea + //score *= Math::sqrt(float(over_count + under_count) / p_simplex_indices.size()); //also multiply score + + if (score > best_plane_score) { + best_plane = plane; + best_plane_score = score; + } + } + } + + LocalVector indices_over; + LocalVector indices_under; + + //split again, but add to list + for (uint32_t i = 0; i < p_simplex_indices.size(); i++) { + uint32_t index = p_simplex_indices[i]; + int side = _bsp_get_simplex_side(p_points, p_simplices, best_plane, index); + + if (side == -2) { + continue; //simplex sits on the plane, does not make sense to use it + } + if (side <= 0) { + indices_under.push_back(index); + } + + if (side >= 0) { + indices_over.push_back(index); + } + } + +#ifdef DEBUG_BSP + print_line("node " + itos(node_index) + " found plane: " + best_plane + " score:" + rtos(best_plane_score) + " - over " + itos(indices_over.size()) + " under " + itos(indices_under.size()) + " intersecting " + itos(intersecting)); +#endif + + if (best_plane_score < 0.0 || indices_over.size() == p_simplex_indices.size() || indices_under.size() == p_simplex_indices.size()) { + ERR_FAIL_COND_V(p_simplex_indices.size() <= 1, 0); //should not happen, this is a bug + + // Failed to separate the tetrahedrons using planes + // this means Delaunay broke at some point. + // Luckily, because we are using tetrahedrons, we can resort to + // less precise but still working ways to generate the separating plane + // this will most likely look bad when interpolating, but at least it will not crash. + // and the arctifact will most likely also be very small, so too difficult to notice. + + //find the longest axis + + WARN_PRINT("Inconsistency found in triangulation while building BSP, probe interpolation quality may degrade a bit."); + + LocalVector centers; + AABB bounds_all; + for (uint32_t i = 0; i < p_simplex_indices.size(); i++) { + AABB bounds; + for (uint32_t j = 0; j < 4; j++) { + Vector3 p = p_points[p_simplices[p_simplex_indices[i]].vertices[j]]; + if (j == 0) { + bounds.position = p; + } else { + bounds.expand_to(p); + } + } + if (i == 0) { + centers.push_back(bounds.position + bounds.size * 0.5); + } else { + bounds_all.merge_with(bounds); + } + } + Vector3::Axis longest_axis = Vector3::Axis(bounds_all.get_longest_axis_index()); + + //find the simplex that will go under + uint32_t min_d_idx = 0xFFFFFFFF; + float min_d_dist = 1e20; + + for (uint32_t i = 0; i < centers.size(); i++) { + if (centers[i][longest_axis] < min_d_dist) { + min_d_idx = i; + min_d_dist = centers[i][longest_axis]; + } + } + //rebuild best_plane and over/under arrays + best_plane = Plane(); + best_plane.normal[longest_axis] = 1.0; + best_plane.d = min_d_dist; + + indices_under.clear(); + indices_under.push_back(min_d_idx); + + indices_over.clear(); + + for (uint32_t i = 0; i < p_simplex_indices.size(); i++) { + if (i == min_d_idx) { + continue; + } + indices_over.push_back(p_simplex_indices[i]); + } + } + + BSPNode node; + node.plane = best_plane; + + if (indices_under.size() == 0) { + //nothing to do here + node.under = BSPNode::EMPTY_LEAF; + } else if (indices_under.size() == 1) { + node.under = -(indices_under[0] + 1); + } else { + node.under = _compute_bsp_tree(p_points, p_planes, planes_tested, p_simplices, indices_under, bsp_nodes); + } + + if (indices_over.size() == 0) { + //nothing to do here + node.over = BSPNode::EMPTY_LEAF; + } else if (indices_over.size() == 1) { + node.over = -(indices_over[0] + 1); + } else { + node.over = _compute_bsp_tree(p_points, p_planes, planes_tested, p_simplices, indices_over, bsp_nodes); + } + + bsp_nodes[node_index] = node; + + return node_index; +} + +bool LightmapGI::_lightmap_bake_step_function(float p_completion, const String &p_text, void *ud, bool p_refresh) { + BakeStepUD *bsud = (BakeStepUD *)ud; + bool ret = false; + if (bsud->func) { + ret = bsud->func(bsud->from_percent + p_completion * (bsud->to_percent - bsud->from_percent), p_text, bsud->ud, p_refresh); + } + return ret; +} + +void LightmapGI::_plot_triangle_into_octree(GenProbesOctree *p_cell, float p_cell_size, const Vector3 *p_triangle) { + for (int i = 0; i < 8; i++) { + Vector3i pos = p_cell->offset; + uint32_t half_size = p_cell->size / 2; + if (i & 1) { + pos.x += half_size; + } + if (i & 2) { + pos.y += half_size; + } + if (i & 4) { + pos.z += half_size; + } + + AABB subcell; + subcell.position = Vector3(pos) * p_cell_size; + subcell.size = Vector3(half_size, half_size, half_size) * p_cell_size; + + if (!Geometry3D::triangle_box_overlap(subcell.position + subcell.size * 0.5, subcell.size * 0.5, p_triangle)) { + continue; + } + + if (p_cell->children[i] == nullptr) { + GenProbesOctree *child = memnew(GenProbesOctree); + child->offset = pos; + child->size = half_size; + p_cell->children[i] = child; + } + + if (half_size > 1) { + //still levels missing + _plot_triangle_into_octree(p_cell->children[i], p_cell_size, p_triangle); + } + } +} + +void LightmapGI::_gen_new_positions_from_octree(const GenProbesOctree *p_cell, float p_cell_size, const Vector &probe_positions, LocalVector &new_probe_positions, HashMap &positions_used, const AABB &p_bounds) { + for (int i = 0; i < 8; i++) { + Vector3i pos = p_cell->offset; + if (i & 1) { + pos.x += p_cell->size; + } + if (i & 2) { + pos.y += p_cell->size; + } + if (i & 4) { + pos.z += p_cell->size; + } + + if (p_cell->size == 1 && !positions_used.has(pos)) { + //new position to insert! + Vector3 real_pos = p_bounds.position + Vector3(pos) * p_cell_size; + //see if a user submitted probe is too close + int ppcount = probe_positions.size(); + const Vector3 *pp = probe_positions.ptr(); + bool exists = false; + for (int j = 0; j < ppcount; j++) { + if (pp[j].distance_to(real_pos) < CMP_EPSILON) { + exists = true; + break; + } + } + + if (!exists) { + new_probe_positions.push_back(real_pos); + } + + positions_used[pos] = true; + } + + if (p_cell->children[i] != nullptr) { + _gen_new_positions_from_octree(p_cell->children[i], p_cell_size, probe_positions, new_probe_positions, positions_used, p_bounds); + } + } +} + +LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_path, Lightmapper::BakeStepFunc p_bake_step, void *p_bake_userdata) { + if (p_image_data_path == "") { + if (get_light_data().is_null()) { + return BAKE_ERROR_NO_SAVE_PATH; + } + + p_image_data_path = get_light_data()->get_path(); + if (!p_image_data_path.is_resource_file()) { + return BAKE_ERROR_NO_SAVE_PATH; + } + } + + Ref lightmapper = Lightmapper::create(); + ERR_FAIL_COND_V(lightmapper.is_null(), BAKE_ERROR_NO_LIGHTMAPPER); + + BakeStepUD bsud; + bsud.func = p_bake_step; + bsud.ud = p_bake_userdata; + bsud.from_percent = 0.2; + bsud.to_percent = 0.8; + + if (p_bake_step) { + p_bake_step(0.0, TTR("Finding meshes, lights and probes"), p_bake_userdata, true); + } + /* STEP 1, FIND MESHES, LIGHTS AND PROBES */ + Vector mesh_data; + Vector lights_found; + Vector probes_found; + AABB bounds; + { + Vector meshes_found; + _find_meshes_and_lights(p_from_node ? p_from_node : get_parent(), meshes_found, lights_found, probes_found); + + if (meshes_found.size() == 0) { + return BAKE_ERROR_NO_MESHES; + } + // create mesh data for insert + + //get the base material textures, help compute atlas size and bounds + for (int m_i = 0; m_i < meshes_found.size(); m_i++) { + if (p_bake_step) { + float p = (float)(m_i) / meshes_found.size(); + p_bake_step(p * 0.1, vformat(TTR("Preparing geometry %d/%d"), m_i, meshes_found.size()), p_bake_userdata, false); + } + + MeshesFound &mf = meshes_found.write[m_i]; + + Size2i lightmap_size = mf.mesh->get_lightmap_size_hint() * mf.lightmap_scale; + Vector overrides; + overrides.resize(mf.overrides.size()); + for (int i = 0; i < mf.overrides.size(); i++) { + if (mf.overrides[i].is_valid()) { + overrides.write[i] = mf.overrides[i]->get_rid(); + } + } + TypedArray images = RS::get_singleton()->bake_render_uv2(mf.mesh->get_rid(), overrides, lightmap_size); + + ERR_FAIL_COND_V(images.is_empty(), BAKE_ERROR_CANT_CREATE_IMAGE); + + Ref albedo = images[RS::BAKE_CHANNEL_ALBEDO_ALPHA]; + Ref orm = images[RS::BAKE_CHANNEL_ORM]; + + //multiply albedo by metal + + Lightmapper::MeshData md; + + { + Dictionary d; + d["path"] = mf.node_path; + if (mf.subindex >= 0) { + d["subindex"] = mf.subindex; + } + md.userdata = d; + } + + { + if (albedo->get_format() != Image::FORMAT_RGBA8) { + albedo->convert(Image::FORMAT_RGBA8); + } + if (orm->get_format() != Image::FORMAT_RGBA8) { + orm->convert(Image::FORMAT_RGBA8); + } + Vector albedo_alpha = albedo->get_data(); + Vector orm_data = orm->get_data(); + + Vector albedom; + uint32_t len = albedo_alpha.size(); + albedom.resize(len); + const uint8_t *r_aa = albedo_alpha.ptr(); + const uint8_t *r_orm = orm_data.ptr(); + uint8_t *w_albedo = albedom.ptrw(); + + for (uint32_t i = 0; i < len; i += 4) { + w_albedo[i + 0] = uint8_t(CLAMP(float(r_aa[i + 0]) * (1.0 - float(r_orm[i + 2] / 255.0)), 0, 255)); + w_albedo[i + 1] = uint8_t(CLAMP(float(r_aa[i + 1]) * (1.0 - float(r_orm[i + 2] / 255.0)), 0, 255)); + w_albedo[i + 2] = uint8_t(CLAMP(float(r_aa[i + 2]) * (1.0 - float(r_orm[i + 2] / 255.0)), 0, 255)); + w_albedo[i + 3] = 255; + } + + md.albedo_on_uv2.instance(); + md.albedo_on_uv2->create(lightmap_size.width, lightmap_size.height, false, Image::FORMAT_RGBA8, albedom); + } + + md.emission_on_uv2 = images[RS::BAKE_CHANNEL_EMISSION]; + if (md.emission_on_uv2->get_format() != Image::FORMAT_RGBAH) { + md.emission_on_uv2->convert(Image::FORMAT_RGBAH); + } + + //get geometry + + Basis normal_xform = mf.xform.basis.inverse().transposed(); + + for (int i = 0; i < mf.mesh->get_surface_count(); i++) { + if (mf.mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { + continue; + } + Array a = mf.mesh->surface_get_arrays(i); + + Vector vertices = a[Mesh::ARRAY_VERTEX]; + const Vector3 *vr = vertices.ptr(); + Vector uv = a[Mesh::ARRAY_TEX_UV2]; + const Vector2 *uvr = nullptr; + Vector normals = a[Mesh::ARRAY_NORMAL]; + const Vector3 *nr = nullptr; + Vector index = a[Mesh::ARRAY_INDEX]; + + ERR_CONTINUE(uv.size() == 0); + ERR_CONTINUE(normals.size() == 0); + + uvr = uv.ptr(); + nr = normals.ptr(); + + int facecount; + const int *ir = nullptr; + + if (index.size()) { + facecount = index.size() / 3; + ir = index.ptr(); + } else { + facecount = vertices.size() / 3; + } + + for (int j = 0; j < facecount; j++) { + uint32_t vidx[3]; + + if (ir) { + for (int k = 0; k < 3; k++) { + vidx[k] = ir[j * 3 + k]; + } + } else { + for (int k = 0; k < 3; k++) { + vidx[k] = j * 3 + k; + } + } + + for (int k = 0; k < 3; k++) { + Vector3 v = mf.xform.xform(vr[vidx[k]]); + if (bounds == AABB()) { + bounds.position = v; + } else { + bounds.expand_to(v); + } + md.points.push_back(v); + + md.uv2.push_back(uvr[vidx[k]]); + md.normal.push_back(normal_xform.xform(nr[vidx[k]]).normalized()); + } + } + } + + mesh_data.push_back(md); + } + } + + /* STEP 2, CREATE PROBES */ + + if (p_bake_step) { + p_bake_step(0.3, TTR("Creating probes"), p_bake_userdata, true); + } + + //bounds need to include the user probes + for (int i = 0; i < probes_found.size(); i++) { + bounds.expand_to(probes_found[i]); + } + + bounds.grow_by(bounds.size.length() * 0.001); + + if (gen_probes == GENERATE_PROBES_DISABLED) { + // generate 8 probes on bound endpoints + for (int i = 0; i < 8; i++) { + probes_found.push_back(bounds.get_endpoint(i)); + } + } else { + // detect probes from geometry + static const int subdiv_values[6] = { 0, 4, 8, 16, 32 }; + int subdiv = subdiv_values[gen_probes]; + + float subdiv_cell_size; + Vector3i bound_limit; + { + int longest_axis = bounds.get_longest_axis_index(); + subdiv_cell_size = bounds.size[longest_axis] / subdiv; + int axis_n1 = (longest_axis + 1) % 3; + int axis_n2 = (longest_axis + 2) % 3; + + bound_limit[longest_axis] = subdiv; + bound_limit[axis_n1] = int(Math::ceil(bounds.size[axis_n1] / subdiv_cell_size)); + bound_limit[axis_n2] = int(Math::ceil(bounds.size[axis_n2] / subdiv_cell_size)); + //compensate bounds + bounds.size[axis_n1] = bound_limit[axis_n1] * subdiv_cell_size; + bounds.size[axis_n2] = bound_limit[axis_n2] * subdiv_cell_size; + } + + GenProbesOctree octree; + octree.size = subdiv; + + for (int i = 0; i < mesh_data.size(); i++) { + if (p_bake_step) { + float p = (float)(i) / mesh_data.size(); + p_bake_step(0.3 + p * 0.1, vformat(TTR("Creating probes from mesh %d/%d"), i, mesh_data.size()), p_bake_userdata, false); + } + + for (int j = 0; j < mesh_data[i].points.size(); j += 3) { + Vector3 points[3] = { mesh_data[i].points[j + 0] - bounds.position, mesh_data[i].points[j + 1] - bounds.position, mesh_data[i].points[j + 2] - bounds.position }; + _plot_triangle_into_octree(&octree, subdiv_cell_size, points); + } + } + + LocalVector new_probe_positions; + HashMap positions_used; + for (uint32_t i = 0; i < 8; i++) { //insert bounding endpoints + Vector3i pos; + if (i & 1) { + pos.x += bound_limit.x; + } + if (i & 2) { + pos.y += bound_limit.y; + } + if (i & 4) { + pos.z += bound_limit.z; + } + + positions_used[pos] = true; + Vector3 real_pos = bounds.position + Vector3(pos) * subdiv_cell_size; //use same formula for numerical stability + new_probe_positions.push_back(real_pos); + } + //skip first level, since probes are always added at bounds endpoints anyway (code above this) + for (int i = 0; i < 8; i++) { + if (octree.children[i]) { + _gen_new_positions_from_octree(octree.children[i], subdiv_cell_size, probes_found, new_probe_positions, positions_used, bounds); + } + } + + for (uint32_t i = 0; i < new_probe_positions.size(); i++) { + probes_found.push_back(new_probe_positions[i]); + } + } + + // Add everything to lightmapper + if (p_bake_step) { + p_bake_step(0.4, TTR("Preparing Lightmapper"), p_bake_userdata, true); + } + + { + for (int i = 0; i < mesh_data.size(); i++) { + lightmapper->add_mesh(mesh_data[i]); + } + for (int i = 0; i < lights_found.size(); i++) { + Light3D *light = lights_found[i].light; + Transform3D xf = lights_found[i].xform; + + if (Object::cast_to(light)) { + DirectionalLight3D *l = Object::cast_to(light); + lightmapper->add_directional_light(light->get_bake_mode() == Light3D::BAKE_STATIC, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_SIZE)); + } else if (Object::cast_to(light)) { + OmniLight3D *l = Object::cast_to(light); + lightmapper->add_omni_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SIZE)); + } else if (Object::cast_to(light)) { + SpotLight3D *l = Object::cast_to(light); + lightmapper->add_spot_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SPOT_ANGLE), l->get_param(Light3D::PARAM_SPOT_ATTENUATION), l->get_param(Light3D::PARAM_SIZE)); + } + } + for (int i = 0; i < probes_found.size(); i++) { + lightmapper->add_probe(probes_found[i]); + } + } + + Ref environment_image; + Basis environment_transform; + + // Add everything to lightmapper + if (environment_mode != ENVIRONMENT_MODE_DISABLED) { + if (p_bake_step) { + p_bake_step(4.1, TTR("Preparing Environment"), p_bake_userdata, true); + } + + environment_transform = get_global_transform().basis; + + switch (environment_mode) { + case ENVIRONMENT_MODE_DISABLED: { + //nothing + } break; + case ENVIRONMENT_MODE_SCENE: { + Ref world = get_world_3d(); + if (world.is_valid()) { + Ref env = world->get_environment(); + if (env.is_null()) { + env = world->get_fallback_environment(); + } + + if (env.is_valid()) { + environment_image = RS::get_singleton()->environment_bake_panorama(env->get_rid(), true, Size2i(128, 64)); + } + } + } break; + case ENVIRONMENT_MODE_CUSTOM_SKY: { + if (environment_custom_sky.is_valid()) { + environment_image = RS::get_singleton()->sky_bake_panorama(environment_custom_sky->get_rid(), environment_custom_energy, true, Size2i(128, 64)); + } + + } break; + case ENVIRONMENT_MODE_CUSTOM_COLOR: { + environment_image.instance(); + environment_image->create(128, 64, false, Image::FORMAT_RGBAF); + Color c = environment_custom_color; + c.r *= environment_custom_energy; + c.g *= environment_custom_energy; + c.b *= environment_custom_energy; + for (int i = 0; i < 128; i++) { + for (int j = 0; j < 64; j++) { + environment_image->set_pixel(i, j, c); + } + } + + } break; + } + } + + Lightmapper::BakeError bake_err = lightmapper->bake(Lightmapper::BakeQuality(bake_quality), use_denoiser, bounces, bias, max_texture_size, directional, Lightmapper::GenerateProbes(gen_probes), environment_image, environment_transform, _lightmap_bake_step_function, &bsud); + + if (bake_err == Lightmapper::BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES) { + return BAKE_ERROR_MESHES_INVALID; + } + + /* POSTBAKE: Save Textures */ + + Ref texture; + { + Vector> images; + for (int i = 0; i < lightmapper->get_bake_texture_count(); i++) { + images.push_back(lightmapper->get_bake_texture(i)); + } + //we assume they are all the same, so let's create a large one for saving + Ref large_image; + large_image.instance(); + + large_image->create(images[0]->get_width(), images[0]->get_height() * images.size(), false, images[0]->get_format()); + + for (int i = 0; i < lightmapper->get_bake_texture_count(); i++) { + large_image->blit_rect(images[i], Rect2(0, 0, images[i]->get_width(), images[i]->get_height()), Point2(0, images[i]->get_height() * i)); + } + + String base_path = p_image_data_path.get_basename() + ".exr"; + + Ref config; + + config.instance(); + if (FileAccess::exists(base_path + ".import")) { + config->load(base_path + ".import"); + } + + config->set_value("remap", "importer", "2d_array_texture"); + config->set_value("remap", "type", "StreamTexture2DArray"); + if (!config->has_section_key("params", "compress/mode")) { + config->set_value("params", "compress/mode", 2); //user may want another compression, so leave it be + } + config->set_value("params", "compress/channel_pack", 1); + config->set_value("params", "mipmaps/generate", false); + config->set_value("params", "slices/horizontal", 1); + config->set_value("params", "slices/vertical", images.size()); + + config->save(base_path + ".import"); + + Error err = large_image->save_exr(base_path, false); + ERR_FAIL_COND_V(err, BAKE_ERROR_CANT_CREATE_IMAGE); + ResourceLoader::import(base_path); + Ref t = ResourceLoader::load(base_path); //if already loaded, it will be updated on refocus? + ERR_FAIL_COND_V(t.is_null(), BAKE_ERROR_CANT_CREATE_IMAGE); + texture = t; + } + + /* POSTBAKE: Save Light Data */ + + Ref data; + if (get_light_data().is_valid()) { + data = get_light_data(); + set_light_data(Ref()); //clear + data->clear(); + } else { + data.instance(); + } + + data->set_light_texture(texture); + data->set_uses_spherical_harmonics(directional); + + for (int i = 0; i < lightmapper->get_bake_mesh_count(); i++) { + Dictionary d = lightmapper->get_bake_mesh_userdata(i); + NodePath np = d["path"]; + int32_t subindex = -1; + if (d.has("subindex")) { + subindex = d["subindex"]; + } + + Rect2 uv_scale = lightmapper->get_bake_mesh_uv_scale(i); + int slice_index = lightmapper->get_bake_mesh_texture_slice(i); + data->add_user(np, uv_scale, slice_index, subindex); + } + + { + // create tetrahedrons + Vector points; + Vector sh; + points.resize(lightmapper->get_bake_probe_count()); + sh.resize(lightmapper->get_bake_probe_count() * 9); + for (int i = 0; i < lightmapper->get_bake_probe_count(); i++) { + points.write[i] = lightmapper->get_bake_probe_point(i); + Vector colors = lightmapper->get_bake_probe_sh(i); + ERR_CONTINUE(colors.size() != 9); + for (int j = 0; j < 9; j++) { + sh.write[i * 9 + j] = colors[j]; + } + } + + //Obtain solved simplices + + if (p_bake_step) { + p_bake_step(0.8, TTR("Generating Probe Volumes"), p_bake_userdata, true); + } + Vector solved_simplices = Delaunay3D::tetrahedralize(points); + + LocalVector bsp_simplices; + LocalVector bsp_planes; + LocalVector bsp_simplex_indices; + PackedInt32Array tetrahedrons; + + for (int i = 0; i < solved_simplices.size(); i++) { + //Prepare a special representation of the simplex, which uses a BSP Tree + BSPSimplex bsp_simplex; + for (int j = 0; j < 4; j++) { + bsp_simplex.vertices[j] = solved_simplices[i].points[j]; + } + for (int j = 0; j < 4; j++) { + static const int face_order[4][3] = { + { 0, 1, 2 }, + { 0, 2, 3 }, + { 0, 1, 3 }, + { 1, 2, 3 } + }; + Vector3 a = points[solved_simplices[i].points[face_order[j][0]]]; + Vector3 b = points[solved_simplices[i].points[face_order[j][1]]]; + Vector3 c = points[solved_simplices[i].points[face_order[j][2]]]; + + //store planes in an array, but ensure they are reused, to speed up processing + + Plane p(a, b, c); + int plane_index = -1; + for (uint32_t k = 0; k < bsp_planes.size(); k++) { + if (bsp_planes[k].is_equal_approx_any_side(p)) { + plane_index = k; + break; + } + } + + if (plane_index == -1) { + plane_index = bsp_planes.size(); + bsp_planes.push_back(p); + } + + bsp_simplex.planes[j] = plane_index; + + //also fill simplex array + tetrahedrons.push_back(solved_simplices[i].points[j]); + } + + bsp_simplex_indices.push_back(bsp_simplices.size()); + bsp_simplices.push_back(bsp_simplex); + } + +//#define DEBUG_SIMPLICES_AS_OBJ_FILE +#ifdef DEBUG_SIMPLICES_AS_OBJ_FILE + { + FileAccessRef f = FileAccess::open("res://bsp.obj", FileAccess::WRITE); + for (uint32_t i = 0; i < bsp_simplices.size(); i++) { + f->store_line("o Simplex" + itos(i)); + for (int j = 0; j < 4; j++) { + f->store_line(vformat("v %f %f %f", points[bsp_simplices[i].vertices[j]].x, points[bsp_simplices[i].vertices[j]].y, points[bsp_simplices[i].vertices[j]].z)); + } + static const int face_order[4][3] = { + { 1, 2, 3 }, + { 1, 3, 4 }, + { 1, 2, 4 }, + { 2, 3, 4 } + }; + + for (int j = 0; j < 4; j++) { + f->store_line(vformat("f %d %d %d", 4 * i + face_order[j][0], 4 * i + face_order[j][1], 4 * i + face_order[j][2])); + } + } + f->close(); + } +#endif + + LocalVector bsp_nodes; + LocalVector planes_tested; + planes_tested.resize(bsp_planes.size()); + for (uint32_t i = 0; i < planes_tested.size(); i++) { + planes_tested[i] = 0x7FFFFFFF; + } + + if (p_bake_step) { + p_bake_step(0.9, TTR("Generating Probe Acceleration Structures"), p_bake_userdata, true); + } + + _compute_bsp_tree(points, bsp_planes, planes_tested, bsp_simplices, bsp_simplex_indices, bsp_nodes); + + PackedInt32Array bsp_array; + bsp_array.resize(bsp_nodes.size() * 6); // six 32 bits values used for each BSP node + { + float *fptr = (float *)bsp_array.ptrw(); + int32_t *iptr = (int32_t *)bsp_array.ptrw(); + for (uint32_t i = 0; i < bsp_nodes.size(); i++) { + fptr[i * 6 + 0] = bsp_nodes[i].plane.normal.x; + fptr[i * 6 + 1] = bsp_nodes[i].plane.normal.y; + fptr[i * 6 + 2] = bsp_nodes[i].plane.normal.z; + fptr[i * 6 + 3] = bsp_nodes[i].plane.d; + iptr[i * 6 + 4] = bsp_nodes[i].over; + iptr[i * 6 + 5] = bsp_nodes[i].under; + } +//#define DEBUG_BSP_TREE +#ifdef DEBUG_BSP_TREE + FileAccessRef f = FileAccess::open("res://bsp.txt", FileAccess::WRITE); + for (uint32_t i = 0; i < bsp_nodes.size(); i++) { + f->store_line(itos(i) + " - plane: " + bsp_nodes[i].plane + " over: " + itos(bsp_nodes[i].over) + " under: " + itos(bsp_nodes[i].under)); + } +#endif + } + + /* Obtain the colors from the images, they will be re-created as cubemaps on the server, depending on the driver */ + + data->set_capture_data(bounds, interior, points, sh, tetrahedrons, bsp_array); + /* Compute a BSP tree of the simplices, so it's easy to find the exact one */ + } + + Error err = ResourceSaver::save(p_image_data_path, data); + data->set_path(p_image_data_path); + + if (err != OK) { + return BAKE_ERROR_CANT_CREATE_IMAGE; + } + + set_light_data(data); + + return BAKE_ERROR_OK; +} + +void LightmapGI::_notification(int p_what) { + if (p_what == NOTIFICATION_POST_ENTER_TREE) { + if (light_data.is_valid()) { + _assign_lightmaps(); + } + } + + if (p_what == NOTIFICATION_EXIT_TREE) { + if (light_data.is_valid()) { + _clear_lightmaps(); + } + } +} + +void LightmapGI::_assign_lightmaps() { + ERR_FAIL_COND(!light_data.is_valid()); + + for (int i = 0; i < light_data->get_user_count(); i++) { + Node *node = get_node(light_data->get_user_path(i)); + int instance_idx = light_data->get_user_sub_instance(i); + if (instance_idx >= 0) { + RID instance = node->call("get_bake_mesh_instance", instance_idx); + if (instance.is_valid()) { + RS::get_singleton()->instance_geometry_set_lightmap(instance, get_instance(), light_data->get_user_lightmap_uv_scale(i), light_data->get_user_lightmap_slice_index(i)); + } + } else { + VisualInstance3D *vi = Object::cast_to(node); + ERR_CONTINUE(!vi); + RS::get_singleton()->instance_geometry_set_lightmap(vi->get_instance(), get_instance(), light_data->get_user_lightmap_uv_scale(i), light_data->get_user_lightmap_slice_index(i)); + } + } +} + +void LightmapGI::_clear_lightmaps() { + ERR_FAIL_COND(!light_data.is_valid()); + for (int i = 0; i < light_data->get_user_count(); i++) { + Node *node = get_node(light_data->get_user_path(i)); + int instance_idx = light_data->get_user_sub_instance(i); + if (instance_idx >= 0) { + RID instance = node->call("get_bake_mesh_instance", instance_idx); + if (instance.is_valid()) { + RS::get_singleton()->instance_geometry_set_lightmap(instance, RID(), Rect2(), 0); + } + } else { + VisualInstance3D *vi = Object::cast_to(node); + ERR_CONTINUE(!vi); + RS::get_singleton()->instance_geometry_set_lightmap(vi->get_instance(), RID(), Rect2(), 0); + } + } +} + +void LightmapGI::set_light_data(const Ref &p_data) { + if (light_data.is_valid()) { + if (is_inside_tree()) { + _clear_lightmaps(); + } + set_base(RID()); + } + light_data = p_data; + + if (light_data.is_valid()) { + set_base(light_data->get_rid()); + if (is_inside_tree()) { + _assign_lightmaps(); + } + } + + update_gizmo(); +} + +Ref LightmapGI::get_light_data() const { + return light_data; +} + +void LightmapGI::set_bake_quality(BakeQuality p_quality) { + bake_quality = p_quality; +} + +LightmapGI::BakeQuality LightmapGI::get_bake_quality() const { + return bake_quality; +} + +AABB LightmapGI::get_aabb() const { + return AABB(); +} + +Vector LightmapGI::get_faces(uint32_t p_usage_flags) const { + return Vector(); +} + +void LightmapGI::set_use_denoiser(bool p_enable) { + use_denoiser = p_enable; +} + +bool LightmapGI::is_using_denoiser() const { + return use_denoiser; +} + +void LightmapGI::set_directional(bool p_enable) { + directional = p_enable; +} + +bool LightmapGI::is_directional() const { + return directional; +} + +void LightmapGI::set_interior(bool p_enable) { + interior = p_enable; +} + +bool LightmapGI::is_interior() const { + return interior; +} + +void LightmapGI::set_environment_mode(EnvironmentMode p_mode) { + environment_mode = p_mode; + notify_property_list_changed(); +} + +LightmapGI::EnvironmentMode LightmapGI::get_environment_mode() const { + return environment_mode; +} + +void LightmapGI::set_environment_custom_sky(const Ref &p_sky) { + environment_custom_sky = p_sky; +} + +Ref LightmapGI::get_environment_custom_sky() const { + return environment_custom_sky; +} + +void LightmapGI::set_environment_custom_color(const Color &p_color) { + environment_custom_color = p_color; +} + +Color LightmapGI::get_environment_custom_color() const { + return environment_custom_color; +} + +void LightmapGI::set_environment_custom_energy(float p_energy) { + environment_custom_energy = p_energy; +} + +float LightmapGI::get_environment_custom_energy() const { + return environment_custom_energy; +} + +void LightmapGI::set_bounces(int p_bounces) { + ERR_FAIL_COND(p_bounces < 0 || p_bounces > 16); + bounces = p_bounces; +} + +int LightmapGI::get_bounces() const { + return bounces; +} + +void LightmapGI::set_bias(float p_bias) { + ERR_FAIL_COND(p_bias < 0.00001); + bias = p_bias; +} + +float LightmapGI::get_bias() const { + return bias; +} + +void LightmapGI::set_max_texture_size(int p_size) { + ERR_FAIL_COND(p_size < 2048); + max_texture_size = p_size; +} + +int LightmapGI::get_max_texture_size() const { + return max_texture_size; +} + +void LightmapGI::set_generate_probes(GenerateProbes p_generate_probes) { + gen_probes = p_generate_probes; +} + +LightmapGI::GenerateProbes LightmapGI::get_generate_probes() const { + return gen_probes; +} + +void LightmapGI::_validate_property(PropertyInfo &property) const { + if (property.name == "environment_custom_sky" && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) { + property.usage = 0; + } + if (property.name == "environment_custom_color" && environment_mode != ENVIRONMENT_MODE_CUSTOM_COLOR) { + property.usage = 0; + } + if (property.name == "environment_custom_energy" && environment_mode != ENVIRONMENT_MODE_CUSTOM_COLOR && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) { + property.usage = 0; + } +} + +void LightmapGI::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_light_data", "data"), &LightmapGI::set_light_data); + ClassDB::bind_method(D_METHOD("get_light_data"), &LightmapGI::get_light_data); + + ClassDB::bind_method(D_METHOD("set_bake_quality", "bake_quality"), &LightmapGI::set_bake_quality); + ClassDB::bind_method(D_METHOD("get_bake_quality"), &LightmapGI::get_bake_quality); + + ClassDB::bind_method(D_METHOD("set_bounces", "bounces"), &LightmapGI::set_bounces); + ClassDB::bind_method(D_METHOD("get_bounces"), &LightmapGI::get_bounces); + + ClassDB::bind_method(D_METHOD("set_generate_probes", "subdivision"), &LightmapGI::set_generate_probes); + ClassDB::bind_method(D_METHOD("get_generate_probes"), &LightmapGI::get_generate_probes); + + ClassDB::bind_method(D_METHOD("set_bias", "bias"), &LightmapGI::set_bias); + ClassDB::bind_method(D_METHOD("get_bias"), &LightmapGI::get_bias); + + ClassDB::bind_method(D_METHOD("set_environment_mode", "mode"), &LightmapGI::set_environment_mode); + ClassDB::bind_method(D_METHOD("get_environment_mode"), &LightmapGI::get_environment_mode); + + ClassDB::bind_method(D_METHOD("set_environment_custom_sky", "sky"), &LightmapGI::set_environment_custom_sky); + ClassDB::bind_method(D_METHOD("get_environment_custom_sky"), &LightmapGI::get_environment_custom_sky); + + ClassDB::bind_method(D_METHOD("set_environment_custom_color", "color"), &LightmapGI::set_environment_custom_color); + ClassDB::bind_method(D_METHOD("get_environment_custom_color"), &LightmapGI::get_environment_custom_color); + + ClassDB::bind_method(D_METHOD("set_environment_custom_energy", "energy"), &LightmapGI::set_environment_custom_energy); + ClassDB::bind_method(D_METHOD("get_environment_custom_energy"), &LightmapGI::get_environment_custom_energy); + + ClassDB::bind_method(D_METHOD("set_max_texture_size", "max_texture_size"), &LightmapGI::set_max_texture_size); + ClassDB::bind_method(D_METHOD("get_max_texture_size"), &LightmapGI::get_max_texture_size); + + ClassDB::bind_method(D_METHOD("set_use_denoiser", "use_denoiser"), &LightmapGI::set_use_denoiser); + ClassDB::bind_method(D_METHOD("is_using_denoiser"), &LightmapGI::is_using_denoiser); + + ClassDB::bind_method(D_METHOD("set_interior", "enable"), &LightmapGI::set_interior); + ClassDB::bind_method(D_METHOD("is_interior"), &LightmapGI::is_interior); + + ClassDB::bind_method(D_METHOD("set_directional", "directional"), &LightmapGI::set_directional); + ClassDB::bind_method(D_METHOD("is_directional"), &LightmapGI::is_directional); + + // ClassDB::bind_method(D_METHOD("bake", "from_node"), &LightmapGI::bake, DEFVAL(Variant())); + + ADD_GROUP("Tweaks", ""); + ADD_PROPERTY(PropertyInfo(Variant::INT, "quality", PROPERTY_HINT_ENUM, "Low,Medium,High,Ultra"), "set_bake_quality", "get_bake_quality"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "bounces", PROPERTY_HINT_RANGE, "0,16,1"), "set_bounces", "get_bounces"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "directional"), "set_directional", "is_directional"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_denoiser"), "set_use_denoiser", "is_using_denoiser"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0.00001,0.1,0.00001,or_greater"), "set_bias", "get_bias"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_texture_size"), "set_max_texture_size", "get_max_texture_size"); + ADD_GROUP("Environment", "environment_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "environment_mode", PROPERTY_HINT_ENUM, "Disabled,Scene,Custom Sky,Custom Color"), "set_environment_mode", "get_environment_mode"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment_custom_sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_environment_custom_sky", "get_environment_custom_sky"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "environment_custom_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_environment_custom_color", "get_environment_custom_color"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "environment_custom_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_environment_custom_energy", "get_environment_custom_energy"); + ADD_GROUP("Gen Probes", "generate_probes_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "generate_probes_subdiv", PROPERTY_HINT_ENUM, "Disabled,4,8,16,32"), "set_generate_probes", "get_generate_probes"); + ADD_GROUP("Data", ""); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_data", PROPERTY_HINT_RESOURCE_TYPE, "LightmapGIData"), "set_light_data", "get_light_data"); + + BIND_ENUM_CONSTANT(BAKE_QUALITY_LOW); + BIND_ENUM_CONSTANT(BAKE_QUALITY_MEDIUM); + BIND_ENUM_CONSTANT(BAKE_QUALITY_HIGH); + BIND_ENUM_CONSTANT(BAKE_QUALITY_ULTRA); + + BIND_ENUM_CONSTANT(GENERATE_PROBES_DISABLED); + BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_4); + BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_8); + BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_16); + BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_32); + + BIND_ENUM_CONSTANT(BAKE_ERROR_OK); + BIND_ENUM_CONSTANT(BAKE_ERROR_NO_LIGHTMAPPER); + BIND_ENUM_CONSTANT(BAKE_ERROR_NO_SAVE_PATH); + BIND_ENUM_CONSTANT(BAKE_ERROR_NO_MESHES); + BIND_ENUM_CONSTANT(BAKE_ERROR_MESHES_INVALID); + BIND_ENUM_CONSTANT(BAKE_ERROR_CANT_CREATE_IMAGE); + BIND_ENUM_CONSTANT(BAKE_ERROR_USER_ABORTED); + + BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_DISABLED); + BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_SCENE); + BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_CUSTOM_SKY); + BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_CUSTOM_COLOR); +} + +LightmapGI::LightmapGI() { +} diff --git a/scene/3d/lightmap_gi.h b/scene/3d/lightmap_gi.h new file mode 100644 index 0000000000..8a54512383 --- /dev/null +++ b/scene/3d/lightmap_gi.h @@ -0,0 +1,284 @@ +/*************************************************************************/ +/* lightmap_gi.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef LIGHTMAP_GI_H +#define LIGHTMAP_GI_H + +#include "core/templates/local_vector.h" +#include "scene/3d/light_3d.h" +#include "scene/3d/lightmapper.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/multimesh_instance_3d.h" +#include "scene/3d/visual_instance_3d.h" +#include "scene/resources/sky.h" + +class LightmapGIData : public Resource { + GDCLASS(LightmapGIData, Resource); + RES_BASE_EXTENSION("lmbake") + + Ref light_texture; + + bool uses_spherical_harmonics = false; + bool interior = false; + + RID lightmap; + AABB bounds; + + struct User { + NodePath path; + int32_t sub_instance = 0; + Rect2 uv_scale; + int slice_index = 0; + }; + + Vector users; + + void _set_user_data(const Array &p_data); + Array _get_user_data() const; + void _set_probe_data(const Dictionary &p_data); + Dictionary _get_probe_data() const; + +protected: + static void _bind_methods(); + +public: + void add_user(const NodePath &p_path, const Rect2 &p_uv_scale, int p_slice_index, int32_t p_sub_instance = -1); + int get_user_count() const; + NodePath get_user_path(int p_user) const; + int32_t get_user_sub_instance(int p_user) const; + Rect2 get_user_lightmap_uv_scale(int p_user) const; + int get_user_lightmap_slice_index(int p_user) const; + void clear_users(); + + void set_light_texture(const Ref &p_light_texture); + Ref get_light_texture() const; + + void set_uses_spherical_harmonics(bool p_enable); + bool is_using_spherical_harmonics() const; + + bool is_interior() const; + + void set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree); + PackedVector3Array get_capture_points() const; + PackedColorArray get_capture_sh() const; + PackedInt32Array get_capture_tetrahedra() const; + PackedInt32Array get_capture_bsp_tree() const; + AABB get_capture_bounds() const; + + void clear(); + + virtual RID get_rid() const override; + LightmapGIData(); + ~LightmapGIData(); +}; + +class LightmapGI : public VisualInstance3D { + GDCLASS(LightmapGI, VisualInstance3D); + +public: + enum BakeQuality { + BAKE_QUALITY_LOW, + BAKE_QUALITY_MEDIUM, + BAKE_QUALITY_HIGH, + BAKE_QUALITY_ULTRA, + }; + + enum GenerateProbes { + GENERATE_PROBES_DISABLED, + GENERATE_PROBES_SUBDIV_4, + GENERATE_PROBES_SUBDIV_8, + GENERATE_PROBES_SUBDIV_16, + GENERATE_PROBES_SUBDIV_32, + }; + + enum BakeError { + BAKE_ERROR_OK, + BAKE_ERROR_NO_LIGHTMAPPER, + BAKE_ERROR_NO_SAVE_PATH, + BAKE_ERROR_NO_MESHES, + BAKE_ERROR_MESHES_INVALID, + BAKE_ERROR_CANT_CREATE_IMAGE, + BAKE_ERROR_USER_ABORTED, + }; + + enum EnvironmentMode { + ENVIRONMENT_MODE_DISABLED, + ENVIRONMENT_MODE_SCENE, + ENVIRONMENT_MODE_CUSTOM_SKY, + ENVIRONMENT_MODE_CUSTOM_COLOR, + }; + +private: + BakeQuality bake_quality = BAKE_QUALITY_MEDIUM; + bool use_denoiser = true; + int bounces = 1; + float bias = 0.0005; + int max_texture_size = 16384; + bool interior = false; + EnvironmentMode environment_mode = ENVIRONMENT_MODE_DISABLED; + Ref environment_custom_sky; + Color environment_custom_color = Color(0.2, 0.7, 1.0); + float environment_custom_energy = 1.0; + bool directional = false; + GenerateProbes gen_probes = GENERATE_PROBES_DISABLED; + + Ref light_data; + + struct LightsFound { + Transform3D xform; + Light3D *light = nullptr; + }; + + struct MeshesFound { + Transform3D xform; + NodePath node_path; + int32_t subindex = 0; + Ref mesh; + int32_t lightmap_scale = 0; + Vector> overrides; + }; + + void _find_meshes_and_lights(Node *p_at_node, Vector &meshes, Vector &lights, Vector &probes); + + void _assign_lightmaps(); + void _clear_lightmaps(); + + struct BakeTimeData { + String text; + int pass = 0; + uint64_t last_step = 0; + }; + + struct BSPSimplex { + int vertices[4] = {}; + int planes[4] = {}; + }; + + struct BSPNode { + static const int32_t EMPTY_LEAF = INT32_MIN; + Plane plane; + int32_t over = EMPTY_LEAF; + int32_t under = EMPTY_LEAF; + }; + + int _bsp_get_simplex_side(const Vector &p_points, const LocalVector &p_simplices, const Plane &p_plane, uint32_t p_simplex) const; + int32_t _compute_bsp_tree(const Vector &p_points, const LocalVector &p_planes, LocalVector &planes_tested, const LocalVector &p_simplices, const LocalVector &p_simplex_indices, LocalVector &bsp_nodes); + + struct BakeStepUD { + Lightmapper::BakeStepFunc func; + void *ud = nullptr; + float from_percent = 0.0; + float to_percent = 0.0; + }; + + static bool _lightmap_bake_step_function(float p_completion, const String &p_text, void *ud, bool p_refresh); + + struct GenProbesOctree { + Vector3i offset; + uint32_t size = 0; + GenProbesOctree *children[8] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; + ~GenProbesOctree() { + for (int i = 0; i < 8; i++) { + if (children[i] != nullptr) { + memdelete(children[i]); + } + } + } + }; + + struct Vector3iHash { + _FORCE_INLINE_ static uint32_t hash(const Vector3i &p_vtx) { + uint32_t h = hash_djb2_one_32(p_vtx.x); + h = hash_djb2_one_32(p_vtx.y, h); + return hash_djb2_one_32(p_vtx.z, h); + } + }; + + void _plot_triangle_into_octree(GenProbesOctree *p_cell, float p_cell_size, const Vector3 *p_triangle); + void _gen_new_positions_from_octree(const GenProbesOctree *p_cell, float p_cell_size, const Vector &probe_positions, LocalVector &new_probe_positions, HashMap &positions_used, const AABB &p_bounds); + +protected: + void _validate_property(PropertyInfo &property) const override; + static void _bind_methods(); + void _notification(int p_what); + +public: + void set_light_data(const Ref &p_data); + Ref get_light_data() const; + + void set_bake_quality(BakeQuality p_quality); + BakeQuality get_bake_quality() const; + + void set_use_denoiser(bool p_enable); + bool is_using_denoiser() const; + + void set_directional(bool p_enable); + bool is_directional() const; + + void set_interior(bool p_interior); + bool is_interior() const; + + void set_environment_mode(EnvironmentMode p_mode); + EnvironmentMode get_environment_mode() const; + + void set_environment_custom_sky(const Ref &p_sky); + Ref get_environment_custom_sky() const; + + void set_environment_custom_color(const Color &p_color); + Color get_environment_custom_color() const; + + void set_environment_custom_energy(float p_energy); + float get_environment_custom_energy() const; + + void set_bounces(int p_bounces); + int get_bounces() const; + + void set_bias(float p_bias); + float get_bias() const; + + void set_max_texture_size(int p_size); + int get_max_texture_size() const; + + void set_generate_probes(GenerateProbes p_generate_probes); + GenerateProbes get_generate_probes() const; + + AABB get_aabb() const override; + Vector get_faces(uint32_t p_usage_flags) const override; + + BakeError bake(Node *p_from_node, String p_image_data_path = "", Lightmapper::BakeStepFunc p_bake_step = nullptr, void *p_bake_userdata = nullptr); + LightmapGI(); +}; + +VARIANT_ENUM_CAST(LightmapGI::BakeQuality); +VARIANT_ENUM_CAST(LightmapGI::GenerateProbes); +VARIANT_ENUM_CAST(LightmapGI::BakeError); +VARIANT_ENUM_CAST(LightmapGI::EnvironmentMode); + +#endif // BAKED_LIGHTMAP_H diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp new file mode 100644 index 0000000000..e00be9204c --- /dev/null +++ b/scene/3d/voxel_gi.cpp @@ -0,0 +1,549 @@ +/*************************************************************************/ +/* voxel_gi.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "voxel_gi.h" + +#include "core/os/os.h" + +#include "mesh_instance_3d.h" +#include "voxelizer.h" + +void VoxelGIData::_set_data(const Dictionary &p_data) { + ERR_FAIL_COND(!p_data.has("bounds")); + ERR_FAIL_COND(!p_data.has("octree_size")); + ERR_FAIL_COND(!p_data.has("octree_cells")); + ERR_FAIL_COND(!p_data.has("octree_data")); + ERR_FAIL_COND(!p_data.has("octree_df") && !p_data.has("octree_df_png")); + ERR_FAIL_COND(!p_data.has("level_counts")); + ERR_FAIL_COND(!p_data.has("to_cell_xform")); + + AABB bounds = p_data["bounds"]; + Vector3 octree_size = p_data["octree_size"]; + Vector octree_cells = p_data["octree_cells"]; + Vector octree_data = p_data["octree_data"]; + + Vector octree_df; + if (p_data.has("octree_df")) { + octree_df = p_data["octree_df"]; + } else if (p_data.has("octree_df_png")) { + Vector octree_df_png = p_data["octree_df_png"]; + Ref img; + img.instance(); + Error err = img->load_png_from_buffer(octree_df_png); + ERR_FAIL_COND(err != OK); + ERR_FAIL_COND(img->get_format() != Image::FORMAT_L8); + octree_df = img->get_data(); + } + Vector octree_levels = p_data["level_counts"]; + Transform3D to_cell_xform = p_data["to_cell_xform"]; + + allocate(to_cell_xform, bounds, octree_size, octree_cells, octree_data, octree_df, octree_levels); +} + +Dictionary VoxelGIData::_get_data() const { + Dictionary d; + d["bounds"] = get_bounds(); + Vector3i otsize = get_octree_size(); + d["octree_size"] = Vector3(otsize); + d["octree_cells"] = get_octree_cells(); + d["octree_data"] = get_data_cells(); + if (otsize != Vector3i()) { + Ref img; + img.instance(); + img->create(otsize.x * otsize.y, otsize.z, false, Image::FORMAT_L8, get_distance_field()); + Vector df_png = img->save_png_to_buffer(); + ERR_FAIL_COND_V(df_png.size() == 0, Dictionary()); + d["octree_df_png"] = df_png; + } else { + d["octree_df"] = Vector(); + } + + d["level_counts"] = get_level_counts(); + d["to_cell_xform"] = get_to_cell_xform(); + return d; +} + +void VoxelGIData::allocate(const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3 &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts) { + RS::get_singleton()->voxel_gi_allocate_data(probe, p_to_cell_xform, p_aabb, p_octree_size, p_octree_cells, p_data_cells, p_distance_field, p_level_counts); + bounds = p_aabb; + to_cell_xform = p_to_cell_xform; + octree_size = p_octree_size; +} + +AABB VoxelGIData::get_bounds() const { + return bounds; +} + +Vector3 VoxelGIData::get_octree_size() const { + return octree_size; +} + +Vector VoxelGIData::get_octree_cells() const { + return RS::get_singleton()->voxel_gi_get_octree_cells(probe); +} + +Vector VoxelGIData::get_data_cells() const { + return RS::get_singleton()->voxel_gi_get_data_cells(probe); +} + +Vector VoxelGIData::get_distance_field() const { + return RS::get_singleton()->voxel_gi_get_distance_field(probe); +} + +Vector VoxelGIData::get_level_counts() const { + return RS::get_singleton()->voxel_gi_get_level_counts(probe); +} + +Transform3D VoxelGIData::get_to_cell_xform() const { + return to_cell_xform; +} + +void VoxelGIData::set_dynamic_range(float p_range) { + RS::get_singleton()->voxel_gi_set_dynamic_range(probe, p_range); + dynamic_range = p_range; +} + +float VoxelGIData::get_dynamic_range() const { + return dynamic_range; +} + +void VoxelGIData::set_propagation(float p_propagation) { + RS::get_singleton()->voxel_gi_set_propagation(probe, p_propagation); + propagation = p_propagation; +} + +float VoxelGIData::get_propagation() const { + return propagation; +} + +void VoxelGIData::set_anisotropy_strength(float p_anisotropy_strength) { + RS::get_singleton()->voxel_gi_set_anisotropy_strength(probe, p_anisotropy_strength); + anisotropy_strength = p_anisotropy_strength; +} + +float VoxelGIData::get_anisotropy_strength() const { + return anisotropy_strength; +} + +void VoxelGIData::set_energy(float p_energy) { + RS::get_singleton()->voxel_gi_set_energy(probe, p_energy); + energy = p_energy; +} + +float VoxelGIData::get_energy() const { + return energy; +} + +void VoxelGIData::set_ao(float p_ao) { + RS::get_singleton()->voxel_gi_set_ao(probe, p_ao); + ao = p_ao; +} + +float VoxelGIData::get_ao() const { + return ao; +} + +void VoxelGIData::set_ao_size(float p_ao_size) { + RS::get_singleton()->voxel_gi_set_ao_size(probe, p_ao_size); + ao_size = p_ao_size; +} + +float VoxelGIData::get_ao_size() const { + return ao_size; +} + +void VoxelGIData::set_bias(float p_bias) { + RS::get_singleton()->voxel_gi_set_bias(probe, p_bias); + bias = p_bias; +} + +float VoxelGIData::get_bias() const { + return bias; +} + +void VoxelGIData::set_normal_bias(float p_normal_bias) { + RS::get_singleton()->voxel_gi_set_normal_bias(probe, p_normal_bias); + normal_bias = p_normal_bias; +} + +float VoxelGIData::get_normal_bias() const { + return normal_bias; +} + +void VoxelGIData::set_interior(bool p_enable) { + RS::get_singleton()->voxel_gi_set_interior(probe, p_enable); + interior = p_enable; +} + +bool VoxelGIData::is_interior() const { + return interior; +} + +void VoxelGIData::set_use_two_bounces(bool p_enable) { + RS::get_singleton()->voxel_gi_set_use_two_bounces(probe, p_enable); + use_two_bounces = p_enable; +} + +bool VoxelGIData::is_using_two_bounces() const { + return use_two_bounces; +} + +RID VoxelGIData::get_rid() const { + return probe; +} + +void VoxelGIData::_validate_property(PropertyInfo &property) const { + if (property.name == "anisotropy_strength") { + bool anisotropy_enabled = ProjectSettings::get_singleton()->get("rendering/global_illumination/voxel_gi/anisotropic"); + if (!anisotropy_enabled) { + property.usage = PROPERTY_USAGE_NOEDITOR; + } + } +} + +void VoxelGIData::_bind_methods() { + ClassDB::bind_method(D_METHOD("allocate", "to_cell_xform", "aabb", "octree_size", "octree_cells", "data_cells", "distance_field", "level_counts"), &VoxelGIData::allocate); + + ClassDB::bind_method(D_METHOD("get_bounds"), &VoxelGIData::get_bounds); + ClassDB::bind_method(D_METHOD("get_octree_size"), &VoxelGIData::get_octree_size); + ClassDB::bind_method(D_METHOD("get_to_cell_xform"), &VoxelGIData::get_to_cell_xform); + ClassDB::bind_method(D_METHOD("get_octree_cells"), &VoxelGIData::get_octree_cells); + ClassDB::bind_method(D_METHOD("get_data_cells"), &VoxelGIData::get_data_cells); + ClassDB::bind_method(D_METHOD("get_level_counts"), &VoxelGIData::get_level_counts); + + ClassDB::bind_method(D_METHOD("set_dynamic_range", "dynamic_range"), &VoxelGIData::set_dynamic_range); + ClassDB::bind_method(D_METHOD("get_dynamic_range"), &VoxelGIData::get_dynamic_range); + + ClassDB::bind_method(D_METHOD("set_energy", "energy"), &VoxelGIData::set_energy); + ClassDB::bind_method(D_METHOD("get_energy"), &VoxelGIData::get_energy); + + ClassDB::bind_method(D_METHOD("set_bias", "bias"), &VoxelGIData::set_bias); + ClassDB::bind_method(D_METHOD("get_bias"), &VoxelGIData::get_bias); + + ClassDB::bind_method(D_METHOD("set_normal_bias", "bias"), &VoxelGIData::set_normal_bias); + ClassDB::bind_method(D_METHOD("get_normal_bias"), &VoxelGIData::get_normal_bias); + + ClassDB::bind_method(D_METHOD("set_propagation", "propagation"), &VoxelGIData::set_propagation); + ClassDB::bind_method(D_METHOD("get_propagation"), &VoxelGIData::get_propagation); + + ClassDB::bind_method(D_METHOD("set_anisotropy_strength", "strength"), &VoxelGIData::set_anisotropy_strength); + ClassDB::bind_method(D_METHOD("get_anisotropy_strength"), &VoxelGIData::get_anisotropy_strength); + + ClassDB::bind_method(D_METHOD("set_ao", "ao"), &VoxelGIData::set_ao); + ClassDB::bind_method(D_METHOD("get_ao"), &VoxelGIData::get_ao); + + ClassDB::bind_method(D_METHOD("set_ao_size", "strength"), &VoxelGIData::set_ao_size); + ClassDB::bind_method(D_METHOD("get_ao_size"), &VoxelGIData::get_ao_size); + + ClassDB::bind_method(D_METHOD("set_interior", "interior"), &VoxelGIData::set_interior); + ClassDB::bind_method(D_METHOD("is_interior"), &VoxelGIData::is_interior); + + ClassDB::bind_method(D_METHOD("set_use_two_bounces", "enable"), &VoxelGIData::set_use_two_bounces); + ClassDB::bind_method(D_METHOD("is_using_two_bounces"), &VoxelGIData::is_using_two_bounces); + + ClassDB::bind_method(D_METHOD("_set_data", "data"), &VoxelGIData::_set_data); + ClassDB::bind_method(D_METHOD("_get_data"), &VoxelGIData::_get_data); + + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "dynamic_range", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_dynamic_range", "get_dynamic_range"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_energy", "get_energy"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_bias", "get_bias"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "normal_bias", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_normal_bias", "get_normal_bias"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "propagation", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_propagation", "get_propagation"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "anisotropy_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_anisotropy_strength", "get_anisotropy_strength"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ao", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ao", "get_ao"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ao_size", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ao_size", "get_ao_size"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_two_bounces"), "set_use_two_bounces", "is_using_two_bounces"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior"); +} + +VoxelGIData::VoxelGIData() { + probe = RS::get_singleton()->voxel_gi_create(); +} + +VoxelGIData::~VoxelGIData() { + RS::get_singleton()->free(probe); +} + +////////////////////// +////////////////////// + +void VoxelGI::set_probe_data(const Ref &p_data) { + if (p_data.is_valid()) { + RS::get_singleton()->instance_set_base(get_instance(), p_data->get_rid()); + } else { + RS::get_singleton()->instance_set_base(get_instance(), RID()); + } + + probe_data = p_data; +} + +Ref VoxelGI::get_probe_data() const { + return probe_data; +} + +void VoxelGI::set_subdiv(Subdiv p_subdiv) { + ERR_FAIL_INDEX(p_subdiv, SUBDIV_MAX); + subdiv = p_subdiv; + update_gizmo(); +} + +VoxelGI::Subdiv VoxelGI::get_subdiv() const { + return subdiv; +} + +void VoxelGI::set_extents(const Vector3 &p_extents) { + extents = p_extents; + update_gizmo(); +} + +Vector3 VoxelGI::get_extents() const { + return extents; +} + +void VoxelGI::_find_meshes(Node *p_at_node, List &plot_meshes) { + MeshInstance3D *mi = Object::cast_to(p_at_node); + if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_BAKED && mi->is_visible_in_tree()) { + Ref mesh = mi->get_mesh(); + if (mesh.is_valid()) { + AABB aabb = mesh->get_aabb(); + + Transform3D xf = get_global_transform().affine_inverse() * mi->get_global_transform(); + + if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) { + PlotMesh pm; + pm.local_xform = xf; + pm.mesh = mesh; + for (int i = 0; i < mesh->get_surface_count(); i++) { + pm.instance_materials.push_back(mi->get_surface_override_material(i)); + } + pm.override_material = mi->get_material_override(); + plot_meshes.push_back(pm); + } + } + } + + Node3D *s = Object::cast_to(p_at_node); + if (s) { + if (s->is_visible_in_tree()) { + Array meshes = p_at_node->call("get_meshes"); + for (int i = 0; i < meshes.size(); i += 2) { + Transform3D mxf = meshes[i]; + Ref mesh = meshes[i + 1]; + if (!mesh.is_valid()) { + continue; + } + + AABB aabb = mesh->get_aabb(); + + Transform3D xf = get_global_transform().affine_inverse() * (s->get_global_transform() * mxf); + + if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) { + PlotMesh pm; + pm.local_xform = xf; + pm.mesh = mesh; + plot_meshes.push_back(pm); + } + } + } + } + + for (int i = 0; i < p_at_node->get_child_count(); i++) { + Node *child = p_at_node->get_child(i); + _find_meshes(child, plot_meshes); + } +} + +VoxelGI::BakeBeginFunc VoxelGI::bake_begin_function = nullptr; +VoxelGI::BakeStepFunc VoxelGI::bake_step_function = nullptr; +VoxelGI::BakeEndFunc VoxelGI::bake_end_function = nullptr; + +Vector3i VoxelGI::get_estimated_cell_size() const { + static const int subdiv_value[SUBDIV_MAX] = { 6, 7, 8, 9 }; + int cell_subdiv = subdiv_value[subdiv]; + int axis_cell_size[3]; + AABB bounds = AABB(-extents, extents * 2.0); + int longest_axis = bounds.get_longest_axis_index(); + axis_cell_size[longest_axis] = 1 << cell_subdiv; + + for (int i = 0; i < 3; i++) { + if (i == longest_axis) { + continue; + } + + axis_cell_size[i] = axis_cell_size[longest_axis]; + float axis_size = bounds.size[longest_axis]; + + //shrink until fit subdiv + while (axis_size / 2.0 >= bounds.size[i]) { + axis_size /= 2.0; + axis_cell_size[i] >>= 1; + } + } + + return Vector3i(axis_cell_size[0], axis_cell_size[1], axis_cell_size[2]); +} + +void VoxelGI::bake(Node *p_from_node, bool p_create_visual_debug) { + static const int subdiv_value[SUBDIV_MAX] = { 6, 7, 8, 9 }; + + p_from_node = p_from_node ? p_from_node : get_parent(); + ERR_FAIL_NULL(p_from_node); + + Voxelizer baker; + + baker.begin_bake(subdiv_value[subdiv], AABB(-extents, extents * 2.0)); + + List mesh_list; + + _find_meshes(p_from_node, mesh_list); + + if (bake_begin_function) { + bake_begin_function(mesh_list.size() + 1); + } + + int pmc = 0; + + for (List::Element *E = mesh_list.front(); E; E = E->next()) { + if (bake_step_function) { + bake_step_function(pmc, RTR("Plotting Meshes") + " " + itos(pmc) + "/" + itos(mesh_list.size())); + } + + pmc++; + + baker.plot_mesh(E->get().local_xform, E->get().mesh, E->get().instance_materials, E->get().override_material); + } + if (bake_step_function) { + bake_step_function(pmc++, RTR("Finishing Plot")); + } + + baker.end_bake(); + + //create the data for visual server + + if (p_create_visual_debug) { + MultiMeshInstance3D *mmi = memnew(MultiMeshInstance3D); + mmi->set_multimesh(baker.create_debug_multimesh()); + add_child(mmi); +#ifdef TOOLS_ENABLED + if (is_inside_tree() && get_tree()->get_edited_scene_root() == this) { + mmi->set_owner(this); + } else { + mmi->set_owner(get_owner()); + } +#else + mmi->set_owner(get_owner()); +#endif + + } else { + Ref probe_data = get_probe_data(); + + if (probe_data.is_null()) { + probe_data.instance(); + } + + if (bake_step_function) { + bake_step_function(pmc++, RTR("Generating Distance Field")); + } + + Vector df = baker.get_sdf_3d_image(); + + probe_data->allocate(baker.get_to_cell_space_xform(), AABB(-extents, extents * 2.0), baker.get_voxel_gi_octree_size(), baker.get_voxel_gi_octree_cells(), baker.get_voxel_gi_data_cells(), df, baker.get_voxel_gi_level_cell_count()); + + set_probe_data(probe_data); +#ifdef TOOLS_ENABLED + probe_data->set_edited(true); //so it gets saved +#endif + } + + if (bake_end_function) { + bake_end_function(); + } + + notify_property_list_changed(); //bake property may have changed +} + +void VoxelGI::_debug_bake() { + bake(nullptr, true); +} + +AABB VoxelGI::get_aabb() const { + return AABB(-extents, extents * 2); +} + +Vector VoxelGI::get_faces(uint32_t p_usage_flags) const { + return Vector(); +} + +TypedArray VoxelGI::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); + + if (RenderingServer::get_singleton()->is_low_end()) { + warnings.push_back(TTR("VoxelGIs are not supported by the GLES2 video driver.\nUse a LightmapGI instead.")); + } else if (probe_data.is_null()) { + warnings.push_back(TTR("No VoxelGI data set, so this node is disabled. Bake static objects to enable GI.")); + } + return warnings; +} + +void VoxelGI::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_probe_data", "data"), &VoxelGI::set_probe_data); + ClassDB::bind_method(D_METHOD("get_probe_data"), &VoxelGI::get_probe_data); + + ClassDB::bind_method(D_METHOD("set_subdiv", "subdiv"), &VoxelGI::set_subdiv); + ClassDB::bind_method(D_METHOD("get_subdiv"), &VoxelGI::get_subdiv); + + ClassDB::bind_method(D_METHOD("set_extents", "extents"), &VoxelGI::set_extents); + ClassDB::bind_method(D_METHOD("get_extents"), &VoxelGI::get_extents); + + ClassDB::bind_method(D_METHOD("bake", "from_node", "create_visual_debug"), &VoxelGI::bake, DEFVAL(Variant()), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("debug_bake"), &VoxelGI::_debug_bake); + ClassDB::set_method_flags(get_class_static(), _scs_create("debug_bake"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "subdiv", PROPERTY_HINT_ENUM, "64,128,256,512"), "set_subdiv", "get_subdiv"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "data", PROPERTY_HINT_RESOURCE_TYPE, "VoxelGIData", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE), "set_probe_data", "get_probe_data"); + + BIND_ENUM_CONSTANT(SUBDIV_64); + BIND_ENUM_CONSTANT(SUBDIV_128); + BIND_ENUM_CONSTANT(SUBDIV_256); + BIND_ENUM_CONSTANT(SUBDIV_512); + BIND_ENUM_CONSTANT(SUBDIV_MAX); +} + +VoxelGI::VoxelGI() { + voxel_gi = RS::get_singleton()->voxel_gi_create(); + set_disable_scale(true); +} + +VoxelGI::~VoxelGI() { + RS::get_singleton()->free(voxel_gi); +} diff --git a/scene/3d/voxel_gi.h b/scene/3d/voxel_gi.h new file mode 100644 index 0000000000..5b9ee28b33 --- /dev/null +++ b/scene/3d/voxel_gi.h @@ -0,0 +1,176 @@ +/*************************************************************************/ +/* voxel_gi.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef VOXEL_GI_H +#define VOXEL_GI_H + +#include "multimesh_instance_3d.h" +#include "scene/3d/visual_instance_3d.h" + +class VoxelGIData : public Resource { + GDCLASS(VoxelGIData, Resource); + + RID probe; + + void _set_data(const Dictionary &p_data); + Dictionary _get_data() const; + + Transform3D to_cell_xform; + AABB bounds; + Vector3 octree_size; + + float dynamic_range = 4.0; + float energy = 1.0; + float bias = 1.5; + float normal_bias = 0.0; + float propagation = 0.7; + float anisotropy_strength = 0.5; + float ao = 0.0; + float ao_size = 0.5; + bool interior = false; + bool use_two_bounces = false; + +protected: + static void _bind_methods(); + void _validate_property(PropertyInfo &property) const override; + +public: + void allocate(const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3 &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts); + AABB get_bounds() const; + Vector3 get_octree_size() const; + Vector get_octree_cells() const; + Vector get_data_cells() const; + Vector get_distance_field() const; + Vector get_level_counts() const; + Transform3D get_to_cell_xform() const; + + void set_dynamic_range(float p_range); + float get_dynamic_range() const; + + void set_propagation(float p_propagation); + float get_propagation() const; + + void set_anisotropy_strength(float p_anisotropy_strength); + float get_anisotropy_strength() const; + + void set_ao(float p_ao); + float get_ao() const; + + void set_ao_size(float p_ao_size); + float get_ao_size() const; + + void set_energy(float p_energy); + float get_energy() const; + + void set_bias(float p_bias); + float get_bias() const; + + void set_normal_bias(float p_normal_bias); + float get_normal_bias() const; + + void set_interior(bool p_enable); + bool is_interior() const; + + void set_use_two_bounces(bool p_enable); + bool is_using_two_bounces() const; + + virtual RID get_rid() const override; + + VoxelGIData(); + ~VoxelGIData(); +}; + +class VoxelGI : public VisualInstance3D { + GDCLASS(VoxelGI, VisualInstance3D); + +public: + enum Subdiv { + SUBDIV_64, + SUBDIV_128, + SUBDIV_256, + SUBDIV_512, + SUBDIV_MAX + + }; + + typedef void (*BakeBeginFunc)(int); + typedef void (*BakeStepFunc)(int, const String &); + typedef void (*BakeEndFunc)(); + +private: + Ref probe_data; + + RID voxel_gi; + + Subdiv subdiv = SUBDIV_128; + Vector3 extents = Vector3(10, 10, 10); + + struct PlotMesh { + Ref override_material; + Vector> instance_materials; + Ref mesh; + Transform3D local_xform; + }; + + void _find_meshes(Node *p_at_node, List &plot_meshes); + void _debug_bake(); + +protected: + static void _bind_methods(); + +public: + static BakeBeginFunc bake_begin_function; + static BakeStepFunc bake_step_function; + static BakeEndFunc bake_end_function; + + void set_probe_data(const Ref &p_data); + Ref get_probe_data() const; + + void set_subdiv(Subdiv p_subdiv); + Subdiv get_subdiv() const; + + void set_extents(const Vector3 &p_extents); + Vector3 get_extents() const; + Vector3i get_estimated_cell_size() const; + + void bake(Node *p_from_node = nullptr, bool p_create_visual_debug = false); + + virtual AABB get_aabb() const override; + virtual Vector get_faces(uint32_t p_usage_flags) const override; + + TypedArray get_configuration_warnings() const override; + + VoxelGI(); + ~VoxelGI(); +}; + +VARIANT_ENUM_CAST(VoxelGI::Subdiv) + +#endif // VOXEL_GI_H diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp index 18ef5acbe3..ee0c3fe9b6 100644 --- a/scene/3d/voxelizer.cpp +++ b/scene/3d/voxelizer.cpp @@ -668,19 +668,19 @@ void Voxelizer::end_bake() { //create the data for visual server -int Voxelizer::get_gi_probe_octree_depth() const { +int Voxelizer::get_voxel_gi_octree_depth() const { return cell_subdiv; } -Vector3i Voxelizer::get_giprobe_octree_size() const { +Vector3i Voxelizer::get_voxel_gi_octree_size() const { return Vector3i(axis_cell_size[0], axis_cell_size[1], axis_cell_size[2]); } -int Voxelizer::get_giprobe_cell_count() const { +int Voxelizer::get_voxel_gi_cell_count() const { return bake_cells.size(); } -Vector Voxelizer::get_giprobe_octree_cells() const { +Vector Voxelizer::get_voxel_gi_octree_cells() const { Vector data; data.resize((8 * 4) * bake_cells.size()); //8 uint32t values { @@ -700,7 +700,7 @@ Vector Voxelizer::get_giprobe_octree_cells() const { return data; } -Vector Voxelizer::get_giprobe_data_cells() const { +Vector Voxelizer::get_voxel_gi_data_cells() const { Vector data; data.resize((4 * 4) * bake_cells.size()); //8 uint32t values { @@ -755,7 +755,7 @@ Vector Voxelizer::get_giprobe_data_cells() const { return data; } -Vector Voxelizer::get_giprobe_level_cell_count() const { +Vector Voxelizer::get_voxel_gi_level_cell_count() const { uint32_t cell_count = bake_cells.size(); const Cell *cells = bake_cells.ptr(); Vector level_count; @@ -819,7 +819,7 @@ static void edt(float *f, int stride, int n) { #undef square Vector Voxelizer::get_sdf_3d_image() const { - Vector3i octree_size = get_giprobe_octree_size(); + Vector3i octree_size = get_voxel_gi_octree_size(); uint32_t float_count = octree_size.x * octree_size.y * octree_size.z; float *work_memory = memnew_arr(float, float_count); diff --git a/scene/3d/voxelizer.h b/scene/3d/voxelizer.h index d0da5a5624..e500d2d4c3 100644 --- a/scene/3d/voxelizer.h +++ b/scene/3d/voxelizer.h @@ -117,12 +117,12 @@ public: void plot_mesh(const Transform3D &p_xform, Ref &p_mesh, const Vector> &p_materials, const Ref &p_override_material); void end_bake(); - int get_gi_probe_octree_depth() const; - Vector3i get_giprobe_octree_size() const; - int get_giprobe_cell_count() const; - Vector get_giprobe_octree_cells() const; - Vector get_giprobe_data_cells() const; - Vector get_giprobe_level_cell_count() const; + int get_voxel_gi_octree_depth() const; + Vector3i get_voxel_gi_octree_size() const; + int get_voxel_gi_cell_count() const; + Vector get_voxel_gi_octree_cells() const; + Vector get_voxel_gi_data_cells() const; + Vector get_voxel_gi_level_cell_count() const; Vector get_sdf_3d_image() const; Ref create_debug_multimesh(); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 2f8311d977..17c0023b09 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -3669,9 +3669,9 @@ void Viewport::_bind_methods() { BIND_ENUM_CONSTANT(DEBUG_DRAW_OVERDRAW); BIND_ENUM_CONSTANT(DEBUG_DRAW_WIREFRAME); BIND_ENUM_CONSTANT(DEBUG_DRAW_NORMAL_BUFFER); - BIND_ENUM_CONSTANT(DEBUG_DRAW_GI_PROBE_ALBEDO); - BIND_ENUM_CONSTANT(DEBUG_DRAW_GI_PROBE_LIGHTING); - BIND_ENUM_CONSTANT(DEBUG_DRAW_GI_PROBE_EMISSION); + BIND_ENUM_CONSTANT(DEBUG_DRAW_VOXEL_GI_ALBEDO); + BIND_ENUM_CONSTANT(DEBUG_DRAW_VOXEL_GI_LIGHTING); + BIND_ENUM_CONSTANT(DEBUG_DRAW_VOXEL_GI_EMISSION); BIND_ENUM_CONSTANT(DEBUG_DRAW_SHADOW_ATLAS); BIND_ENUM_CONSTANT(DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS); BIND_ENUM_CONSTANT(DEBUG_DRAW_SCENE_LUMINANCE); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index c108d13d88..2d7f5101c2 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -130,9 +130,9 @@ public: DEBUG_DRAW_OVERDRAW, DEBUG_DRAW_WIREFRAME, DEBUG_DRAW_NORMAL_BUFFER, - DEBUG_DRAW_GI_PROBE_ALBEDO, - DEBUG_DRAW_GI_PROBE_LIGHTING, - DEBUG_DRAW_GI_PROBE_EMISSION, + DEBUG_DRAW_VOXEL_GI_ALBEDO, + DEBUG_DRAW_VOXEL_GI_LIGHTING, + DEBUG_DRAW_VOXEL_GI_EMISSION, DEBUG_DRAW_SHADOW_ATLAS, DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS, DEBUG_DRAW_SCENE_LUMINANCE, diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 94da5749fc..04ce94d5c0 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -184,18 +184,17 @@ #ifndef _3D_DISABLED #include "scene/3d/area_3d.h" #include "scene/3d/audio_stream_player_3d.h" -#include "scene/3d/baked_lightmap.h" #include "scene/3d/bone_attachment_3d.h" #include "scene/3d/camera_3d.h" #include "scene/3d/collision_polygon_3d.h" #include "scene/3d/collision_shape_3d.h" #include "scene/3d/cpu_particles_3d.h" #include "scene/3d/decal.h" -#include "scene/3d/gi_probe.h" #include "scene/3d/gpu_particles_3d.h" #include "scene/3d/gpu_particles_collision_3d.h" #include "scene/3d/immediate_geometry_3d.h" #include "scene/3d/light_3d.h" +#include "scene/3d/lightmap_gi.h" #include "scene/3d/lightmap_probe.h" #include "scene/3d/listener_3d.h" #include "scene/3d/mesh_instance_3d.h" @@ -220,6 +219,7 @@ #include "scene/3d/sprite_3d.h" #include "scene/3d/vehicle_body_3d.h" #include "scene/3d/visibility_notifier_3d.h" +#include "scene/3d/voxel_gi.h" #include "scene/3d/world_environment.h" #include "scene/3d/xr_nodes.h" #include "scene/resources/environment.h" @@ -452,10 +452,10 @@ void register_scene_types() { ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_virtual_class(); ClassDB::register_class(); @@ -819,6 +819,10 @@ void register_scene_types() { ClassDB::add_compatibility_class("Navigation3D", "Node3D"); ClassDB::add_compatibility_class("Navigation2D", "Node2D"); ClassDB::add_compatibility_class("YSort", "Node2D"); + ClassDB::add_compatibility_class("GIProbe", "VoxelGI"); + ClassDB::add_compatibility_class("GIProbeData", "VoxelGIData"); + ClassDB::add_compatibility_class("BakedLightmap", "LightmapGI"); + ClassDB::add_compatibility_class("BakedLightmapData", "LightmapGIData"); // Renamed in 4.0. // Keep alphabetical ordering to easily locate classes and avoid duplicates. diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h index f4a3c4497a..96c9137c6e 100644 --- a/servers/rendering/rasterizer_dummy.h +++ b/servers/rendering/rasterizer_dummy.h @@ -59,7 +59,7 @@ public: void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override {} void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {} void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override {} - void geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) override {} + void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {} void geometry_instance_free(GeometryInstance *p_geometry_instance) override {} @@ -168,14 +168,14 @@ public: RID lightmap_instance_create(RID p_lightmap) override { return RID(); } void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override {} - RID gi_probe_instance_create(RID p_gi_probe) override { return RID(); } - void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override {} - bool gi_probe_needs_update(RID p_probe) const override { return false; } - void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector &p_light_instances, const PagedArray &p_dynamic_objects) override {} + RID voxel_gi_instance_create(RID p_voxel_gi) override { return RID(); } + void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override {} + bool voxel_gi_needs_update(RID p_probe) const override { return false; } + void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector &p_light_instances, const PagedArray &p_dynamic_objects) override {} - void gi_probe_set_quality(RS::GIProbeQuality) override {} + void voxel_gi_set_quality(RS::VoxelGIQuality) override {} - void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray &p_instances, const PagedArray &p_lights, const PagedArray &p_reflection_probes, const PagedArray &p_gi_probes, const PagedArray &p_decals, const PagedArray &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr) override {} + void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray &p_instances, const PagedArray &p_lights, const PagedArray &p_reflection_probes, const PagedArray &p_voxel_gi_instances, const PagedArray &p_decals, const PagedArray &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr) override {} void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray &p_instances, RID p_framebuffer, const Rect2i &p_region) override {} void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray &p_instances) override {} @@ -482,52 +482,52 @@ public: AABB decal_get_aabb(RID p_decal) const override { return AABB(); } - /* GI PROBE API */ + /* VOXEL GI API */ - RID gi_probe_allocate() override { return RID(); } - void gi_probe_initialize(RID p_rid) override {} - void gi_probe_allocate_data(RID p_gi_probe, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts) override {} + RID voxel_gi_allocate() override { return RID(); } + void voxel_gi_initialize(RID p_rid) override {} + void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts) override {} - AABB gi_probe_get_bounds(RID p_gi_probe) const override { return AABB(); } - Vector3i gi_probe_get_octree_size(RID p_gi_probe) const override { return Vector3i(); } - Vector gi_probe_get_octree_cells(RID p_gi_probe) const override { return Vector(); } - Vector gi_probe_get_data_cells(RID p_gi_probe) const override { return Vector(); } - Vector gi_probe_get_distance_field(RID p_gi_probe) const override { return Vector(); } + AABB voxel_gi_get_bounds(RID p_voxel_gi) const override { return AABB(); } + Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const override { return Vector3i(); } + Vector voxel_gi_get_octree_cells(RID p_voxel_gi) const override { return Vector(); } + Vector voxel_gi_get_data_cells(RID p_voxel_gi) const override { return Vector(); } + Vector voxel_gi_get_distance_field(RID p_voxel_gi) const override { return Vector(); } - Vector gi_probe_get_level_counts(RID p_gi_probe) const override { return Vector(); } - Transform3D gi_probe_get_to_cell_xform(RID p_gi_probe) const override { return Transform3D(); } + Vector voxel_gi_get_level_counts(RID p_voxel_gi) const override { return Vector(); } + Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const override { return Transform3D(); } - void gi_probe_set_dynamic_range(RID p_gi_probe, float p_range) override {} - float gi_probe_get_dynamic_range(RID p_gi_probe) const override { return 0; } + void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) override {} + float voxel_gi_get_dynamic_range(RID p_voxel_gi) const override { return 0; } - void gi_probe_set_propagation(RID p_gi_probe, float p_range) override {} - float gi_probe_get_propagation(RID p_gi_probe) const override { return 0; } + void voxel_gi_set_propagation(RID p_voxel_gi, float p_range) override {} + float voxel_gi_get_propagation(RID p_voxel_gi) const override { return 0; } - void gi_probe_set_energy(RID p_gi_probe, float p_range) override {} - float gi_probe_get_energy(RID p_gi_probe) const override { return 0.0; } + void voxel_gi_set_energy(RID p_voxel_gi, float p_range) override {} + float voxel_gi_get_energy(RID p_voxel_gi) const override { return 0.0; } - void gi_probe_set_ao(RID p_gi_probe, float p_ao) override {} - float gi_probe_get_ao(RID p_gi_probe) const override { return 0; } + void voxel_gi_set_ao(RID p_voxel_gi, float p_ao) override {} + float voxel_gi_get_ao(RID p_voxel_gi) const override { return 0; } - void gi_probe_set_ao_size(RID p_gi_probe, float p_strength) override {} - float gi_probe_get_ao_size(RID p_gi_probe) const override { return 0; } + void voxel_gi_set_ao_size(RID p_voxel_gi, float p_strength) override {} + float voxel_gi_get_ao_size(RID p_voxel_gi) const override { return 0; } - void gi_probe_set_bias(RID p_gi_probe, float p_range) override {} - float gi_probe_get_bias(RID p_gi_probe) const override { return 0.0; } + void voxel_gi_set_bias(RID p_voxel_gi, float p_range) override {} + float voxel_gi_get_bias(RID p_voxel_gi) const override { return 0.0; } - void gi_probe_set_normal_bias(RID p_gi_probe, float p_range) override {} - float gi_probe_get_normal_bias(RID p_gi_probe) const override { return 0.0; } + void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) override {} + float voxel_gi_get_normal_bias(RID p_voxel_gi) const override { return 0.0; } - void gi_probe_set_interior(RID p_gi_probe, bool p_enable) override {} - bool gi_probe_is_interior(RID p_gi_probe) const override { return false; } + void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) override {} + bool voxel_gi_is_interior(RID p_voxel_gi) const override { return false; } - void gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable) override {} - bool gi_probe_is_using_two_bounces(RID p_gi_probe) const override { return false; } + void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) override {} + bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const override { return false; } - void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) override {} - float gi_probe_get_anisotropy_strength(RID p_gi_probe) const override { return 0; } + void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) override {} + float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const override { return 0; } - uint32_t gi_probe_get_version(RID p_gi_probe) override { return 0; } + uint32_t voxel_gi_get_version(RID p_voxel_gi) override { return 0; } /* LIGHTMAP CAPTURE */ RID lightmap_allocate() override { return RID(); } diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp index 563e08fdcb..872f7b5beb 100644 --- a/servers/rendering/renderer_rd/effects_rd.cpp +++ b/servers/rendering/renderer_rd/effects_rd.cpp @@ -1401,19 +1401,19 @@ void EffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_ RD::get_singleton()->draw_list_draw(draw_list, true); } -void EffectsRD::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_giprobe, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_giprobe, Vector2i p_screen_size, int p_samples, uint32_t p_barrier) { +void EffectsRD::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier) { ResolvePushConstant push_constant; push_constant.screen_size[0] = p_screen_size.x; push_constant.screen_size[1] = p_screen_size.y; push_constant.samples = p_samples; RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, resolve.pipelines[p_source_giprobe.is_valid() ? RESOLVE_MODE_GI_GIPROBE : RESOLVE_MODE_GI]); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, resolve.pipelines[p_source_voxel_gi.is_valid() ? RESOLVE_MODE_GI_VOXEL_GI : RESOLVE_MODE_GI]); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_source_depth, p_source_normal_roughness), 0); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_dest_depth, p_dest_normal_roughness), 1); - if (p_source_giprobe.is_valid()) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_giprobe), 2); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_giprobe), 3); + if (p_source_voxel_gi.is_valid()) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_voxel_gi), 2); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_voxel_gi), 3); } RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ResolvePushConstant)); @@ -1907,7 +1907,7 @@ EffectsRD::EffectsRD() { { Vector resolve_modes; resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n"); - resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n#define GIPROBE_RESOLVE\n"); + resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n#define VOXEL_GI_RESOLVE\n"); resolve.shader.initialize(resolve_modes); diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h index 1ba25e301b..ab0100f8f9 100644 --- a/servers/rendering/renderer_rd/effects_rd.h +++ b/servers/rendering/renderer_rd/effects_rd.h @@ -585,7 +585,7 @@ class EffectsRD { enum ResolveMode { RESOLVE_MODE_GI, - RESOLVE_MODE_GI_GIPROBE, + RESOLVE_MODE_GI_VOXEL_GI, RESOLVE_MODE_MAX }; @@ -750,7 +750,7 @@ public: void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection); void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality); - void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_giprobe, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_giprobe, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL); + void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL); void sort_buffer(RID p_uniform_set, int p_size); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 9a9d7a1214..e1c2836f6c 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -93,8 +93,8 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular() } } -void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_giprobe() { - if (!giprobe_buffer.is_valid()) { +void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_voxelgi() { + if (!voxelgi_buffer.is_valid()) { RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R8G8_UINT; tf.width = width; @@ -105,41 +105,41 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_giprobe() RD::TextureFormat tf_aa = tf; tf_aa.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; tf_aa.samples = texture_samples; - giprobe_buffer_msaa = RD::get_singleton()->texture_create(tf_aa, RD::TextureView()); + voxelgi_buffer_msaa = RD::get_singleton()->texture_create(tf_aa, RD::TextureView()); } else { tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; } tf.usage_bits |= RD::TEXTURE_USAGE_STORAGE_BIT; - giprobe_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + voxelgi_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); Vector fb; if (msaa != RS::VIEWPORT_MSAA_DISABLED) { fb.push_back(depth_msaa); fb.push_back(normal_roughness_buffer_msaa); - fb.push_back(giprobe_buffer_msaa); + fb.push_back(voxelgi_buffer_msaa); } else { fb.push_back(depth); fb.push_back(normal_roughness_buffer); - fb.push_back(giprobe_buffer); + fb.push_back(voxelgi_buffer); } - depth_normal_roughness_giprobe_fb = RD::get_singleton()->framebuffer_create(fb); + depth_normal_roughness_voxelgi_fb = RD::get_singleton()->framebuffer_create(fb); } } void RenderForwardClustered::RenderBufferDataForwardClustered::clear() { - if (giprobe_buffer != RID()) { - RD::get_singleton()->free(giprobe_buffer); - giprobe_buffer = RID(); + if (voxelgi_buffer != RID()) { + RD::get_singleton()->free(voxelgi_buffer); + voxelgi_buffer = RID(); - if (giprobe_buffer_msaa.is_valid()) { - RD::get_singleton()->free(giprobe_buffer_msaa); - giprobe_buffer_msaa = RID(); + if (voxelgi_buffer_msaa.is_valid()) { + RD::get_singleton()->free(voxelgi_buffer_msaa); + voxelgi_buffer_msaa = RID(); } - depth_normal_roughness_giprobe_fb = RID(); + depth_normal_roughness_voxelgi_fb = RID(); } if (color_msaa.is_valid()) { @@ -398,8 +398,8 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: { shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS; } break; - case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE: { - shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE; + case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI: { + shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI; } break; case PASS_MODE_DEPTH_MATERIAL: { shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL; @@ -498,8 +498,8 @@ void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_lis case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: { _render_list_template(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); } break; - case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE: { - _render_list_template(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); + case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI: { + _render_list_template(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); } break; case PASS_MODE_DEPTH_MATERIAL: { _render_list_template(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); @@ -948,14 +948,14 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con flags |= INSTANCE_DATA_FLAG_USE_GI_BUFFERS; } - if (inst->gi_probes[0].is_valid()) { + if (inst->voxel_gi_instances[0].is_valid()) { uint32_t probe0_index = 0xFFFF; uint32_t probe1_index = 0xFFFF; - for (uint32_t j = 0; j < scene_state.giprobes_used; j++) { - if (scene_state.giprobe_ids[j] == inst->gi_probes[0]) { + for (uint32_t j = 0; j < scene_state.voxelgis_used; j++) { + if (scene_state.voxelgi_ids[j] == inst->voxel_gi_instances[0]) { probe0_index = j; - } else if (scene_state.giprobe_ids[j] == inst->gi_probes[1]) { + } else if (scene_state.voxelgi_ids[j] == inst->voxel_gi_instances[1]) { probe1_index = j; } } @@ -966,7 +966,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con } inst->gi_offset_cache = probe0_index | (probe1_index << 16); - flags |= INSTANCE_DATA_FLAG_USE_GIPROBE; + flags |= INSTANCE_DATA_FLAG_USE_VOXEL_GI; uses_gi = true; } else { if (p_using_sdfgi && inst->can_sdfgi) { @@ -1061,10 +1061,10 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con } } -void RenderForwardClustered::_setup_giprobes(const PagedArray &p_giprobes) { - scene_state.giprobes_used = MIN(p_giprobes.size(), uint32_t(MAX_GI_PROBES)); - for (uint32_t i = 0; i < scene_state.giprobes_used; i++) { - scene_state.giprobe_ids[i] = p_giprobes[i]; +void RenderForwardClustered::_setup_voxelgis(const PagedArray &p_voxelgis) { + scene_state.voxelgis_used = MIN(p_voxelgis.size(), uint32_t(MAX_VOXEL_GI_INSTANCESS)); + for (uint32_t i = 0; i < scene_state.voxelgis_used; i++) { + scene_state.voxelgi_ids[i] = p_voxelgis[i]; } } @@ -1120,7 +1120,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool using_separate_specular = false; bool using_ssr = false; bool using_sdfgi = false; - bool using_giprobe = false; + bool using_voxelgi = false; bool reverse_cull = false; if (render_buffer) { @@ -1129,19 +1129,19 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co opaque_framebuffer = render_buffer->color_fb; - if (p_render_data->gi_probes->size() > 0) { - using_giprobe = true; + if (p_render_data->voxel_gi_instances->size() > 0) { + using_voxelgi = true; } - if (!p_render_data->environment.is_valid() && using_giprobe) { - depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE; + if (!p_render_data->environment.is_valid() && using_voxelgi) { + depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI; - } else if (p_render_data->environment.is_valid() && (environment_is_ssr_enabled(p_render_data->environment) || environment_is_sdfgi_enabled(p_render_data->environment) || using_giprobe)) { + } else if (p_render_data->environment.is_valid() && (environment_is_ssr_enabled(p_render_data->environment) || environment_is_sdfgi_enabled(p_render_data->environment) || using_voxelgi)) { if (environment_is_sdfgi_enabled(p_render_data->environment)) { - depth_pass_mode = using_giprobe ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; // also giprobe + depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; // also voxelgi using_sdfgi = true; } else { - depth_pass_mode = using_giprobe ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; + depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; } if (environment_is_ssr_enabled(p_render_data->environment)) { @@ -1164,10 +1164,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co depth_framebuffer = render_buffer->depth_normal_roughness_fb; depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0)); } break; - case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE: { + case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI: { _allocate_normal_roughness_texture(render_buffer); - render_buffer->ensure_giprobe(); - depth_framebuffer = render_buffer->depth_normal_roughness_giprobe_fb; + render_buffer->ensure_voxelgi(); + depth_framebuffer = render_buffer->depth_normal_roughness_voxelgi_fb; depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0)); depth_pass_clear.push_back(Color(0, 0, 0, 0)); } break; @@ -1198,12 +1198,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_begin_label("Render Setup"); _setup_lightmaps(*p_render_data->lightmaps, p_render_data->cam_transform); - _setup_giprobes(*p_render_data->gi_probes); + _setup_voxelgis(*p_render_data->voxel_gi_instances); _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false); _update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example) - _fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR, using_sdfgi, using_sdfgi || using_giprobe); + _fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR, using_sdfgi, using_sdfgi || using_voxelgi); render_list[RENDER_LIST_OPAQUE].sort_by_key(); render_list[RENDER_LIST_ALPHA].sort_by_depth(); _fill_instance_data(RENDER_LIST_OPAQUE); @@ -1293,7 +1293,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co clear_color = p_default_bg_color; } - bool debug_giprobes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION; + bool debug_voxelgis = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_ALBEDO || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION; bool debug_sdfgi_probes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES; bool depth_pre_pass = depth_framebuffer.is_valid(); @@ -1301,7 +1301,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool continue_depth = false; if (depth_pre_pass) { //depth pre pass - bool needs_pre_resolve = _needs_post_prepass_render(p_render_data, using_sdfgi || using_giprobe); + bool needs_pre_resolve = _needs_post_prepass_render(p_render_data, using_sdfgi || using_voxelgi); if (needs_pre_resolve) { RENDER_TIMESTAMP("GI + Render Depth Pre-Pass (parallel)"); } else { @@ -1312,32 +1312,32 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE, depth_pass_clear); RD::get_singleton()->draw_list_end(); //start compute processes here, so they run at the same time as depth pre-pass - _post_prepass_render(p_render_data, using_sdfgi || using_giprobe); + _post_prepass_render(p_render_data, using_sdfgi || using_voxelgi); } RD::get_singleton()->draw_command_begin_label("Render Depth Pre-Pass"); RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID()); - bool finish_depth = using_ssao || using_sdfgi || using_giprobe; + bool finish_depth = using_ssao || using_sdfgi || using_voxelgi; RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold); _render_list_with_threads(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, needs_pre_resolve ? Vector() : depth_pass_clear); RD::get_singleton()->draw_command_end_label(); if (needs_pre_resolve) { - _pre_resolve_render(p_render_data, using_sdfgi || using_giprobe); + _pre_resolve_render(p_render_data, using_sdfgi || using_voxelgi); } if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { RENDER_TIMESTAMP("Resolve Depth Pre-Pass"); RD::get_singleton()->draw_command_begin_label("Resolve Depth Pre-Pass"); - if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE) { + if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI) { if (needs_pre_resolve) { RD::get_singleton()->barrier(RD::BARRIER_MASK_RASTER, RD::BARRIER_MASK_COMPUTE); } static int texture_samples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8, 16 }; - storage->get_effects()->resolve_gi(render_buffer->depth_msaa, render_buffer->normal_roughness_buffer_msaa, using_giprobe ? render_buffer->giprobe_buffer_msaa : RID(), render_buffer->depth, render_buffer->normal_roughness_buffer, using_giprobe ? render_buffer->giprobe_buffer : RID(), Vector2i(render_buffer->width, render_buffer->height), texture_samples[render_buffer->msaa]); + storage->get_effects()->resolve_gi(render_buffer->depth_msaa, render_buffer->normal_roughness_buffer_msaa, using_voxelgi ? render_buffer->voxelgi_buffer_msaa : RID(), render_buffer->depth, render_buffer->normal_roughness_buffer, using_voxelgi ? render_buffer->voxelgi_buffer : RID(), Vector2i(render_buffer->width, render_buffer->height), texture_samples[render_buffer->msaa]); } else if (finish_depth) { RD::get_singleton()->texture_resolve_multisample(render_buffer->depth_msaa, render_buffer->depth); } @@ -1347,7 +1347,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co continue_depth = !finish_depth; } - _pre_opaque_render(p_render_data, using_ssao, using_sdfgi || using_giprobe, render_buffer ? render_buffer->normal_roughness_buffer : RID(), render_buffer ? render_buffer->giprobe_buffer : RID()); + _pre_opaque_render(p_render_data, using_ssao, using_sdfgi || using_voxelgi, render_buffer ? render_buffer->normal_roughness_buffer : RID(), render_buffer ? render_buffer->voxelgi_buffer : RID()); RD::get_singleton()->draw_command_begin_label("Render Opaque Pass"); @@ -1363,8 +1363,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool can_continue_depth = !scene_state.used_depth_texture && !using_ssr && !using_sss; { - bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only || debug_giprobes || debug_sdfgi_probes); - bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only || debug_giprobes || debug_sdfgi_probes); + bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only || debug_voxelgis || debug_sdfgi_probes); + bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only || debug_voxelgis || debug_sdfgi_probes); //regular forward for now Vector c; @@ -1389,8 +1389,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_end_label(); - if (debug_giprobes) { - //debug giprobes + if (debug_voxelgis) { + //debug voxelgis bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only); bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only); @@ -1398,16 +1398,16 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co dc.set_depth_correction(true); CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->cam_transform.affine_inverse()); RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); - RD::get_singleton()->draw_command_begin_label("Debug GIProbes"); - for (int i = 0; i < (int)p_render_data->gi_probes->size(); i++) { - gi.debug_giprobe((*p_render_data->gi_probes)[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, 1.0); + RD::get_singleton()->draw_command_begin_label("Debug VoxelGIs"); + for (int i = 0; i < (int)p_render_data->voxel_gi_instances->size(); i++) { + gi.debug_voxel_gi((*p_render_data->voxel_gi_instances)[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION, 1.0); } RD::get_singleton()->draw_command_end_label(); RD::get_singleton()->draw_list_end(); } if (debug_sdfgi_probes) { - //debug giprobes + //debug voxelgis bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only); bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only); @@ -2059,11 +2059,11 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.resize(MAX_GI_PROBES); + u.ids.resize(MAX_VOXEL_GI_INSTANCESS); RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); - for (int i = 0; i < MAX_GI_PROBES; i++) { - if (p_render_data && i < (int)p_render_data->gi_probes->size()) { - RID tex = gi.gi_probe_instance_get_texture((*p_render_data->gi_probes)[i]); + for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) { + if (p_render_data && i < (int)p_render_data->voxel_gi_instances->size()) { + RID tex = gi.voxel_gi_instance_get_texture((*p_render_data->voxel_gi_instances)[i]); if (!tex.is_valid()) { tex = default_tex; } @@ -2170,7 +2170,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 17; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(rb ? render_buffers_get_gi_probe_buffer(p_render_data->render_buffers) : render_buffers_get_default_gi_probe_buffer()); + u.ids.push_back(rb ? render_buffers_get_voxel_gi_buffer(p_render_data->render_buffers) : render_buffers_get_default_voxel_gi_buffer()); uniforms.push_back(u); } { @@ -2279,13 +2279,13 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te } { - // No GIProbes + // No VoxelGIs RD::Uniform u; u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.resize(MAX_GI_PROBES); + u.ids.resize(MAX_VOXEL_GI_INSTANCESS); RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); - for (int i = 0; i < MAX_GI_PROBES; i++) { + for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) { u.ids.write[i] = default_tex; } @@ -2633,7 +2633,7 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome ginstance->can_sdfgi = false; if (!lightmap_instance_is_valid(ginstance->lightmap_instance)) { - if (ginstance->gi_probes[0].is_null() && (ginstance->data->use_baked_light || ginstance->data->use_dynamic_gi)) { + if (ginstance->voxel_gi_instances[0].is_null() && (ginstance->data->use_baked_light || ginstance->data->use_dynamic_gi)) { ginstance->can_sdfgi = true; } } @@ -2816,7 +2816,7 @@ void RenderForwardClustered::geometry_instance_free(GeometryInstance *p_geometry } uint32_t RenderForwardClustered::geometry_instance_get_pair_mask() { - return (1 << RS::INSTANCE_GI_PROBE); + return (1 << RS::INSTANCE_VOXEL_GI); } void RenderForwardClustered::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) { } @@ -2837,19 +2837,19 @@ AABB RenderForwardClustered::geometry_instance_get_aabb(GeometryInstance *p_inst return ginstance->data->aabb; } -void RenderForwardClustered::geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) { +void RenderForwardClustered::geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) { GeometryInstanceForwardClustered *ginstance = static_cast(p_geometry_instance); ERR_FAIL_COND(!ginstance); - if (p_gi_probe_instance_count > 0) { - ginstance->gi_probes[0] = p_gi_probe_instances[0]; + if (p_voxel_gi_instance_count > 0) { + ginstance->voxel_gi_instances[0] = p_voxel_gi_instances[0]; } else { - ginstance->gi_probes[0] = RID(); + ginstance->voxel_gi_instances[0] = RID(); } - if (p_gi_probe_instance_count > 1) { - ginstance->gi_probes[1] = p_gi_probe_instances[1]; + if (p_voxel_gi_instance_count > 1) { + ginstance->voxel_gi_instances[1] = p_voxel_gi_instances[1]; } else { - ginstance->gi_probes[1] = RID(); + ginstance->voxel_gi_instances[1] = RID(); } } diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index 86c04eb08e..e276e55de2 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -52,9 +52,9 @@ class RenderForwardClustered : public RendererSceneRenderRD { enum { SDFGI_MAX_CASCADES = 8, - MAX_GI_PROBES = 8, + MAX_VOXEL_GI_INSTANCESS = 8, MAX_LIGHTMAPS = 8, - MAX_GI_PROBES_PER_INSTANCE = 2, + MAX_VOXEL_GI_INSTANCESS_PER_INSTANCE = 2, INSTANCE_DATA_BUFFER_MIN_SIZE = 4096 }; @@ -79,7 +79,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { RID depth; RID specular; RID normal_roughness_buffer; - RID giprobe_buffer; + RID voxelgi_buffer; RS::ViewportMSAA msaa; RD::TextureSamples texture_samples; @@ -89,11 +89,11 @@ class RenderForwardClustered : public RendererSceneRenderRD { RID specular_msaa; RID normal_roughness_buffer_msaa; RID roughness_buffer_msaa; - RID giprobe_buffer_msaa; + RID voxelgi_buffer_msaa; RID depth_fb; RID depth_normal_roughness_fb; - RID depth_normal_roughness_giprobe_fb; + RID depth_normal_roughness_voxelgi_fb; RID color_fb; RID color_specular_fb; RID specular_only_fb; @@ -101,7 +101,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { RID render_sdfgi_uniform_set; void ensure_specular(); - void ensure_giprobe(); + void ensure_voxelgi(); void clear(); virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa); @@ -132,7 +132,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { PASS_MODE_SHADOW_DP, PASS_MODE_DEPTH, PASS_MODE_DEPTH_NORMAL_ROUGHNESS, - PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE, + PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI, PASS_MODE_DEPTH_MATERIAL, PASS_MODE_SDF, }; @@ -189,7 +189,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8, INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 9, INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 10, - INSTANCE_DATA_FLAG_USE_GIPROBE = 1 << 11, + INSTANCE_DATA_FLAG_USE_VOXEL_GI = 1 << 11, INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12, INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13, INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14, @@ -318,8 +318,8 @@ class RenderForwardClustered : public RendererSceneRenderRD { uint32_t max_lightmap_captures; RID lightmap_capture_buffer; - RID giprobe_ids[MAX_GI_PROBES]; - uint32_t giprobes_used = 0; + RID voxelgi_ids[MAX_VOXEL_GI_INSTANCESS]; + uint32_t voxelgis_used = 0; bool used_screen_texture = false; bool used_normal_texture = false; @@ -350,7 +350,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { static RenderForwardClustered *singleton; void _setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false, int p_index = 0); - void _setup_giprobes(const PagedArray &p_giprobes); + void _setup_voxelgis(const PagedArray &p_voxelgis); void _setup_lightmaps(const PagedArray &p_lightmaps, const Transform3D &p_cam_transform); struct RenderElementInfo { @@ -459,7 +459,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { //used during setup uint32_t base_flags = 0; Transform3D transform; - RID gi_probes[MAX_GI_PROBES_PER_INSTANCE]; + RID voxel_gi_instances[MAX_VOXEL_GI_INSTANCESS_PER_INSTANCE]; RID lightmap_instance; GeometryInstanceLightmapSH *lightmap_sh = nullptr; GeometryInstanceSurfaceDataCache *surface_caches = nullptr; @@ -603,7 +603,7 @@ public: virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count); virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count); virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count); - virtual void geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count); + virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count); virtual bool free(RID p_rid); diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index 5a26b5abbb..6dbac0f7e1 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -311,7 +311,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { //none, leave empty } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) { blend_state = blend_state_depth_normal_roughness; - } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE) { + } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) { blend_state = blend_state_depth_normal_roughness_giprobe; } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) { blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way @@ -563,7 +563,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n"); shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n"); - shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_GIPROBE\n"); + shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n"); shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n"); shader_versions.push_back(""); diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index 7c8879686b..6845133825 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -48,7 +48,7 @@ public: SHADER_VERSION_DEPTH_PASS, SHADER_VERSION_DEPTH_PASS_DP, SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS, - SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE, + SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI, SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL, SHADER_VERSION_DEPTH_PASS_WITH_SDF, SHADER_VERSION_COLOR_PASS, diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index c5f13df6e2..370d8eca4e 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -226,11 +226,11 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ RD::Uniform u; u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.resize(MAX_GI_PROBES); + u.ids.resize(MAX_VOXEL_GI_INSTANCESS); RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); - for (int i = 0; i < MAX_GI_PROBES; i++) { - if (i < (int)p_gi_probes.size()) { - RID tex = gi.gi_probe_instance_get_texture(p_gi_probes[i]); + for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) { + if (i < (int)p_voxel_gi_instances.size()) { + RID tex = gi.voxel_gi_instance_get_texture(p_voxel_gi_instances[i]); if (!tex.is_valid()) { tex = default_tex; } @@ -1725,7 +1725,7 @@ void RenderForwardMobile::geometry_instance_pair_decal_instances(GeometryInstanc } } -void RenderForwardMobile::geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) { +void RenderForwardMobile::geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) { // We do not have this here! } diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index 28abc7e0b5..a2189693d0 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -104,7 +104,7 @@ protected: PASS_MODE_SHADOW_DP, // PASS_MODE_DEPTH, // PASS_MODE_DEPTH_NORMAL_ROUGHNESS, - // PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE, + // PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI, PASS_MODE_DEPTH_MATERIAL, // PASS_MODE_SDF, }; @@ -390,7 +390,7 @@ protected: INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8, INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 9, INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 10, - INSTANCE_DATA_FLAG_USE_GIPROBE = 1 << 11, + INSTANCE_DATA_FLAG_USE_VOXEL_GI = 1 << 11, INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12, INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13, INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14, @@ -587,7 +587,7 @@ public: virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count); virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count); virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count); - virtual void geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count); + virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count); virtual bool free(RID p_rid); diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 883273c8a5..37508d70af 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -342,7 +342,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { //none, leave empty } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) { blend_state = blend_state_depth_normal_roughness; - } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE) { + } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) { blend_state = blend_state_depth_normal_roughness_giprobe; } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) { blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp index cce3b5a3cd..43a4058ab6 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp @@ -2012,10 +2012,10 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32 } //////////////////////////////////////////////////////////////////////////////// -// GIProbeInstance +// VoxelGIInstance -void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, const Vector &p_light_instances, const PagedArray &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) { - uint32_t data_version = storage->gi_probe_get_data_version(probe); +void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, const Vector &p_light_instances, const PagedArray &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) { + uint32_t data_version = storage->voxel_gi_get_data_version(probe); // (RE)CREATE IF NEEDED @@ -2034,11 +2034,11 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c dynamic_maps.clear(); - Vector3i octree_size = storage->gi_probe_get_octree_size(probe); + Vector3i octree_size = storage->voxel_gi_get_octree_size(probe); if (octree_size != Vector3i()) { //can create a 3D texture - Vector levels = storage->gi_probe_get_level_counts(probe); + Vector levels = storage->voxel_gi_get_level_counts(probe); RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; @@ -2064,7 +2064,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c } for (int i = 0; i < levels.size(); i++) { - GIProbeInstance::Mipmap mipmap; + VoxelGIInstance::Mipmap mipmap; mipmap.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), texture, 0, i, RD::TEXTURE_SLICE_3D); mipmap.level = levels.size() - i - 1; mipmap.cell_offset = 0; @@ -2078,14 +2078,14 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; - u.ids.push_back(storage->gi_probe_get_octree_buffer(probe)); + u.ids.push_back(storage->voxel_gi_get_octree_buffer(probe)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; - u.ids.push_back(storage->gi_probe_get_data_buffer(probe)); + u.ids.push_back(storage->voxel_gi_get_data_buffer(probe)); uniforms.push_back(u); } @@ -2100,7 +2100,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 9; - u.ids.push_back(storage->gi_probe_get_sdf_texture(probe)); + u.ids.push_back(storage->voxel_gi_get_sdf_texture(probe)); uniforms.push_back(u); } { @@ -2118,11 +2118,11 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 3; - u.ids.push_back(gi->gi_probe_lights_uniform); + u.ids.push_back(gi->voxel_gi_lights_uniform); copy_uniforms.push_back(u); } - mipmap.uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, gi->giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT], 0); + mipmap.uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, gi->voxel_gi_lighting_shader_version_shaders[VOXEL_GI_SHADER_VERSION_COMPUTE_LIGHT], 0); copy_uniforms = uniforms; //restore @@ -2133,9 +2133,9 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c u.ids.push_back(texture); copy_uniforms.push_back(u); } - mipmap.second_bounce_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, gi->giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE], 0); + mipmap.second_bounce_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, gi->voxel_gi_lighting_shader_version_shaders[VOXEL_GI_SHADER_VERSION_COMPUTE_SECOND_BOUNCE], 0); } else { - mipmap.uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, gi->giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP], 0); + mipmap.uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, gi->voxel_gi_lighting_shader_version_shaders[VOXEL_GI_SHADER_VERSION_COMPUTE_MIPMAP], 0); } } @@ -2147,7 +2147,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c uniforms.push_back(u); } - mipmap.write_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_WRITE_TEXTURE], 0); + mipmap.write_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->voxel_gi_lighting_shader_version_shaders[VOXEL_GI_SHADER_VERSION_WRITE_TEXTURE], 0); mipmaps.push_back(mipmap); } @@ -2158,7 +2158,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c int mipmap_index = 0; while (mipmap_index < mipmaps.size()) { - GIProbeInstance::DynamicMap dmap; + VoxelGIInstance::DynamicMap dmap; if (oversample > 0) { dmap.size = dynamic_map_size * (1 << oversample); @@ -2217,7 +2217,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 3; - u.ids.push_back(gi->gi_probe_lights_uniform); + u.ids.push_back(gi->voxel_gi_lights_uniform); uniforms.push_back(u); } @@ -2253,7 +2253,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 9; - u.ids.push_back(storage->gi_probe_get_sdf_texture(probe)); + u.ids.push_back(storage->voxel_gi_get_sdf_texture(probe)); uniforms.push_back(u); } { @@ -2278,7 +2278,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c uniforms.push_back(u); } - dmap.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING], 0); + dmap.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->voxel_gi_lighting_shader_version_shaders[VOXEL_GI_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING], 0); } } else { bool plot = dmap.mipmap >= 0; @@ -2322,7 +2322,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 9; - u.ids.push_back(storage->gi_probe_get_sdf_texture(probe)); + u.ids.push_back(storage->voxel_gi_get_sdf_texture(probe)); uniforms.push_back(u); } { @@ -2345,7 +2345,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c dmap.uniform_set = RD::get_singleton()->uniform_set_create( uniforms, - gi->giprobe_lighting_shader_version_shaders[(write && plot) ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT : (write ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE : GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT)], + gi->voxel_gi_lighting_shader_version_shaders[(write && plot) ? VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT : (write ? VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_WRITE : VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_PLOT)], 0); } @@ -2370,15 +2370,15 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c uint32_t light_count = 0; if (p_update_light_instances || p_dynamic_objects.size() > 0) { - light_count = MIN(gi->gi_probe_max_lights, (uint32_t)p_light_instances.size()); + light_count = MIN(gi->voxel_gi_max_lights, (uint32_t)p_light_instances.size()); { - Transform3D to_cell = storage->gi_probe_get_to_cell_xform(probe); + Transform3D to_cell = storage->voxel_gi_get_to_cell_xform(probe); Transform3D to_probe_xform = (transform * to_cell.affine_inverse()).affine_inverse(); //update lights for (uint32_t i = 0; i < light_count; i++) { - GIProbeLight &l = gi->gi_probe_lights[i]; + VoxelGILight &l = gi->voxel_gi_lights[i]; RID light_instance = p_light_instances[i]; RID light = p_scene_render->light_instance_get_base_light(light_instance); @@ -2415,7 +2415,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c l.has_shadow = storage->light_has_shadow(light); } - RD::get_singleton()->buffer_update(gi->gi_probe_lights_uniform, 0, sizeof(GIProbeLight) * light_count, gi->gi_probe_lights); + RD::get_singleton()->buffer_update(gi->voxel_gi_lights_uniform, 0, sizeof(VoxelGILight) * light_count, gi->voxel_gi_lights); } } @@ -2424,17 +2424,17 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c if (mipmaps.size()) { //can update mipmaps - Vector3i probe_size = storage->gi_probe_get_octree_size(probe); + Vector3i probe_size = storage->voxel_gi_get_octree_size(probe); - GIProbePushConstant push_constant; + VoxelGIPushConstant push_constant; push_constant.limits[0] = probe_size.x; push_constant.limits[1] = probe_size.y; push_constant.limits[2] = probe_size.z; push_constant.stack_size = mipmaps.size(); push_constant.emission_scale = 1.0; - push_constant.propagation = storage->gi_probe_get_propagation(probe); - push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(probe); + push_constant.propagation = storage->voxel_gi_get_propagation(probe); + push_constant.dynamic_range = storage->voxel_gi_get_dynamic_range(probe); push_constant.light_count = light_count; push_constant.aniso_strength = 0; @@ -2446,7 +2446,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c int passes; if (p_update_light_instances) { - passes = storage->gi_probe_is_using_two_bounces(probe) ? 2 : 1; + passes = storage->voxel_gi_is_using_two_bounces(probe) ? 2 : 1; } else { passes = 1; //only re-blitting is necessary } @@ -2457,9 +2457,9 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c if (p_update_light_instances) { for (int i = 0; i < mipmaps.size(); i++) { if (i == 0) { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->giprobe_lighting_shader_version_pipelines[pass == 0 ? GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT : GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE]); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[pass == 0 ? VOXEL_GI_SHADER_VERSION_COMPUTE_LIGHT : VOXEL_GI_SHADER_VERSION_COMPUTE_SECOND_BOUNCE]); } else if (i == 1) { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP]); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_COMPUTE_MIPMAP]); } if (pass == 1 || i > 0) { @@ -2477,7 +2477,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c int wg_todo = (mipmaps[i].cell_count - 1) / wg_size + 1; while (wg_todo) { int wg_count = MIN(wg_todo, wg_limit_x); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbePushConstant)); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIPushConstant)); RD::get_singleton()->compute_list_dispatch(compute_list, wg_count, 1, 1); wg_todo -= wg_count; push_constant.cell_offset += wg_count * wg_size; @@ -2487,7 +2487,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c RD::get_singleton()->compute_list_add_barrier(compute_list); //wait til previous step is done } - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_WRITE_TEXTURE]); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_WRITE_TEXTURE]); for (int i = 0; i < mipmaps.size(); i++) { RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mipmaps[i].write_uniform_set, 0); @@ -2498,7 +2498,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c int wg_todo = (mipmaps[i].cell_count - 1) / wg_size + 1; while (wg_todo) { int wg_count = MIN(wg_todo, wg_limit_x); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbePushConstant)); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIPushConstant)); RD::get_singleton()->compute_list_dispatch(compute_list, wg_count, 1, 1); wg_todo -= wg_count; push_constant.cell_offset += wg_count * wg_size; @@ -2513,13 +2513,13 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c has_dynamic_object_data = false; //clear until dynamic object data is used again if (p_dynamic_objects.size() && dynamic_maps.size()) { - Vector3i octree_size = storage->gi_probe_get_octree_size(probe); + Vector3i octree_size = storage->voxel_gi_get_octree_size(probe); int multiplier = dynamic_maps[0].size / MAX(MAX(octree_size.x, octree_size.y), octree_size.z); Transform3D oversample_scale; oversample_scale.basis.scale(Vector3(multiplier, multiplier, multiplier)); - Transform3D to_cell = oversample_scale * storage->gi_probe_get_to_cell_xform(probe); + Transform3D to_cell = oversample_scale * storage->voxel_gi_get_to_cell_xform(probe); Transform3D to_world_xform = transform * to_cell.affine_inverse(); Transform3D to_probe_xform = to_world_xform.affine_inverse(); @@ -2529,7 +2529,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c for (int i = 0; i < (int)p_dynamic_objects.size(); i++) { RendererSceneRender::GeometryInstance *instance = p_dynamic_objects[i]; - //transform aabb to giprobe + //transform aabb to voxel_gi AABB aabb = (to_probe_xform * p_scene_render->geometry_instance_get_transform(instance)).xform(p_scene_render->geometry_instance_get_aabb(instance)); //this needs to wrap to grid resolution to avoid jitter @@ -2601,8 +2601,8 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c p_scene_render->_render_material(to_world_xform * xform, cm, true, p_scene_render->cull_argument, dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size)); - GIProbeDynamicPushConstant push_constant; - memset(&push_constant, 0, sizeof(GIProbeDynamicPushConstant)); + VoxelGIDynamicPushConstant push_constant; + memset(&push_constant, 0, sizeof(VoxelGIDynamicPushConstant)); push_constant.limits[0] = octree_size.x; push_constant.limits[1] = octree_size.y; push_constant.limits[2] = octree_size.z; @@ -2619,7 +2619,7 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c push_constant.z_base = xform.origin[z_axis]; push_constant.z_sign = (z_flip ? -1.0 : 1.0); push_constant.pos_multiplier = float(1.0) / multiplier; - push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(probe); + push_constant.dynamic_range = storage->voxel_gi_get_dynamic_range(probe); push_constant.flip_x = x_flip; push_constant.flip_y = y_flip; push_constant.rect_pos[0] = rect.position[0]; @@ -2631,16 +2631,16 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c push_constant.prev_rect_size[0] = 0; push_constant.prev_rect_size[1] = 0; push_constant.on_mipmap = false; - push_constant.propagation = storage->gi_probe_get_propagation(probe); + push_constant.propagation = storage->voxel_gi_get_propagation(probe); push_constant.pad[0] = 0; push_constant.pad[1] = 0; push_constant.pad[2] = 0; //process lighting RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING]); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING]); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, dynamic_maps[0].uniform_set, 0); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbeDynamicPushConstant)); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIDynamicPushConstant)); RD::get_singleton()->compute_list_dispatch(compute_list, (rect.size.x - 1) / 8 + 1, (rect.size.y - 1) / 8 + 1, 1); //print_line("rect: " + itos(i) + ": " + rect); @@ -2695,14 +2695,14 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c RD::get_singleton()->compute_list_add_barrier(compute_list); if (dynamic_maps[k].mipmap < 0) { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE]); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_WRITE]); } else if (k < dynamic_maps.size() - 1) { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT]); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT]); } else { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT]); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_PLOT]); } RD::get_singleton()->compute_list_bind_uniform_set(compute_list, dynamic_maps[k].uniform_set, 0); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbeDynamicPushConstant)); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIDynamicPushConstant)); RD::get_singleton()->compute_list_dispatch(compute_list, (rect.size.x - 1) / 8 + 1, (rect.size.y - 1) / 8 + 1, 1); } @@ -2713,22 +2713,22 @@ void RendererSceneGIRD::GIProbeInstance::update(bool p_update_light_instances, c has_dynamic_object_data = true; //clear until dynamic object data is used again } - last_probe_version = storage->gi_probe_get_version(probe); + last_probe_version = storage->voxel_gi_get_version(probe); } -void RendererSceneGIRD::GIProbeInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { +void RendererSceneGIRD::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { if (mipmaps.size() == 0) { return; } - CameraMatrix cam_transform = (p_camera_with_transform * CameraMatrix(transform)) * CameraMatrix(storage->gi_probe_get_to_cell_xform(probe).affine_inverse()); + CameraMatrix cam_transform = (p_camera_with_transform * CameraMatrix(transform)) * CameraMatrix(storage->voxel_gi_get_to_cell_xform(probe).affine_inverse()); int level = 0; - Vector3i octree_size = storage->gi_probe_get_octree_size(probe); + Vector3i octree_size = storage->voxel_gi_get_octree_size(probe); - GIProbeDebugPushConstant push_constant; + VoxelGIDebugPushConstant push_constant; push_constant.alpha = p_alpha; - push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(probe); + push_constant.dynamic_range = storage->voxel_gi_get_dynamic_range(probe); push_constant.cell_offset = mipmaps[level].cell_offset; push_constant.level = level; @@ -2743,15 +2743,15 @@ void RendererSceneGIRD::GIProbeInstance::debug(RD::DrawListID p_draw_list, RID p } } - if (gi->giprobe_debug_uniform_set.is_valid()) { - RD::get_singleton()->free(gi->giprobe_debug_uniform_set); + if (gi->voxel_gi_debug_uniform_set.is_valid()) { + RD::get_singleton()->free(gi->voxel_gi_debug_uniform_set); } Vector uniforms; { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; - u.ids.push_back(storage->gi_probe_get_data_buffer(probe)); + u.ids.push_back(storage->voxel_gi_get_data_buffer(probe)); uniforms.push_back(u); } { @@ -2776,19 +2776,19 @@ void RendererSceneGIRD::GIProbeInstance::debug(RD::DrawListID p_draw_list, RID p cell_count = mipmaps[level].cell_count; } - gi->giprobe_debug_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->giprobe_debug_shader_version_shaders[0], 0); + gi->voxel_gi_debug_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->voxel_gi_debug_shader_version_shaders[0], 0); - int giprobe_debug_pipeline = GI_PROBE_DEBUG_COLOR; + int voxel_gi_debug_pipeline = VOXEL_GI_DEBUG_COLOR; if (p_emission) { - giprobe_debug_pipeline = GI_PROBE_DEBUG_EMISSION; + voxel_gi_debug_pipeline = VOXEL_GI_DEBUG_EMISSION; } else if (p_lighting) { - giprobe_debug_pipeline = has_dynamic_object_data ? GI_PROBE_DEBUG_LIGHT_FULL : GI_PROBE_DEBUG_LIGHT; + voxel_gi_debug_pipeline = has_dynamic_object_data ? VOXEL_GI_DEBUG_LIGHT_FULL : VOXEL_GI_DEBUG_LIGHT; } RD::get_singleton()->draw_list_bind_render_pipeline( p_draw_list, - gi->giprobe_debug_shader_version_pipelines[giprobe_debug_pipeline].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, gi->giprobe_debug_uniform_set, 0); - RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(GIProbeDebugPushConstant)); + gi->voxel_gi_debug_shader_version_pipelines[voxel_gi_debug_pipeline].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, gi->voxel_gi_debug_uniform_set, 0); + RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(VoxelGIDebugPushConstant)); RD::get_singleton()->draw_list_draw(p_draw_list, false, cell_count, 36); } @@ -2812,13 +2812,13 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p { //kinda complicated to compute the amount of slots, we try to use as many as we can - gi_probe_max_lights = 32; + voxel_gi_max_lights = 32; - gi_probe_lights = memnew_arr(GIProbeLight, gi_probe_max_lights); - gi_probe_lights_uniform = RD::get_singleton()->uniform_buffer_create(gi_probe_max_lights * sizeof(GIProbeLight)); - gi_probe_quality = RS::GIProbeQuality(CLAMP(int(GLOBAL_GET("rendering/global_illumination/gi_probes/quality")), 0, 1)); + voxel_gi_lights = memnew_arr(VoxelGILight, voxel_gi_max_lights); + voxel_gi_lights_uniform = RD::get_singleton()->uniform_buffer_create(voxel_gi_max_lights * sizeof(VoxelGILight)); + voxel_gi_quality = RS::VoxelGIQuality(CLAMP(int(GLOBAL_GET("rendering/global_illumination/voxel_gi/quality")), 0, 1)); - String defines = "\n#define MAX_LIGHTS " + itos(gi_probe_max_lights) + "\n"; + String defines = "\n#define MAX_LIGHTS " + itos(voxel_gi_max_lights) + "\n"; Vector versions; versions.push_back("\n#define MODE_COMPUTE_LIGHT\n"); @@ -2830,11 +2830,11 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p versions.push_back("\n#define MODE_DYNAMIC\n#define MODE_DYNAMIC_SHRINK\n#define MODE_DYNAMIC_SHRINK_PLOT\n"); versions.push_back("\n#define MODE_DYNAMIC\n#define MODE_DYNAMIC_SHRINK\n#define MODE_DYNAMIC_SHRINK_PLOT\n#define MODE_DYNAMIC_SHRINK_WRITE\n"); - giprobe_shader.initialize(versions, defines); - giprobe_lighting_shader_version = giprobe_shader.version_create(); - for (int i = 0; i < GI_PROBE_SHADER_VERSION_MAX; i++) { - giprobe_lighting_shader_version_shaders[i] = giprobe_shader.version_get_shader(giprobe_lighting_shader_version, i); - giprobe_lighting_shader_version_pipelines[i] = RD::get_singleton()->compute_pipeline_create(giprobe_lighting_shader_version_shaders[i]); + voxel_gi_shader.initialize(versions, defines); + voxel_gi_lighting_shader_version = voxel_gi_shader.version_create(); + for (int i = 0; i < VOXEL_GI_SHADER_VERSION_MAX; i++) { + voxel_gi_lighting_shader_version_shaders[i] = voxel_gi_shader.version_get_shader(voxel_gi_lighting_shader_version, i); + voxel_gi_lighting_shader_version_pipelines[i] = RD::get_singleton()->compute_pipeline_create(voxel_gi_lighting_shader_version_shaders[i]); } } @@ -2846,10 +2846,10 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p versions.push_back("\n#define MODE_DEBUG_EMISSION\n"); versions.push_back("\n#define MODE_DEBUG_LIGHT\n#define MODE_DEBUG_LIGHT_FULL\n"); - giprobe_debug_shader.initialize(versions, defines); - giprobe_debug_shader_version = giprobe_debug_shader.version_create(); - for (int i = 0; i < GI_PROBE_DEBUG_MAX; i++) { - giprobe_debug_shader_version_shaders[i] = giprobe_debug_shader.version_get_shader(giprobe_debug_shader_version, i); + voxel_gi_debug_shader.initialize(versions, defines); + voxel_gi_debug_shader_version = voxel_gi_debug_shader.version_create(); + for (int i = 0; i < VOXEL_GI_DEBUG_MAX; i++) { + voxel_gi_debug_shader_version_shaders[i] = voxel_gi_debug_shader.version_get_shader(voxel_gi_debug_shader_version, i); RD::PipelineRasterizationState rs; rs.cull_mode = RD::POLYGON_CULL_FRONT; @@ -2858,7 +2858,7 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p ds.enable_depth_write = true; ds.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL; - giprobe_debug_shader_version_pipelines[i].setup(giprobe_debug_shader_version_shaders[i], RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0); + voxel_gi_debug_shader_version_pipelines[i].setup(voxel_gi_debug_shader_version_shaders[i], RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0); } } @@ -2944,12 +2944,12 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p //calculate tables String defines = "\n#define SDFGI_OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; Vector gi_modes; - gi_modes.push_back("\n#define USE_GIPROBES\n"); + gi_modes.push_back("\n#define USE_VOXEL_GI_INSTANCES\n"); gi_modes.push_back("\n#define USE_SDFGI\n"); - gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_GIPROBES\n"); - gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_GIPROBES\n"); + gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n"); + gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_VOXEL_GI_INSTANCES\n"); gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n"); - gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n\n#define USE_GIPROBES\n"); + gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n"); shader.initialize(gi_modes, defines); shader_version = shader.version_create(); @@ -2991,17 +2991,17 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p } } } - default_giprobe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GIProbeData) * MAX_GIPROBES); + default_voxel_gi_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(VoxelGIData) * MAX_VOXEL_GI_INSTANCES); half_resolution = GLOBAL_GET("rendering/global_illumination/gi/use_half_resolution"); } void RendererSceneGIRD::free() { - RD::get_singleton()->free(default_giprobe_buffer); - RD::get_singleton()->free(gi_probe_lights_uniform); + RD::get_singleton()->free(default_voxel_gi_buffer); + RD::get_singleton()->free(voxel_gi_lights_uniform); RD::get_singleton()->free(sdfgi_ubo); - giprobe_debug_shader.version_free(giprobe_debug_shader_version); - giprobe_shader.version_free(giprobe_lighting_shader_version); + voxel_gi_debug_shader.version_free(voxel_gi_debug_shader_version); + voxel_gi_shader.version_free(voxel_gi_lighting_shader_version); shader.version_free(shader_version); sdfgi_shader.debug_probes.version_free(sdfgi_shader.debug_probes_shader); sdfgi_shader.debug.version_free(sdfgi_shader.debug_shader); @@ -3009,7 +3009,7 @@ void RendererSceneGIRD::free() { sdfgi_shader.integrate.version_free(sdfgi_shader.integrate_shader); sdfgi_shader.preprocess.version_free(sdfgi_shader.preprocess_shader); - memdelete_arr(gi_probe_lights); + memdelete_arr(voxel_gi_lights); } RendererSceneGIRD::SDFGI *RendererSceneGIRD::create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) { @@ -3020,36 +3020,36 @@ RendererSceneGIRD::SDFGI *RendererSceneGIRD::create_sdfgi(RendererSceneEnvironme return sdfgi; } -void RendererSceneGIRD::setup_giprobes(RID p_render_buffers, const Transform3D &p_transform, const PagedArray &p_gi_probes, uint32_t &r_gi_probes_used, RendererSceneRenderRD *p_scene_render) { - r_gi_probes_used = 0; +void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) { + r_voxel_gi_instances_used = 0; // feels a little dirty to use our container this way but.... RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND(rb == nullptr); - RID gi_probe_buffer = p_scene_render->render_buffers_get_gi_probe_buffer(p_render_buffers); + RID voxel_gi_buffer = p_scene_render->render_buffers_get_voxel_gi_buffer(p_render_buffers); - RD::get_singleton()->draw_command_begin_label("GIProbes Setup"); + RD::get_singleton()->draw_command_begin_label("VoxelGIs Setup"); - GIProbeData gi_probe_data[MAX_GIPROBES]; + VoxelGIData voxel_gi_data[MAX_VOXEL_GI_INSTANCES]; - bool giprobes_changed = false; + bool voxel_gi_instances_changed = false; Transform3D to_camera; to_camera.origin = p_transform.origin; //only translation, make local - for (int i = 0; i < MAX_GIPROBES; i++) { + for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) { RID texture; - if (i < (int)p_gi_probes.size()) { - GIProbeInstance *gipi = get_probe_instance(p_gi_probes[i]); + if (i < (int)p_voxel_gi_instances.size()) { + VoxelGIInstance *gipi = get_probe_instance(p_voxel_gi_instances[i]); if (gipi) { texture = gipi->texture; - GIProbeData &gipd = gi_probe_data[i]; + VoxelGIData &gipd = voxel_gi_data[i]; RID base_probe = gipi->probe; - Transform3D to_cell = storage->gi_probe_get_to_cell_xform(gipi->probe) * gipi->transform.affine_inverse() * to_camera; + Transform3D to_cell = storage->voxel_gi_get_to_cell_xform(gipi->probe) * gipi->transform.affine_inverse() * to_camera; gipd.xform[0] = to_cell.basis.elements[0][0]; gipd.xform[1] = to_cell.basis.elements[1][0]; @@ -3068,36 +3068,36 @@ void RendererSceneGIRD::setup_giprobes(RID p_render_buffers, const Transform3D & gipd.xform[14] = to_cell.origin.z; gipd.xform[15] = 1; - Vector3 bounds = storage->gi_probe_get_octree_size(base_probe); + Vector3 bounds = storage->voxel_gi_get_octree_size(base_probe); gipd.bounds[0] = bounds.x; gipd.bounds[1] = bounds.y; gipd.bounds[2] = bounds.z; - gipd.dynamic_range = storage->gi_probe_get_dynamic_range(base_probe) * storage->gi_probe_get_energy(base_probe); - gipd.bias = storage->gi_probe_get_bias(base_probe); - gipd.normal_bias = storage->gi_probe_get_normal_bias(base_probe); - gipd.blend_ambient = !storage->gi_probe_is_interior(base_probe); + gipd.dynamic_range = storage->voxel_gi_get_dynamic_range(base_probe) * storage->voxel_gi_get_energy(base_probe); + gipd.bias = storage->voxel_gi_get_bias(base_probe); + gipd.normal_bias = storage->voxel_gi_get_normal_bias(base_probe); + gipd.blend_ambient = !storage->voxel_gi_is_interior(base_probe); gipd.anisotropy_strength = 0; - gipd.ao = storage->gi_probe_get_ao(base_probe); - gipd.ao_size = Math::pow(storage->gi_probe_get_ao_size(base_probe), 4.0f); + gipd.ao = storage->voxel_gi_get_ao(base_probe); + gipd.ao_size = Math::pow(storage->voxel_gi_get_ao_size(base_probe), 4.0f); gipd.mipmaps = gipi->mipmaps.size(); } - r_gi_probes_used++; + r_voxel_gi_instances_used++; } if (texture == RID()) { texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); } - if (texture != rb->gi.giprobe_textures[i]) { - giprobes_changed = true; - rb->gi.giprobe_textures[i] = texture; + if (texture != rb->gi.voxel_gi_textures[i]) { + voxel_gi_instances_changed = true; + rb->gi.voxel_gi_textures[i] = texture; } } - if (giprobes_changed) { + if (voxel_gi_instances_changed) { if (RD::get_singleton()->uniform_set_is_valid(rb->gi.uniform_set)) { RD::get_singleton()->free(rb->gi.uniform_set); } @@ -3112,14 +3112,14 @@ void RendererSceneGIRD::setup_giprobes(RID p_render_buffers, const Transform3D & } } - if (p_gi_probes.size() > 0) { - RD::get_singleton()->buffer_update(gi_probe_buffer, 0, sizeof(GIProbeData) * MIN((uint64_t)MAX_GIPROBES, p_gi_probes.size()), gi_probe_data, RD::BARRIER_MASK_COMPUTE); + if (p_voxel_gi_instances.size() > 0) { + RD::get_singleton()->buffer_update(voxel_gi_buffer, 0, sizeof(VoxelGIData) * MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size()), voxel_gi_data, RD::BARRIER_MASK_COMPUTE); } RD::get_singleton()->draw_command_end_label(); } -void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform3D &p_transform, const PagedArray &p_gi_probes, RendererSceneRenderRD *p_scene_render) { +void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform3D &p_transform, const PagedArray &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) { RD::get_singleton()->draw_command_begin_label("GI Render"); RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.getornull(p_render_buffers); @@ -3157,11 +3157,11 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ push_constant.proj_info[1] = -2.0f / (rb->height * p_projection.matrix[1][1]); push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0]; push_constant.proj_info[3] = (1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1]; - push_constant.max_giprobes = MIN((uint64_t)MAX_GIPROBES, p_gi_probes.size()); - push_constant.high_quality_vct = gi_probe_quality == RS::GI_PROBE_QUALITY_HIGH; + push_constant.max_voxel_gi_instances = MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size()); + push_constant.high_quality_vct = voxel_gi_quality == RS::VOXEL_GI_QUALITY_HIGH; bool use_sdfgi = rb->sdfgi != nullptr; - bool use_giprobes = push_constant.max_giprobes > 0; + bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0; if (env) { push_constant.ao_color[0] = env->ao_color.r; @@ -3311,7 +3311,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 14; - RID buffer = p_gi_probe_buffer.is_valid() ? p_gi_probe_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); u.ids.push_back(buffer); uniforms.push_back(u); } @@ -3326,15 +3326,15 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 16; - u.ids.push_back(rb->gi.giprobe_buffer); + u.ids.push_back(rb->gi.voxel_gi_buffer); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 17; - for (int i = 0; i < MAX_GIPROBES; i++) { - u.ids.push_back(rb->gi.giprobe_textures[i]); + for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) { + u.ids.push_back(rb->gi.voxel_gi_textures[i]); } uniforms.push_back(u); } @@ -3345,9 +3345,9 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ Mode mode; if (rb->gi.using_half_size_gi) { - mode = (use_sdfgi && use_giprobes) ? MODE_HALF_RES_COMBINED : (use_sdfgi ? MODE_HALF_RES_SDFGI : MODE_HALF_RES_GIPROBE); + mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_HALF_RES_COMBINED : (use_sdfgi ? MODE_HALF_RES_SDFGI : MODE_HALF_RES_VOXEL_GI); } else { - mode = (use_sdfgi && use_giprobes) ? MODE_COMBINED : (use_sdfgi ? MODE_SDFGI : MODE_GIPROBE); + mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED : (use_sdfgi ? MODE_SDFGI : MODE_VOXEL_GI); } RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(true); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[mode]); @@ -3364,39 +3364,39 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ RD::get_singleton()->draw_command_end_label(); } -RID RendererSceneGIRD::gi_probe_instance_create(RID p_base) { - GIProbeInstance gi_probe; - gi_probe.gi = this; - gi_probe.storage = storage; - gi_probe.probe = p_base; - RID rid = gi_probe_instance_owner.make_rid(gi_probe); +RID RendererSceneGIRD::voxel_gi_instance_create(RID p_base) { + VoxelGIInstance voxel_gi; + voxel_gi.gi = this; + voxel_gi.storage = storage; + voxel_gi.probe = p_base; + RID rid = voxel_gi_instance_owner.make_rid(voxel_gi); return rid; } -void RendererSceneGIRD::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) { - GIProbeInstance *gi_probe = get_probe_instance(p_probe); - ERR_FAIL_COND(!gi_probe); +void RendererSceneGIRD::voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) { + VoxelGIInstance *voxel_gi = get_probe_instance(p_probe); + ERR_FAIL_COND(!voxel_gi); - gi_probe->transform = p_xform; + voxel_gi->transform = p_xform; } -bool RendererSceneGIRD::gi_probe_needs_update(RID p_probe) const { - GIProbeInstance *gi_probe = get_probe_instance(p_probe); - ERR_FAIL_COND_V(!gi_probe, false); +bool RendererSceneGIRD::voxel_gi_needs_update(RID p_probe) const { + VoxelGIInstance *voxel_gi = get_probe_instance(p_probe); + ERR_FAIL_COND_V(!voxel_gi, false); - return gi_probe->last_probe_version != storage->gi_probe_get_version(gi_probe->probe); + return voxel_gi->last_probe_version != storage->voxel_gi_get_version(voxel_gi->probe); } -void RendererSceneGIRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector &p_light_instances, const PagedArray &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) { - GIProbeInstance *gi_probe = get_probe_instance(p_probe); - ERR_FAIL_COND(!gi_probe); +void RendererSceneGIRD::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector &p_light_instances, const PagedArray &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) { + VoxelGIInstance *voxel_gi = get_probe_instance(p_probe); + ERR_FAIL_COND(!voxel_gi); - gi_probe->update(p_update_light_instances, p_light_instances, p_dynamic_objects, p_scene_render); + voxel_gi->update(p_update_light_instances, p_light_instances, p_dynamic_objects, p_scene_render); } -void RendererSceneGIRD::debug_giprobe(RID p_gi_probe, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { - GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); +void RendererSceneGIRD::debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { + VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.getornull(p_voxel_gi); + ERR_FAIL_COND(!voxel_gi); - gi_probe->debug(p_draw_list, p_framebuffer, p_camera_with_transform, p_lighting, p_emission, p_alpha); + voxel_gi->debug(p_draw_list, p_framebuffer, p_camera_with_transform, p_lighting, p_emission, p_alpha); } diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h index 3394e31831..45fc7b3951 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h @@ -38,13 +38,13 @@ #include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h" #include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/renderer_rd/shaders/gi.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/giprobe.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/giprobe_debug.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/voxel_gi.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl.gen.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" @@ -56,9 +56,9 @@ class RendererSceneGIRD { private: RendererStorageRD *storage; - /* GIPROBE INSTANCE */ + /* VOXEL_GI INSTANCE */ - struct GIProbeLight { + struct VoxelGILight { uint32_t type; float energy; float radius; @@ -74,7 +74,7 @@ private: uint32_t has_shadow; }; - struct GIProbePushConstant { + struct VoxelGIPushConstant { int32_t limits[3]; uint32_t stack_size; @@ -89,7 +89,7 @@ private: uint32_t pad; }; - struct GIProbeDynamicPushConstant { + struct VoxelGIDynamicPushConstant { int32_t limits[3]; uint32_t light_count; int32_t x_dir[3]; @@ -110,36 +110,36 @@ private: float pad[3]; }; - GIProbeLight *gi_probe_lights; - uint32_t gi_probe_max_lights; - RID gi_probe_lights_uniform; + VoxelGILight *voxel_gi_lights; + uint32_t voxel_gi_max_lights; + RID voxel_gi_lights_uniform; enum { - GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT, - GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE, - GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP, - GI_PROBE_SHADER_VERSION_WRITE_TEXTURE, - GI_PROBE_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING, - GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE, - GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT, - GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT, - GI_PROBE_SHADER_VERSION_MAX + VOXEL_GI_SHADER_VERSION_COMPUTE_LIGHT, + VOXEL_GI_SHADER_VERSION_COMPUTE_SECOND_BOUNCE, + VOXEL_GI_SHADER_VERSION_COMPUTE_MIPMAP, + VOXEL_GI_SHADER_VERSION_WRITE_TEXTURE, + VOXEL_GI_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING, + VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_WRITE, + VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_PLOT, + VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT, + VOXEL_GI_SHADER_VERSION_MAX }; - GiprobeShaderRD giprobe_shader; - RID giprobe_lighting_shader_version; - RID giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_MAX]; - RID giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_MAX]; + VoxelGiShaderRD voxel_gi_shader; + RID voxel_gi_lighting_shader_version; + RID voxel_gi_lighting_shader_version_shaders[VOXEL_GI_SHADER_VERSION_MAX]; + RID voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_MAX]; enum { - GI_PROBE_DEBUG_COLOR, - GI_PROBE_DEBUG_LIGHT, - GI_PROBE_DEBUG_EMISSION, - GI_PROBE_DEBUG_LIGHT_FULL, - GI_PROBE_DEBUG_MAX + VOXEL_GI_DEBUG_COLOR, + VOXEL_GI_DEBUG_LIGHT, + VOXEL_GI_DEBUG_EMISSION, + VOXEL_GI_DEBUG_LIGHT_FULL, + VOXEL_GI_DEBUG_MAX }; - struct GIProbeDebugPushConstant { + struct VoxelGIDebugPushConstant { float projection[16]; uint32_t cell_offset; float dynamic_range; @@ -149,11 +149,11 @@ private: uint32_t pad; }; - GiprobeDebugShaderRD giprobe_debug_shader; - RID giprobe_debug_shader_version; - RID giprobe_debug_shader_version_shaders[GI_PROBE_DEBUG_MAX]; - PipelineCacheRD giprobe_debug_shader_version_pipelines[GI_PROBE_DEBUG_MAX]; - RID giprobe_debug_uniform_set; + VoxelGiDebugShaderRD voxel_gi_debug_shader; + RID voxel_gi_debug_shader_version; + RID voxel_gi_debug_shader_version_shaders[VOXEL_GI_DEBUG_MAX]; + PipelineCacheRD voxel_gi_debug_shader_version_pipelines[VOXEL_GI_DEBUG_MAX]; + RID voxel_gi_debug_uniform_set; /* SDFGI */ @@ -326,11 +326,11 @@ private: } sdfgi_shader; public: - /* GIPROBE INSTANCE */ + /* VOXEL_GI INSTANCE */ - //@TODO GIProbeInstance is still directly used in the render code, we'll address this when we refactor the render code itself. + //@TODO VoxelGIInstance is still directly used in the render code, we'll address this when we refactor the render code itself. - struct GIProbeInstance { + struct VoxelGIInstance { // access to our containers RendererStorageRD *storage; RendererSceneGIRD *gi; @@ -380,19 +380,19 @@ public: void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); }; - mutable RID_Owner gi_probe_instance_owner; + mutable RID_Owner voxel_gi_instance_owner; - _FORCE_INLINE_ GIProbeInstance *get_probe_instance(RID p_probe) const { - return gi_probe_instance_owner.getornull(p_probe); + _FORCE_INLINE_ VoxelGIInstance *get_probe_instance(RID p_probe) const { + return voxel_gi_instance_owner.getornull(p_probe); }; - _FORCE_INLINE_ RID gi_probe_instance_get_texture(RID p_probe) { - GIProbeInstance *gi_probe = get_probe_instance(p_probe); - ERR_FAIL_COND_V(!gi_probe, RID()); - return gi_probe->texture; + _FORCE_INLINE_ RID voxel_gi_instance_get_texture(RID p_probe) { + VoxelGIInstance *voxel_gi = get_probe_instance(p_probe); + ERR_FAIL_COND_V(!voxel_gi, RID()); + return voxel_gi->texture; }; - RS::GIProbeQuality gi_probe_quality = RS::GI_PROBE_QUALITY_HIGH; + RS::VoxelGIQuality voxel_gi_quality = RS::VOXEL_GI_QUALITY_HIGH; /* SDFGI */ @@ -551,13 +551,13 @@ public: /* GI */ enum { - MAX_GIPROBES = 8 + MAX_VOXEL_GI_INSTANCES = 8 }; // Struct for use in render buffer struct RenderBuffersGI { - RID giprobe_textures[MAX_GIPROBES]; - RID giprobe_buffer; + RID voxel_gi_textures[MAX_VOXEL_GI_INSTANCES]; + RID voxel_gi_buffer; RID full_buffer; RID full_dispatch; @@ -601,7 +601,7 @@ public: ProbeCascadeData cascades[SDFGI::MAX_CASCADES]; }; - struct GIProbeData { + struct VoxelGIData { float xform[16]; float bounds[3]; float dynamic_range; @@ -624,7 +624,7 @@ public: float proj_info[4]; float ao_color[3]; - uint32_t max_giprobes; + uint32_t max_voxel_gi_instances; uint32_t high_quality_vct; uint32_t orthogonal; @@ -635,16 +635,16 @@ public: RID sdfgi_ubo; enum Mode { - MODE_GIPROBE, + MODE_VOXEL_GI, MODE_SDFGI, MODE_COMBINED, - MODE_HALF_RES_GIPROBE, + MODE_HALF_RES_VOXEL_GI, MODE_HALF_RES_SDFGI, MODE_HALF_RES_COMBINED, MODE_MAX }; - RID default_giprobe_buffer; + RID default_voxel_gi_buffer; bool half_resolution = false; GiShaderRD shader; @@ -659,14 +659,14 @@ public: SDFGI *create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size); - void setup_giprobes(RID p_render_buffers, const Transform3D &p_transform, const PagedArray &p_gi_probes, uint32_t &r_gi_probes_used, RendererSceneRenderRD *p_scene_render); - void process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform3D &p_transform, const PagedArray &p_gi_probes, RendererSceneRenderRD *p_scene_render); + void setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render); + void process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform3D &p_transform, const PagedArray &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render); - RID gi_probe_instance_create(RID p_base); - void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform); - bool gi_probe_needs_update(RID p_probe) const; - void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector &p_light_instances, const PagedArray &p_dynamic_objects, RendererSceneRenderRD *p_scene_render); - void debug_giprobe(RID p_gi_probe, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); + RID voxel_gi_instance_create(RID p_base); + void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform); + bool voxel_gi_needs_update(RID p_probe) const; + void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector &p_light_instances, const PagedArray &p_dynamic_objects, RendererSceneRenderRD *p_scene_render); + void debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); }; #endif /* !RENDERING_SERVER_SCENE_GI_RD_H */ diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 0698a5f952..ff7e6c502f 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -1326,28 +1326,28 @@ void RendererSceneRenderRD::lightmap_instance_set_transform(RID p_lightmap, cons ///////////////////////////////// -RID RendererSceneRenderRD::gi_probe_instance_create(RID p_base) { - return gi.gi_probe_instance_create(p_base); +RID RendererSceneRenderRD::voxel_gi_instance_create(RID p_base) { + return gi.voxel_gi_instance_create(p_base); } -void RendererSceneRenderRD::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) { - gi.gi_probe_instance_set_transform_to_data(p_probe, p_xform); +void RendererSceneRenderRD::voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) { + gi.voxel_gi_instance_set_transform_to_data(p_probe, p_xform); } -bool RendererSceneRenderRD::gi_probe_needs_update(RID p_probe) const { +bool RendererSceneRenderRD::voxel_gi_needs_update(RID p_probe) const { if (!is_dynamic_gi_supported()) { return false; } - return gi.gi_probe_needs_update(p_probe); + return gi.voxel_gi_needs_update(p_probe); } -void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector &p_light_instances, const PagedArray &p_dynamic_objects) { +void RendererSceneRenderRD::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector &p_light_instances, const PagedArray &p_dynamic_objects) { if (!is_dynamic_gi_supported()) { return; } - gi.gi_probe_update(p_probe, p_update_light_instances, p_light_instances, p_dynamic_objects, this); + gi.voxel_gi_update(p_probe, p_update_light_instances, p_light_instances, p_dynamic_objects, this); } void RendererSceneRenderRD::_debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform) { @@ -1959,17 +1959,17 @@ RID RendererSceneRenderRD::render_buffers_get_ao_texture(RID p_render_buffers) { return rb->ssao.ao_final; } -RID RendererSceneRenderRD::render_buffers_get_gi_probe_buffer(RID p_render_buffers) { +RID RendererSceneRenderRD::render_buffers_get_voxel_gi_buffer(RID p_render_buffers) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(!rb, RID()); - if (rb->gi.giprobe_buffer.is_null()) { - rb->gi.giprobe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(RendererSceneGIRD::GIProbeData) * RendererSceneGIRD::MAX_GIPROBES); + if (rb->gi.voxel_gi_buffer.is_null()) { + rb->gi.voxel_gi_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(RendererSceneGIRD::VoxelGIData) * RendererSceneGIRD::MAX_VOXEL_GI_INSTANCES); } - return rb->gi.giprobe_buffer; + return rb->gi.voxel_gi_buffer; } -RID RendererSceneRenderRD::render_buffers_get_default_gi_probe_buffer() { - return gi.default_giprobe_buffer; +RID RendererSceneRenderRD::render_buffers_get_default_voxel_gi_buffer() { + return gi.default_voxel_gi_buffer; } RID RendererSceneRenderRD::render_buffers_get_gi_ambient_texture(RID p_render_buffers) { @@ -3066,7 +3066,7 @@ void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) { rb->volumetric_fog = nullptr; } -void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_gi_probe_count) { +void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count) { ERR_FAIL_COND(!is_clustered_enabled()); // can't use volumetric fog without clustered RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND(!rb); @@ -3228,7 +3228,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 11; - u.ids.push_back(render_buffers_get_gi_probe_buffer(p_render_buffers)); + u.ids.push_back(render_buffers_get_voxel_gi_buffer(p_render_buffers)); uniforms.push_back(u); } @@ -3236,8 +3236,8 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 12; - for (int i = 0; i < RendererSceneGIRD::MAX_GIPROBES; i++) { - u.ids.push_back(rb->gi.giprobe_textures[i]); + for (int i = 0; i < RendererSceneGIRD::MAX_VOXEL_GI_INSTANCES; i++) { + u.ids.push_back(rb->gi.voxel_gi_textures[i]); } uniforms.push_back(u); } @@ -3362,7 +3362,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e params.cam_rotation[10] = p_cam_transform.basis[2][2]; params.cam_rotation[11] = 0; params.filter_axis = 0; - params.max_gi_probes = env->volumetric_fog_gi_inject > 0.001 ? p_gi_probe_count : 0; + params.max_voxel_gi_instances = env->volumetric_fog_gi_inject > 0.001 ? p_voxel_gi_count : 0; params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES; Transform3D to_prev_cam_view = rb->volumetric_fog->prev_cam_transform.affine_inverse() * p_cam_transform; @@ -3492,7 +3492,7 @@ void RendererSceneRenderRD::_pre_resolve_render(RenderDataRD *p_render_data, boo } } -void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_gi, RID p_normal_roughness_buffer, RID p_gi_probe_buffer) { +void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_gi, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer) { // Render shadows while GI is rendering, due to how barriers are handled, this should happen at the same time if (p_render_data->render_buffers.is_valid() && p_use_gi) { @@ -3569,7 +3569,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool //start GI if (render_gi) { - gi.process_gi(p_render_data->render_buffers, p_normal_roughness_buffer, p_gi_probe_buffer, p_render_data->environment, p_render_data->cam_projection, p_render_data->cam_transform, *p_render_data->gi_probes, this); + gi.process_gi(p_render_data->render_buffers, p_normal_roughness_buffer, p_voxel_gi_buffer, p_render_data->environment, p_render_data->cam_projection, p_render_data->cam_transform, *p_render_data->voxel_gi_instances, this); } //Do shadow rendering (in parallel with GI) @@ -3625,12 +3625,12 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool } } if (is_volumetric_supported()) { - _update_volumetric_fog(p_render_data->render_buffers, p_render_data->environment, p_render_data->cam_projection, p_render_data->cam_transform, p_render_data->shadow_atlas, directional_light_count, directional_shadows, positional_light_count, render_state.gi_probe_count); + _update_volumetric_fog(p_render_data->render_buffers, p_render_data->environment, p_render_data->cam_projection, p_render_data->cam_transform, p_render_data->shadow_atlas, directional_light_count, directional_shadows, positional_light_count, render_state.voxel_gi_count); } } } -void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray &p_instances, const PagedArray &p_lights, const PagedArray &p_reflection_probes, const PagedArray &p_gi_probes, const PagedArray &p_decals, const PagedArray &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data) { +void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray &p_instances, const PagedArray &p_lights, const PagedArray &p_reflection_probes, const PagedArray &p_voxel_gi_instances, const PagedArray &p_decals, const PagedArray &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data) { // getting this here now so we can direct call a bunch of things more easily RenderBuffers *rb = nullptr; if (p_render_buffers.is_valid()) { @@ -3652,7 +3652,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform3D render_data.instances = &p_instances; render_data.lights = &p_lights; render_data.reflection_probes = &p_reflection_probes; - render_data.gi_probes = &p_gi_probes; + render_data.voxel_gi_instances = &p_voxel_gi_instances; render_data.decals = &p_decals; render_data.lightmaps = &p_lightmaps; render_data.environment = p_environment; @@ -3683,7 +3683,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform3D if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) { render_data.lights = ∅ render_data.reflection_probes = ∅ - render_data.gi_probes = ∅ + render_data.voxel_gi_instances = ∅ } //sdfgi first @@ -3703,12 +3703,12 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform3D clear_color = storage->get_default_clear_color(); } - //assign render indices to giprobes + //assign render indices to voxel_gi_instances if (is_dynamic_gi_supported()) { - for (uint32_t i = 0; i < (uint32_t)p_gi_probes.size(); i++) { - RendererSceneGIRD::GIProbeInstance *giprobe_inst = gi.gi_probe_instance_owner.getornull(p_gi_probes[i]); - if (giprobe_inst) { - giprobe_inst->render_index = i; + for (uint32_t i = 0; i < (uint32_t)p_voxel_gi_instances.size(); i++) { + RendererSceneGIRD::VoxelGIInstance *voxel_gi_inst = gi.voxel_gi_instance_owner.getornull(p_voxel_gi_instances[i]); + if (voxel_gi_inst) { + voxel_gi_inst->render_index = i; } } } @@ -3736,9 +3736,9 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform3D rb->sdfgi->pre_process_gi(p_cam_transform, &render_data, this); } - render_state.gi_probe_count = 0; + render_state.voxel_gi_count = 0; if (rb != nullptr && rb->sdfgi != nullptr) { - gi.setup_giprobes(render_data.render_buffers, render_data.cam_transform, *render_data.gi_probes, render_state.gi_probe_count, this); + gi.setup_voxel_gi_instances(render_data.render_buffers, render_data.cam_transform, *render_data.voxel_gi_instances, render_state.voxel_gi_count, this); rb->sdfgi->update_light(); } @@ -4018,19 +4018,19 @@ bool RendererSceneRenderRD::free(RID p_rid) { decal_instance_owner.free(p_rid); } else if (lightmap_instance_owner.owns(p_rid)) { lightmap_instance_owner.free(p_rid); - } else if (gi.gi_probe_instance_owner.owns(p_rid)) { - RendererSceneGIRD::GIProbeInstance *gi_probe = gi.gi_probe_instance_owner.getornull(p_rid); - if (gi_probe->texture.is_valid()) { - RD::get_singleton()->free(gi_probe->texture); - RD::get_singleton()->free(gi_probe->write_buffer); + } else if (gi.voxel_gi_instance_owner.owns(p_rid)) { + RendererSceneGIRD::VoxelGIInstance *voxel_gi = gi.voxel_gi_instance_owner.getornull(p_rid); + if (voxel_gi->texture.is_valid()) { + RD::get_singleton()->free(voxel_gi->texture); + RD::get_singleton()->free(voxel_gi->write_buffer); } - for (int i = 0; i < gi_probe->dynamic_maps.size(); i++) { - RD::get_singleton()->free(gi_probe->dynamic_maps[i].texture); - RD::get_singleton()->free(gi_probe->dynamic_maps[i].depth); + for (int i = 0; i < voxel_gi->dynamic_maps.size(); i++) { + RD::get_singleton()->free(voxel_gi->dynamic_maps[i].texture); + RD::get_singleton()->free(voxel_gi->dynamic_maps[i].depth); } - gi.gi_probe_instance_owner.free(p_rid); + gi.voxel_gi_instance_owner.free(p_rid); } else if (sky.sky_owner.owns(p_rid)) { sky.update_dirty_skys(); sky.free_sky(p_rid); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 159d206898..c8fcbecc95 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -56,7 +56,7 @@ struct RenderDataRD { const PagedArray *instances = nullptr; const PagedArray *lights = nullptr; const PagedArray *reflection_probes = nullptr; - const PagedArray *gi_probes = nullptr; + const PagedArray *voxel_gi_instances = nullptr; const PagedArray *decals = nullptr; const PagedArray *lightmaps = nullptr; RID environment = RID(); @@ -123,7 +123,7 @@ protected: void _post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi); void _pre_resolve_render(RenderDataRD *p_render_data, bool p_use_gi); - void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_gi, RID p_normal_roughness_buffer, RID p_gi_probe_buffer); + void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_gi, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer); // needed for a single argument calls (material and uv2) PagedArrayPool cull_argument_pool; @@ -631,7 +631,7 @@ private: int render_sdfgi_region_count = 0; const RendererSceneRender::RenderSDFGIUpdateData *sdfgi_update_data = nullptr; - uint32_t gi_probe_count = 0; + uint32_t voxel_gi_count = 0; LocalVector cube_shadows; LocalVector shadows; @@ -692,7 +692,7 @@ private: float detail_spread; float gi_inject; - uint32_t max_gi_probes; + uint32_t max_voxel_gi_instances; uint32_t cluster_type_size; float screen_size[2]; @@ -721,7 +721,7 @@ private: bool volumetric_fog_filter_active = true; void _volumetric_fog_erase(RenderBuffers *rb); - void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_gi_probe_count); + void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count); RID shadow_sampler; @@ -1109,11 +1109,11 @@ public: /* gi light probes */ - RID gi_probe_instance_create(RID p_base); - void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform); - bool gi_probe_needs_update(RID p_probe) const; - void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector &p_light_instances, const PagedArray &p_dynamic_objects); - void gi_probe_set_quality(RS::GIProbeQuality p_quality) { gi.gi_probe_quality = p_quality; } + RID voxel_gi_instance_create(RID p_base); + void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform); + bool voxel_gi_needs_update(RID p_probe) const; + void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector &p_light_instances, const PagedArray &p_dynamic_objects); + void voxel_gi_set_quality(RS::VoxelGIQuality p_quality) { gi.voxel_gi_quality = p_quality; } /* render buffers */ @@ -1123,8 +1123,8 @@ public: RID render_buffers_get_ao_texture(RID p_render_buffers); RID render_buffers_get_back_buffer_texture(RID p_render_buffers); - RID render_buffers_get_gi_probe_buffer(RID p_render_buffers); - RID render_buffers_get_default_gi_probe_buffer(); + RID render_buffers_get_voxel_gi_buffer(RID p_render_buffers); + RID render_buffers_get_default_voxel_gi_buffer(); RID render_buffers_get_gi_ambient_texture(RID p_render_buffers); RID render_buffers_get_gi_reflection_texture(RID p_render_buffers); @@ -1147,7 +1147,7 @@ public: float render_buffers_get_volumetric_fog_end(RID p_render_buffers); float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers); - void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray &p_instances, const PagedArray &p_lights, const PagedArray &p_reflection_probes, const PagedArray &p_gi_probes, const PagedArray &p_decals, const PagedArray &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr); + void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray &p_instances, const PagedArray &p_lights, const PagedArray &p_reflection_probes, const PagedArray &p_voxel_gi_instances, const PagedArray &p_decals, const PagedArray &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr); void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray &p_instances, RID p_framebuffer, const Rect2i &p_region); diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index 8888b2c92e..05993829d1 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -6324,36 +6324,36 @@ AABB RendererStorageRD::decal_get_aabb(RID p_decal) const { return AABB(-decal->extents, decal->extents * 2.0); } -RID RendererStorageRD::gi_probe_allocate() { - return gi_probe_owner.allocate_rid(); +RID RendererStorageRD::voxel_gi_allocate() { + return voxel_gi_owner.allocate_rid(); } -void RendererStorageRD::gi_probe_initialize(RID p_gi_probe) { - gi_probe_owner.initialize_rid(p_gi_probe, GIProbe()); +void RendererStorageRD::voxel_gi_initialize(RID p_voxel_gi) { + voxel_gi_owner.initialize_rid(p_voxel_gi, VoxelGI()); } -void RendererStorageRD::gi_probe_allocate_data(RID p_gi_probe, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); +void RendererStorageRD::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts) { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND(!voxel_gi); - if (gi_probe->octree_buffer.is_valid()) { - RD::get_singleton()->free(gi_probe->octree_buffer); - RD::get_singleton()->free(gi_probe->data_buffer); - if (gi_probe->sdf_texture.is_valid()) { - RD::get_singleton()->free(gi_probe->sdf_texture); + if (voxel_gi->octree_buffer.is_valid()) { + RD::get_singleton()->free(voxel_gi->octree_buffer); + RD::get_singleton()->free(voxel_gi->data_buffer); + if (voxel_gi->sdf_texture.is_valid()) { + RD::get_singleton()->free(voxel_gi->sdf_texture); } - gi_probe->sdf_texture = RID(); - gi_probe->octree_buffer = RID(); - gi_probe->data_buffer = RID(); - gi_probe->octree_buffer_size = 0; - gi_probe->data_buffer_size = 0; - gi_probe->cell_count = 0; + voxel_gi->sdf_texture = RID(); + voxel_gi->octree_buffer = RID(); + voxel_gi->data_buffer = RID(); + voxel_gi->octree_buffer_size = 0; + voxel_gi->data_buffer_size = 0; + voxel_gi->cell_count = 0; } - gi_probe->to_cell_xform = p_to_cell_xform; - gi_probe->bounds = p_aabb; - gi_probe->octree_size = p_octree_size; - gi_probe->level_counts = p_level_counts; + voxel_gi->to_cell_xform = p_to_cell_xform; + voxel_gi->bounds = p_aabb; + voxel_gi->octree_size = p_octree_size; + voxel_gi->level_counts = p_level_counts; if (p_octree_cells.size()) { ERR_FAIL_COND(p_octree_cells.size() % 32 != 0); //cells size must be a multiple of 32 @@ -6362,42 +6362,42 @@ void RendererStorageRD::gi_probe_allocate_data(RID p_gi_probe, const Transform3D ERR_FAIL_COND(p_data_cells.size() != (int)cell_count * 16); //see that data size matches - gi_probe->cell_count = cell_count; - gi_probe->octree_buffer = RD::get_singleton()->storage_buffer_create(p_octree_cells.size(), p_octree_cells); - gi_probe->octree_buffer_size = p_octree_cells.size(); - gi_probe->data_buffer = RD::get_singleton()->storage_buffer_create(p_data_cells.size(), p_data_cells); - gi_probe->data_buffer_size = p_data_cells.size(); + voxel_gi->cell_count = cell_count; + voxel_gi->octree_buffer = RD::get_singleton()->storage_buffer_create(p_octree_cells.size(), p_octree_cells); + voxel_gi->octree_buffer_size = p_octree_cells.size(); + voxel_gi->data_buffer = RD::get_singleton()->storage_buffer_create(p_data_cells.size(), p_data_cells); + voxel_gi->data_buffer_size = p_data_cells.size(); if (p_distance_field.size()) { RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = gi_probe->octree_size.x; - tf.height = gi_probe->octree_size.y; - tf.depth = gi_probe->octree_size.z; + tf.width = voxel_gi->octree_size.x; + tf.height = voxel_gi->octree_size.y; + tf.depth = voxel_gi->octree_size.z; tf.texture_type = RD::TEXTURE_TYPE_3D; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; Vector> s; s.push_back(p_distance_field); - gi_probe->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView(), s); + voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView(), s); } #if 0 { RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = gi_probe->octree_size.x; - tf.height = gi_probe->octree_size.y; - tf.depth = gi_probe->octree_size.z; + tf.width = voxel_gi->octree_size.x; + tf.height = voxel_gi->octree_size.y; + tf.depth = voxel_gi->octree_size.z; tf.type = RD::TEXTURE_TYPE_3D; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UNORM); tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UINT); - gi_probe->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); } RID shared_tex; { RD::TextureView tv; tv.format_override = RD::DATA_FORMAT_R8_UINT; - shared_tex = RD::get_singleton()->texture_create_shared(tv, gi_probe->sdf_texture); + shared_tex = RD::get_singleton()->texture_create_shared(tv, voxel_gi->sdf_texture); } //update SDF texture Vector uniforms; @@ -6405,14 +6405,14 @@ void RendererStorageRD::gi_probe_allocate_data(RID p_gi_probe, const Transform3D RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; - u.ids.push_back(gi_probe->octree_buffer); + u.ids.push_back(voxel_gi->octree_buffer); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; - u.ids.push_back(gi_probe->data_buffer); + u.ids.push_back(voxel_gi->data_buffer); uniforms.push_back(u); } { @@ -6423,24 +6423,24 @@ void RendererStorageRD::gi_probe_allocate_data(RID p_gi_probe, const Transform3D uniforms.push_back(u); } - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_sdf_shader_version_shader, 0); + RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, voxel_gi_sdf_shader_version_shader, 0); { uint32_t push_constant[4] = { 0, 0, 0, 0 }; - for (int i = 0; i < gi_probe->level_counts.size() - 1; i++) { - push_constant[0] += gi_probe->level_counts[i]; + for (int i = 0; i < voxel_gi->level_counts.size() - 1; i++) { + push_constant[0] += voxel_gi->level_counts[i]; } - push_constant[1] = push_constant[0] + gi_probe->level_counts[gi_probe->level_counts.size() - 1]; + push_constant[1] = push_constant[0] + voxel_gi->level_counts[voxel_gi->level_counts.size() - 1]; print_line("offset: " + itos(push_constant[0])); print_line("size: " + itos(push_constant[1])); //create SDF RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_sdf_shader_pipeline); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, voxel_gi_sdf_shader_pipeline); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set, 0); RD::get_singleton()->compute_list_set_push_constant(compute_list, push_constant, sizeof(uint32_t) * 4); - RD::get_singleton()->compute_list_dispatch(compute_list, gi_probe->octree_size.x / 4, gi_probe->octree_size.y / 4, gi_probe->octree_size.z / 4); + RD::get_singleton()->compute_list_dispatch(compute_list, voxel_gi->octree_size.x / 4, voxel_gi->octree_size.y / 4, voxel_gi->octree_size.z / 4); RD::get_singleton()->compute_list_end(); } @@ -6450,232 +6450,232 @@ void RendererStorageRD::gi_probe_allocate_data(RID p_gi_probe, const Transform3D #endif } - gi_probe->version++; - gi_probe->data_version++; + voxel_gi->version++; + voxel_gi->data_version++; - gi_probe->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); + voxel_gi->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); } -AABB RendererStorageRD::gi_probe_get_bounds(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, AABB()); +AABB RendererStorageRD::voxel_gi_get_bounds(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, AABB()); - return gi_probe->bounds; + return voxel_gi->bounds; } -Vector3i RendererStorageRD::gi_probe_get_octree_size(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, Vector3i()); - return gi_probe->octree_size; +Vector3i RendererStorageRD::voxel_gi_get_octree_size(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, Vector3i()); + return voxel_gi->octree_size; } -Vector RendererStorageRD::gi_probe_get_octree_cells(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, Vector()); +Vector RendererStorageRD::voxel_gi_get_octree_cells(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, Vector()); - if (gi_probe->octree_buffer.is_valid()) { - return RD::get_singleton()->buffer_get_data(gi_probe->octree_buffer); + if (voxel_gi->octree_buffer.is_valid()) { + return RD::get_singleton()->buffer_get_data(voxel_gi->octree_buffer); } return Vector(); } -Vector RendererStorageRD::gi_probe_get_data_cells(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, Vector()); +Vector RendererStorageRD::voxel_gi_get_data_cells(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, Vector()); - if (gi_probe->data_buffer.is_valid()) { - return RD::get_singleton()->buffer_get_data(gi_probe->data_buffer); + if (voxel_gi->data_buffer.is_valid()) { + return RD::get_singleton()->buffer_get_data(voxel_gi->data_buffer); } return Vector(); } -Vector RendererStorageRD::gi_probe_get_distance_field(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, Vector()); +Vector RendererStorageRD::voxel_gi_get_distance_field(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, Vector()); - if (gi_probe->data_buffer.is_valid()) { - return RD::get_singleton()->texture_get_data(gi_probe->sdf_texture, 0); + if (voxel_gi->data_buffer.is_valid()) { + return RD::get_singleton()->texture_get_data(voxel_gi->sdf_texture, 0); } return Vector(); } -Vector RendererStorageRD::gi_probe_get_level_counts(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, Vector()); +Vector RendererStorageRD::voxel_gi_get_level_counts(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, Vector()); - return gi_probe->level_counts; + return voxel_gi->level_counts; } -Transform3D RendererStorageRD::gi_probe_get_to_cell_xform(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, Transform3D()); +Transform3D RendererStorageRD::voxel_gi_get_to_cell_xform(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, Transform3D()); - return gi_probe->to_cell_xform; + return voxel_gi->to_cell_xform; } -void RendererStorageRD::gi_probe_set_dynamic_range(RID p_gi_probe, float p_range) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); +void RendererStorageRD::voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND(!voxel_gi); - gi_probe->dynamic_range = p_range; - gi_probe->version++; + voxel_gi->dynamic_range = p_range; + voxel_gi->version++; } -float RendererStorageRD::gi_probe_get_dynamic_range(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); +float RendererStorageRD::voxel_gi_get_dynamic_range(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, 0); - return gi_probe->dynamic_range; + return voxel_gi->dynamic_range; } -void RendererStorageRD::gi_probe_set_propagation(RID p_gi_probe, float p_range) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); +void RendererStorageRD::voxel_gi_set_propagation(RID p_voxel_gi, float p_range) { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND(!voxel_gi); - gi_probe->propagation = p_range; - gi_probe->version++; + voxel_gi->propagation = p_range; + voxel_gi->version++; } -float RendererStorageRD::gi_probe_get_propagation(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); - return gi_probe->propagation; +float RendererStorageRD::voxel_gi_get_propagation(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, 0); + return voxel_gi->propagation; } -void RendererStorageRD::gi_probe_set_energy(RID p_gi_probe, float p_energy) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); +void RendererStorageRD::voxel_gi_set_energy(RID p_voxel_gi, float p_energy) { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND(!voxel_gi); - gi_probe->energy = p_energy; + voxel_gi->energy = p_energy; } -float RendererStorageRD::gi_probe_get_energy(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); - return gi_probe->energy; +float RendererStorageRD::voxel_gi_get_energy(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, 0); + return voxel_gi->energy; } -void RendererStorageRD::gi_probe_set_ao(RID p_gi_probe, float p_ao) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); +void RendererStorageRD::voxel_gi_set_ao(RID p_voxel_gi, float p_ao) { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND(!voxel_gi); - gi_probe->ao = p_ao; + voxel_gi->ao = p_ao; } -float RendererStorageRD::gi_probe_get_ao(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); - return gi_probe->ao; +float RendererStorageRD::voxel_gi_get_ao(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, 0); + return voxel_gi->ao; } -void RendererStorageRD::gi_probe_set_ao_size(RID p_gi_probe, float p_strength) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); +void RendererStorageRD::voxel_gi_set_ao_size(RID p_voxel_gi, float p_strength) { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND(!voxel_gi); - gi_probe->ao_size = p_strength; + voxel_gi->ao_size = p_strength; } -float RendererStorageRD::gi_probe_get_ao_size(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); - return gi_probe->ao_size; +float RendererStorageRD::voxel_gi_get_ao_size(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, 0); + return voxel_gi->ao_size; } -void RendererStorageRD::gi_probe_set_bias(RID p_gi_probe, float p_bias) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); +void RendererStorageRD::voxel_gi_set_bias(RID p_voxel_gi, float p_bias) { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND(!voxel_gi); - gi_probe->bias = p_bias; + voxel_gi->bias = p_bias; } -float RendererStorageRD::gi_probe_get_bias(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); - return gi_probe->bias; +float RendererStorageRD::voxel_gi_get_bias(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, 0); + return voxel_gi->bias; } -void RendererStorageRD::gi_probe_set_normal_bias(RID p_gi_probe, float p_normal_bias) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); +void RendererStorageRD::voxel_gi_set_normal_bias(RID p_voxel_gi, float p_normal_bias) { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND(!voxel_gi); - gi_probe->normal_bias = p_normal_bias; + voxel_gi->normal_bias = p_normal_bias; } -float RendererStorageRD::gi_probe_get_normal_bias(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); - return gi_probe->normal_bias; +float RendererStorageRD::voxel_gi_get_normal_bias(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, 0); + return voxel_gi->normal_bias; } -void RendererStorageRD::gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); +void RendererStorageRD::voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND(!voxel_gi); - gi_probe->anisotropy_strength = p_strength; + voxel_gi->anisotropy_strength = p_strength; } -float RendererStorageRD::gi_probe_get_anisotropy_strength(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); - return gi_probe->anisotropy_strength; +float RendererStorageRD::voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, 0); + return voxel_gi->anisotropy_strength; } -void RendererStorageRD::gi_probe_set_interior(RID p_gi_probe, bool p_enable) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); +void RendererStorageRD::voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND(!voxel_gi); - gi_probe->interior = p_enable; + voxel_gi->interior = p_enable; } -void RendererStorageRD::gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); +void RendererStorageRD::voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND(!voxel_gi); - gi_probe->use_two_bounces = p_enable; - gi_probe->version++; + voxel_gi->use_two_bounces = p_enable; + voxel_gi->version++; } -bool RendererStorageRD::gi_probe_is_using_two_bounces(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, false); - return gi_probe->use_two_bounces; +bool RendererStorageRD::voxel_gi_is_using_two_bounces(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, false); + return voxel_gi->use_two_bounces; } -bool RendererStorageRD::gi_probe_is_interior(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); - return gi_probe->interior; +bool RendererStorageRD::voxel_gi_is_interior(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, 0); + return voxel_gi->interior; } -uint32_t RendererStorageRD::gi_probe_get_version(RID p_gi_probe) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); - return gi_probe->version; +uint32_t RendererStorageRD::voxel_gi_get_version(RID p_voxel_gi) { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, 0); + return voxel_gi->version; } -uint32_t RendererStorageRD::gi_probe_get_data_version(RID p_gi_probe) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); - return gi_probe->data_version; +uint32_t RendererStorageRD::voxel_gi_get_data_version(RID p_voxel_gi) { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, 0); + return voxel_gi->data_version; } -RID RendererStorageRD::gi_probe_get_octree_buffer(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, RID()); - return gi_probe->octree_buffer; +RID RendererStorageRD::voxel_gi_get_octree_buffer(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, RID()); + return voxel_gi->octree_buffer; } -RID RendererStorageRD::gi_probe_get_data_buffer(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, RID()); - return gi_probe->data_buffer; +RID RendererStorageRD::voxel_gi_get_data_buffer(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, RID()); + return voxel_gi->data_buffer; } -RID RendererStorageRD::gi_probe_get_sdf_texture(RID p_gi_probe) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, RID()); +RID RendererStorageRD::voxel_gi_get_sdf_texture(RID p_voxel_gi) { + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, RID()); - return gi_probe->sdf_texture; + return voxel_gi->sdf_texture; } /* LIGHTMAP API */ @@ -7566,8 +7566,8 @@ void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_ } else if (decal_owner.owns(p_base)) { Decal *decal = decal_owner.getornull(p_base); p_instance->update_dependency(&decal->dependency); - } else if (gi_probe_owner.owns(p_base)) { - GIProbe *gip = gi_probe_owner.getornull(p_base); + } else if (voxel_gi_owner.owns(p_base)) { + VoxelGI *gip = voxel_gi_owner.getornull(p_base); p_instance->update_dependency(&gip->dependency); } else if (lightmap_owner.owns(p_base)) { Lightmap *lm = lightmap_owner.getornull(p_base); @@ -7604,8 +7604,8 @@ RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const { if (decal_owner.owns(p_rid)) { return RS::INSTANCE_DECAL; } - if (gi_probe_owner.owns(p_rid)) { - return RS::INSTANCE_GI_PROBE; + if (voxel_gi_owner.owns(p_rid)) { + return RS::INSTANCE_VOXEL_GI; } if (light_owner.owns(p_rid)) { return RS::INSTANCE_LIGHT; @@ -8662,11 +8662,11 @@ bool RendererStorageRD::free(RID p_rid) { } decal->dependency.deleted_notify(p_rid); decal_owner.free(p_rid); - } else if (gi_probe_owner.owns(p_rid)) { - gi_probe_allocate_data(p_rid, Transform3D(), AABB(), Vector3i(), Vector(), Vector(), Vector(), Vector()); //deallocate - GIProbe *gi_probe = gi_probe_owner.getornull(p_rid); - gi_probe->dependency.deleted_notify(p_rid); - gi_probe_owner.free(p_rid); + } else if (voxel_gi_owner.owns(p_rid)) { + voxel_gi_allocate_data(p_rid, Transform3D(), AABB(), Vector3i(), Vector(), Vector(), Vector(), Vector()); //deallocate + VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_rid); + voxel_gi->dependency.deleted_notify(p_rid); + voxel_gi_owner.free(p_rid); } else if (lightmap_owner.owns(p_rid)) { lightmap_set_textures(p_rid, RID(), false); Lightmap *lightmap = lightmap_owner.getornull(p_rid); @@ -9181,10 +9181,10 @@ RendererStorageRD::RendererStorageRD() { { Vector sdf_versions; sdf_versions.push_back(""); //one only - giprobe_sdf_shader.initialize(sdf_versions); - giprobe_sdf_shader_version = giprobe_sdf_shader.version_create(); - giprobe_sdf_shader_version_shader = giprobe_sdf_shader.version_get_shader(giprobe_sdf_shader_version, 0); - giprobe_sdf_shader_pipeline = RD::get_singleton()->compute_pipeline_create(giprobe_sdf_shader_version_shader); + voxel_gi_sdf_shader.initialize(sdf_versions); + voxel_gi_sdf_shader_version = voxel_gi_sdf_shader.version_create(); + voxel_gi_sdf_shader_version_shader = voxel_gi_sdf_shader.version_get_shader(voxel_gi_sdf_shader_version, 0); + voxel_gi_sdf_shader_pipeline = RD::get_singleton()->compute_pipeline_create(voxel_gi_sdf_shader_version_shader); } using_lightmap_array = true; // high end @@ -9400,7 +9400,7 @@ RendererStorageRD::~RendererStorageRD() { RD::get_singleton()->free(mesh_default_rd_buffers[i]); } - giprobe_sdf_shader.version_free(giprobe_sdf_shader_version); + voxel_gi_sdf_shader.version_free(voxel_gi_sdf_shader_version); particles_shader.copy_shader.version_free(particles_shader.copy_shader_version); rt_sdf.shader.version_free(rt_sdf.shader_version); diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h index 97e2e9a434..8bfab545fd 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.h +++ b/servers/rendering/renderer_rd/renderer_storage_rd.h @@ -38,10 +38,10 @@ #include "servers/rendering/renderer_rd/effects_rd.h" #include "servers/rendering/renderer_rd/shader_compiler_rd.h" #include "servers/rendering/renderer_rd/shaders/canvas_sdf.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/giprobe_sdf.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/particles.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/skeleton.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl.gen.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" class RendererStorageRD : public RendererStorage { @@ -1045,9 +1045,9 @@ private: mutable RID_Owner decal_owner; - /* GI PROBE */ + /* VOXEL GI */ - struct GIProbe { + struct VoxelGI { RID octree_buffer; RID data_buffer; RID sdf_texture; @@ -1081,12 +1081,12 @@ private: Dependency dependency; }; - GiprobeSdfShaderRD giprobe_sdf_shader; - RID giprobe_sdf_shader_version; - RID giprobe_sdf_shader_version_shader; - RID giprobe_sdf_shader_pipeline; + VoxelGiSdfShaderRD voxel_gi_sdf_shader; + RID voxel_gi_sdf_shader_version; + RID voxel_gi_sdf_shader_version_shader; + RID voxel_gi_sdf_shader_pipeline; - mutable RID_Owner gi_probe_owner; + mutable RID_Owner voxel_gi_owner; /* REFLECTION PROBE */ @@ -2019,59 +2019,59 @@ public: virtual AABB decal_get_aabb(RID p_decal) const; - /* GI PROBE API */ + /* VOXEL GI API */ - RID gi_probe_allocate(); - void gi_probe_initialize(RID p_gi_probe); + RID voxel_gi_allocate(); + void voxel_gi_initialize(RID p_voxel_gi); - void gi_probe_allocate_data(RID p_gi_probe, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts); + void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts); - AABB gi_probe_get_bounds(RID p_gi_probe) const; - Vector3i gi_probe_get_octree_size(RID p_gi_probe) const; - Vector gi_probe_get_octree_cells(RID p_gi_probe) const; - Vector gi_probe_get_data_cells(RID p_gi_probe) const; - Vector gi_probe_get_distance_field(RID p_gi_probe) const; + AABB voxel_gi_get_bounds(RID p_voxel_gi) const; + Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const; + Vector voxel_gi_get_octree_cells(RID p_voxel_gi) const; + Vector voxel_gi_get_data_cells(RID p_voxel_gi) const; + Vector voxel_gi_get_distance_field(RID p_voxel_gi) const; - Vector gi_probe_get_level_counts(RID p_gi_probe) const; - Transform3D gi_probe_get_to_cell_xform(RID p_gi_probe) const; + Vector voxel_gi_get_level_counts(RID p_voxel_gi) const; + Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const; - void gi_probe_set_dynamic_range(RID p_gi_probe, float p_range); - float gi_probe_get_dynamic_range(RID p_gi_probe) const; + void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range); + float voxel_gi_get_dynamic_range(RID p_voxel_gi) const; - void gi_probe_set_propagation(RID p_gi_probe, float p_range); - float gi_probe_get_propagation(RID p_gi_probe) const; + void voxel_gi_set_propagation(RID p_voxel_gi, float p_range); + float voxel_gi_get_propagation(RID p_voxel_gi) const; - void gi_probe_set_energy(RID p_gi_probe, float p_energy); - float gi_probe_get_energy(RID p_gi_probe) const; + void voxel_gi_set_energy(RID p_voxel_gi, float p_energy); + float voxel_gi_get_energy(RID p_voxel_gi) const; - void gi_probe_set_ao(RID p_gi_probe, float p_ao); - float gi_probe_get_ao(RID p_gi_probe) const; + void voxel_gi_set_ao(RID p_voxel_gi, float p_ao); + float voxel_gi_get_ao(RID p_voxel_gi) const; - void gi_probe_set_ao_size(RID p_gi_probe, float p_strength); - float gi_probe_get_ao_size(RID p_gi_probe) const; + void voxel_gi_set_ao_size(RID p_voxel_gi, float p_strength); + float voxel_gi_get_ao_size(RID p_voxel_gi) const; - void gi_probe_set_bias(RID p_gi_probe, float p_bias); - float gi_probe_get_bias(RID p_gi_probe) const; + void voxel_gi_set_bias(RID p_voxel_gi, float p_bias); + float voxel_gi_get_bias(RID p_voxel_gi) const; - void gi_probe_set_normal_bias(RID p_gi_probe, float p_range); - float gi_probe_get_normal_bias(RID p_gi_probe) const; + void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range); + float voxel_gi_get_normal_bias(RID p_voxel_gi) const; - void gi_probe_set_interior(RID p_gi_probe, bool p_enable); - bool gi_probe_is_interior(RID p_gi_probe) const; + void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable); + bool voxel_gi_is_interior(RID p_voxel_gi) const; - void gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable); - bool gi_probe_is_using_two_bounces(RID p_gi_probe) const; + void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable); + bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const; - void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength); - float gi_probe_get_anisotropy_strength(RID p_gi_probe) const; + void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength); + float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const; - uint32_t gi_probe_get_version(RID p_probe); - uint32_t gi_probe_get_data_version(RID p_probe); + uint32_t voxel_gi_get_version(RID p_probe); + uint32_t voxel_gi_get_data_version(RID p_probe); - RID gi_probe_get_octree_buffer(RID p_gi_probe) const; - RID gi_probe_get_data_buffer(RID p_gi_probe) const; + RID voxel_gi_get_octree_buffer(RID p_voxel_gi) const; + RID voxel_gi_get_data_buffer(RID p_voxel_gi) const; - RID gi_probe_get_sdf_texture(RID p_gi_probe); + RID voxel_gi_get_sdf_texture(RID p_voxel_gi); /* LIGHTMAP CAPTURE */ diff --git a/servers/rendering/renderer_rd/shaders/gi.glsl b/servers/rendering/renderer_rd/shaders/gi.glsl index bfd5c4c88d..3977f4efa0 100644 --- a/servers/rendering/renderer_rd/shaders/gi.glsl +++ b/servers/rendering/renderer_rd/shaders/gi.glsl @@ -35,7 +35,7 @@ layout(set = 0, binding = 11) uniform texture2DArray lightprobe_texture; layout(set = 0, binding = 12) uniform texture2D depth_buffer; layout(set = 0, binding = 13) uniform texture2D normal_roughness_buffer; -layout(set = 0, binding = 14) uniform utexture2D giprobe_buffer; +layout(set = 0, binding = 14) uniform utexture2D voxel_gi_buffer; layout(set = 0, binding = 15, std140) uniform SDFGI { vec3 grid_size; @@ -65,9 +65,9 @@ layout(set = 0, binding = 15, std140) uniform SDFGI { } sdfgi; -#define MAX_GI_PROBES 8 +#define MAX_VOXEL_GI_INSTANCES 8 -struct GIProbeData { +struct VoxelGIData { mat4 xform; vec3 bounds; float dynamic_range; @@ -83,12 +83,12 @@ struct GIProbeData { uint mipmaps; }; -layout(set = 0, binding = 16, std140) uniform GIProbes { - GIProbeData data[MAX_GI_PROBES]; +layout(set = 0, binding = 16, std140) uniform VoxelGIs { + VoxelGIData data[MAX_VOXEL_GI_INSTANCES]; } -gi_probes; +voxel_gi_instances; -layout(set = 0, binding = 17) uniform texture3D gi_probe_textures[MAX_GI_PROBES]; +layout(set = 0, binding = 17) uniform texture3D voxel_gi_textures[MAX_VOXEL_GI_INSTANCES]; layout(push_constant, binding = 0, std430) uniform Params { ivec2 screen_size; @@ -98,7 +98,7 @@ layout(push_constant, binding = 0, std430) uniform Params { vec4 proj_info; vec3 ao_color; - uint max_giprobes; + uint max_voxel_gi_instances; bool high_quality_vct; bool orthogonal; @@ -155,7 +155,7 @@ vec3 reconstruct_position(ivec2 screen_pos) { return pos; } -void sdfgi_probe_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal, vec3 cam_specular_normal, float roughness, out vec3 diffuse_light, out vec3 specular_light) { +void sdfvoxel_gi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal, vec3 cam_specular_normal, float roughness, out vec3 diffuse_light, out vec3 specular_light) { cascade_pos += cam_normal * sdfgi.normal_bias; vec3 base_pos = floor(cascade_pos); @@ -293,7 +293,7 @@ void sdfgi_process(vec3 vertex, vec3 normal, vec3 reflection, float roughness, o float blend; vec3 diffuse, specular; - sdfgi_probe_process(cascade, cascade_pos, cam_pos, cam_normal, reflection, roughness, diffuse, specular); + sdfvoxel_gi_process(cascade, cascade_pos, cam_pos, cam_normal, reflection, roughness, diffuse, specular); { //process blend @@ -323,7 +323,7 @@ void sdfgi_process(vec3 vertex, vec3 normal, vec3 reflection, float roughness, o } else { vec3 diffuse2, specular2; cascade_pos = (cam_pos - sdfgi.cascades[cascade + 1].position) * sdfgi.cascades[cascade + 1].to_probe; - sdfgi_probe_process(cascade + 1, cascade_pos, cam_pos, cam_normal, reflection, roughness, diffuse2, specular2); + sdfvoxel_gi_process(cascade + 1, cascade_pos, cam_pos, cam_normal, reflection, roughness, diffuse2, specular2); diffuse = mix(diffuse, diffuse2, blend); specular = mix(specular, specular2, blend); } @@ -494,26 +494,26 @@ vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3 return color; } -void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 normal_xform, float roughness, inout vec4 out_spec, inout vec4 out_diff, inout float out_blend) { - position = (gi_probes.data[index].xform * vec4(position, 1.0)).xyz; - ref_vec = normalize((gi_probes.data[index].xform * vec4(ref_vec, 0.0)).xyz); - normal = normalize((gi_probes.data[index].xform * vec4(normal, 0.0)).xyz); +void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 normal_xform, float roughness, inout vec4 out_spec, inout vec4 out_diff, inout float out_blend) { + position = (voxel_gi_instances.data[index].xform * vec4(position, 1.0)).xyz; + ref_vec = normalize((voxel_gi_instances.data[index].xform * vec4(ref_vec, 0.0)).xyz); + normal = normalize((voxel_gi_instances.data[index].xform * vec4(normal, 0.0)).xyz); - position += normal * gi_probes.data[index].normal_bias; + position += normal * voxel_gi_instances.data[index].normal_bias; //this causes corrupted pixels, i have no idea why.. - if (any(bvec2(any(lessThan(position, vec3(0.0))), any(greaterThan(position, gi_probes.data[index].bounds))))) { + if (any(bvec2(any(lessThan(position, vec3(0.0))), any(greaterThan(position, voxel_gi_instances.data[index].bounds))))) { return; } - mat3 dir_xform = mat3(gi_probes.data[index].xform) * normal_xform; + mat3 dir_xform = mat3(voxel_gi_instances.data[index].xform) * normal_xform; - vec3 blendv = abs(position / gi_probes.data[index].bounds * 2.0 - 1.0); + vec3 blendv = abs(position / voxel_gi_instances.data[index].bounds * 2.0 - 1.0); float blend = clamp(1.0 - max(blendv.x, max(blendv.y, blendv.z)), 0.0, 1.0); //float blend=1.0; - float max_distance = length(gi_probes.data[index].bounds); - vec3 cell_size = 1.0 / gi_probes.data[index].bounds; + float max_distance = length(voxel_gi_instances.data[index].bounds); + vec3 cell_size = 1.0 / voxel_gi_instances.data[index].bounds; //irradiance @@ -534,7 +534,7 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 for (uint i = 0; i < cone_dir_count; i++) { vec3 dir = normalize(dir_xform * cone_dirs[i]); - light += cone_weights[i] * voxel_cone_trace(gi_probe_textures[index], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias); + light += cone_weights[i] * voxel_cone_trace(voxel_gi_textures[index], cell_size, position, dir, cone_angle_tan, max_distance, voxel_gi_instances.data[index].bias); } } else { const uint cone_dir_count = 4; @@ -547,42 +547,42 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 float cone_weights[cone_dir_count] = float[](0.25, 0.25, 0.25, 0.25); for (int i = 0; i < cone_dir_count; i++) { vec3 dir = normalize(dir_xform * cone_dirs[i]); - light += cone_weights[i] * voxel_cone_trace_45_degrees(gi_probe_textures[index], cell_size, position, dir, max_distance, gi_probes.data[index].bias); + light += cone_weights[i] * voxel_cone_trace_45_degrees(voxel_gi_textures[index], cell_size, position, dir, max_distance, voxel_gi_instances.data[index].bias); } } - if (gi_probes.data[index].ambient_occlusion > 0.001) { - float size = 1.0 + gi_probes.data[index].ambient_occlusion_size * 7.0; + if (voxel_gi_instances.data[index].ambient_occlusion > 0.001) { + float size = 1.0 + voxel_gi_instances.data[index].ambient_occlusion_size * 7.0; float taps, blend; blend = modf(size, taps); float ao = 0.0; for (float i = 1.0; i <= taps; i++) { vec3 ofs = (position + normal * (i * 0.5 + 1.0)) * cell_size; - ao += textureLod(sampler3D(gi_probe_textures[index], linear_sampler_with_mipmaps), ofs, i - 1.0).a * i; + ao += textureLod(sampler3D(voxel_gi_textures[index], linear_sampler_with_mipmaps), ofs, i - 1.0).a * i; } if (blend > 0.001) { vec3 ofs = (position + normal * ((taps + 1.0) * 0.5 + 1.0)) * cell_size; - ao += textureLod(sampler3D(gi_probe_textures[index], linear_sampler_with_mipmaps), ofs, taps).a * (taps + 1.0) * blend; + ao += textureLod(sampler3D(voxel_gi_textures[index], linear_sampler_with_mipmaps), ofs, taps).a * (taps + 1.0) * blend; } ao = 1.0 - min(1.0, ao); - light.rgb = mix(params.ao_color, light.rgb, mix(1.0, ao, gi_probes.data[index].ambient_occlusion)); + light.rgb = mix(params.ao_color, light.rgb, mix(1.0, ao, voxel_gi_instances.data[index].ambient_occlusion)); } - light.rgb *= gi_probes.data[index].dynamic_range; - if (!gi_probes.data[index].blend_ambient) { + light.rgb *= voxel_gi_instances.data[index].dynamic_range; + if (!voxel_gi_instances.data[index].blend_ambient) { light.a = 1.0; } out_diff += light * blend; //radiance - vec4 irr_light = voxel_cone_trace(gi_probe_textures[index], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, gi_probes.data[index].bias); - irr_light.rgb *= gi_probes.data[index].dynamic_range; - if (!gi_probes.data[index].blend_ambient) { + vec4 irr_light = voxel_cone_trace(voxel_gi_textures[index], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, voxel_gi_instances.data[index].bias); + irr_light.rgb *= voxel_gi_instances.data[index].dynamic_range; + if (!voxel_gi_instances.data[index].blend_ambient) { irr_light.a = 1.0; } @@ -614,9 +614,9 @@ void process_gi(ivec2 pos, vec3 vertex, inout vec4 ambient_light, inout vec4 ref sdfgi_process(vertex, normal, reflection, roughness, ambient_light, reflection_light); #endif -#ifdef USE_GIPROBES +#ifdef USE_VOXEL_GI_INSTANCES { - uvec2 giprobe_tex = texelFetch(usampler2D(giprobe_buffer, linear_sampler), pos, 0).rg; + uvec2 voxel_gi_tex = texelFetch(usampler2D(voxel_gi_buffer, linear_sampler), pos, 0).rg; roughness *= roughness; //find arbitrary tangent and bitangent, then build a matrix vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); @@ -628,9 +628,9 @@ void process_gi(ivec2 pos, vec3 vertex, inout vec4 ambient_light, inout vec4 ref vec4 spec_accum = vec4(0.0); float blend_accum = 0.0; - for (uint i = 0; i < params.max_giprobes; i++) { - if (any(equal(uvec2(i), giprobe_tex))) { - gi_probe_compute(i, vertex, normal, reflection, normal_mat, roughness, spec_accum, amb_accum, blend_accum); + for (uint i = 0; i < params.max_voxel_gi_instances; i++) { + if (any(equal(uvec2(i), voxel_gi_tex))) { + voxel_gi_compute(i, vertex, normal, reflection, normal_mat, roughness, spec_accum, amb_accum, blend_accum); } } if (blend_accum > 0.0) { diff --git a/servers/rendering/renderer_rd/shaders/giprobe.glsl b/servers/rendering/renderer_rd/shaders/giprobe.glsl deleted file mode 100644 index 49a493cdc7..0000000000 --- a/servers/rendering/renderer_rd/shaders/giprobe.glsl +++ /dev/null @@ -1,779 +0,0 @@ -#[compute] - -#version 450 - -#VERSION_DEFINES - -#ifdef MODE_DYNAMIC -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; -#else -layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; -#endif - -#ifndef MODE_DYNAMIC - -#define NO_CHILDREN 0xFFFFFFFF -#define GREY_VEC vec3(0.33333, 0.33333, 0.33333) - -struct CellChildren { - uint children[8]; -}; - -layout(set = 0, binding = 1, std430) buffer CellChildrenBuffer { - CellChildren data[]; -} -cell_children; - -struct CellData { - uint position; // xyz 10 bits - uint albedo; //rgb albedo - uint emission; //rgb normalized with e as multiplier - uint normal; //RGB normal encoded -}; - -layout(set = 0, binding = 2, std430) buffer CellDataBuffer { - CellData data[]; -} -cell_data; - -#endif // MODE DYNAMIC - -#define LIGHT_TYPE_DIRECTIONAL 0 -#define LIGHT_TYPE_OMNI 1 -#define LIGHT_TYPE_SPOT 2 - -#if defined(MODE_COMPUTE_LIGHT) || defined(MODE_DYNAMIC_LIGHTING) - -struct Light { - uint type; - float energy; - float radius; - float attenuation; - - vec3 color; - float cos_spot_angle; - - vec3 position; - float inv_spot_attenuation; - - vec3 direction; - bool has_shadow; -}; - -layout(set = 0, binding = 3, std140) uniform Lights { - Light data[MAX_LIGHTS]; -} -lights; - -#endif // MODE COMPUTE LIGHT - -#ifdef MODE_SECOND_BOUNCE - -layout(set = 0, binding = 5) uniform texture3D color_texture; - -#ifdef MODE_ANISOTROPIC -layout(set = 0, binding = 7) uniform texture3D aniso_pos_texture; -layout(set = 0, binding = 8) uniform texture3D aniso_neg_texture; -#endif // MODE ANISOTROPIC - -#endif // MODE_SECOND_BOUNCE - -#ifndef MODE_DYNAMIC - -layout(push_constant, binding = 0, std430) uniform Params { - ivec3 limits; - uint stack_size; - - float emission_scale; - float propagation; - float dynamic_range; - - uint light_count; - uint cell_offset; - uint cell_count; - float aniso_strength; - uint pad; -} -params; - -layout(set = 0, binding = 4, std430) buffer Outputs { - vec4 data[]; -} -outputs; - -#endif // MODE DYNAMIC - -layout(set = 0, binding = 9) uniform texture3D texture_sdf; -layout(set = 0, binding = 10) uniform sampler texture_sampler; - -#ifdef MODE_WRITE_TEXTURE - -layout(rgba8, set = 0, binding = 5) uniform restrict writeonly image3D color_tex; - -#ifdef MODE_ANISOTROPIC - -layout(r16ui, set = 0, binding = 6) uniform restrict writeonly uimage3D aniso_pos_tex; -layout(r16ui, set = 0, binding = 7) uniform restrict writeonly uimage3D aniso_neg_tex; - -#endif - -#endif - -#ifdef MODE_DYNAMIC - -layout(push_constant, binding = 0, std430) uniform Params { - ivec3 limits; - uint light_count; //when not lighting - ivec3 x_dir; - float z_base; - ivec3 y_dir; - float z_sign; - ivec3 z_dir; - float pos_multiplier; - ivec2 rect_pos; - ivec2 rect_size; - ivec2 prev_rect_ofs; - ivec2 prev_rect_size; - bool flip_x; - bool flip_y; - float dynamic_range; - bool on_mipmap; - float propagation; - float pad[3]; -} -params; - -#ifdef MODE_DYNAMIC_LIGHTING - -layout(rgba8, set = 0, binding = 5) uniform restrict readonly image2D source_albedo; -layout(rgba8, set = 0, binding = 6) uniform restrict readonly image2D source_normal; -layout(rgba8, set = 0, binding = 7) uniform restrict readonly image2D source_orm; -//layout (set=0,binding=8) uniform texture2D source_depth; -layout(rgba16f, set = 0, binding = 11) uniform restrict image2D emission; -layout(r32f, set = 0, binding = 12) uniform restrict image2D depth; - -#endif - -#ifdef MODE_DYNAMIC_SHRINK - -layout(rgba16f, set = 0, binding = 5) uniform restrict readonly image2D source_light; -layout(r32f, set = 0, binding = 6) uniform restrict readonly image2D source_depth; - -#ifdef MODE_DYNAMIC_SHRINK_WRITE - -layout(rgba16f, set = 0, binding = 7) uniform restrict writeonly image2D light; -layout(r32f, set = 0, binding = 8) uniform restrict writeonly image2D depth; - -#endif // MODE_DYNAMIC_SHRINK_WRITE - -#ifdef MODE_DYNAMIC_SHRINK_PLOT - -layout(rgba8, set = 0, binding = 11) uniform restrict image3D color_texture; - -#ifdef MODE_ANISOTROPIC - -layout(r16ui, set = 0, binding = 12) uniform restrict writeonly uimage3D aniso_pos_texture; -layout(r16ui, set = 0, binding = 13) uniform restrict writeonly uimage3D aniso_neg_texture; - -#endif // MODE ANISOTROPIC - -#endif //MODE_DYNAMIC_SHRINK_PLOT - -#endif // MODE_DYNAMIC_SHRINK - -//layout (rgba8,set=0,binding=5) uniform restrict writeonly image3D color_tex; - -#endif // MODE DYNAMIC - -#if defined(MODE_COMPUTE_LIGHT) || defined(MODE_DYNAMIC_LIGHTING) - -float raymarch(float distance, float distance_adv, vec3 from, vec3 direction) { - vec3 cell_size = 1.0 / vec3(params.limits); - float occlusion = 1.0; - while (distance > 0.5) { //use this to avoid precision errors - float advance = texture(sampler3D(texture_sdf, texture_sampler), from * cell_size).r * 255.0 - 1.0; - if (advance < 0.0) { - occlusion = 0.0; - break; - } - - occlusion = min(advance, occlusion); - - advance = max(distance_adv, advance - mod(advance, distance_adv)); //should always advance in multiples of distance_adv - - from += direction * advance; - distance -= advance; - } - - return occlusion; //max(0.0,distance); -} - -float get_omni_attenuation(float distance, float inv_range, float decay) { - float nd = distance * inv_range; - nd *= nd; - nd *= nd; // nd^4 - nd = max(1.0 - nd, 0.0); - nd *= nd; // nd^2 - return nd * pow(max(distance, 0.0001), -decay); -} - -bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3 light_pos) { - if (lights.data[light].type == LIGHT_TYPE_DIRECTIONAL) { - light_pos = pos - lights.data[light].direction * length(vec3(params.limits)); - attenuation = 1.0; - - } else { - light_pos = lights.data[light].position; - float distance = length(pos - light_pos); - if (distance >= lights.data[light].radius) { - return false; - } - - attenuation = get_omni_attenuation(distance, 1.0 / lights.data[light].radius, lights.data[light].attenuation); - - if (lights.data[light].type == LIGHT_TYPE_SPOT) { - vec3 rel = normalize(pos - light_pos); - float cos_spot_angle = lights.data[light].cos_spot_angle; - float cos_angle = dot(rel, lights.data[light].direction); - if (cos_angle < cos_spot_angle) { - return false; - } - - float scos = max(cos_angle, cos_spot_angle); - float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cos_spot_angle)); - attenuation *= 1.0 - pow(spot_rim, lights.data[light].inv_spot_attenuation); - } - } - - return true; -} - -float get_normal_advance(vec3 p_normal) { - vec3 normal = p_normal; - vec3 unorm = abs(normal); - - if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) { - // x code - unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0); - } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) { - // y code - unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0); - } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) { - // z code - unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0); - } else { - // oh-no we messed up code - // has to be - unorm = vec3(1.0, 0.0, 0.0); - } - - return 1.0 / dot(normal, unorm); -} - -void clip_segment(vec4 plane, vec3 begin, inout vec3 end) { - vec3 segment = begin - end; - float den = dot(plane.xyz, segment); - - //printf("den is %i\n",den); - if (den < 0.0001) { - return; - } - - float dist = (dot(plane.xyz, begin) - plane.w) / den; - - if (dist < 0.0001 || dist > 1.0001) { - return; - } - - end = begin + segment * -dist; -} - -bool compute_light_at_pos(uint index, vec3 pos, vec3 normal, inout vec3 light, inout vec3 light_dir) { - float attenuation; - vec3 light_pos; - - if (!compute_light_vector(index, pos, attenuation, light_pos)) { - return false; - } - - light_dir = normalize(pos - light_pos); - - if (attenuation < 0.01 || (length(normal) > 0.2 && dot(normal, light_dir) >= 0)) { - return false; //not facing the light, or attenuation is near zero - } - - if (lights.data[index].has_shadow) { - float distance_adv = get_normal_advance(light_dir); - - vec3 to = pos; - if (length(normal) > 0.2) { - to += normal * distance_adv * 0.51; - } else { - to -= sign(light_dir) * 0.45; //go near the edge towards the light direction to avoid self occlusion - } - - //clip - clip_segment(mix(vec4(-1.0, 0.0, 0.0, 0.0), vec4(1.0, 0.0, 0.0, float(params.limits.x - 1)), bvec4(light_dir.x < 0.0)), to, light_pos); - clip_segment(mix(vec4(0.0, -1.0, 0.0, 0.0), vec4(0.0, 1.0, 0.0, float(params.limits.y - 1)), bvec4(light_dir.y < 0.0)), to, light_pos); - clip_segment(mix(vec4(0.0, 0.0, -1.0, 0.0), vec4(0.0, 0.0, 1.0, float(params.limits.z - 1)), bvec4(light_dir.z < 0.0)), to, light_pos); - - float distance = length(to - light_pos); - if (distance < 0.1) { - return false; // hit - } - - distance += distance_adv - mod(distance, distance_adv); //make it reach the center of the box always - light_pos = to - light_dir * distance; - - //from -= sign(light_dir)*0.45; //go near the edge towards the light direction to avoid self occlusion - - /*float dist = raymarch(distance,distance_adv,light_pos,light_dir); - - if (dist > distance_adv) { - return false; - } - - attenuation *= 1.0 - smoothstep(0.1*distance_adv,distance_adv,dist); - */ - - float occlusion = raymarch(distance, distance_adv, light_pos, light_dir); - - if (occlusion == 0.0) { - return false; - } - - attenuation *= occlusion; //1.0 - smoothstep(0.1*distance_adv,distance_adv,dist); - } - - light = lights.data[index].color * attenuation * lights.data[index].energy; - return true; -} - -#endif // MODE COMPUTE LIGHT - -void main() { -#ifndef MODE_DYNAMIC - - uint cell_index = gl_GlobalInvocationID.x; - if (cell_index >= params.cell_count) { - return; - } - cell_index += params.cell_offset; - - uvec3 posu = uvec3(cell_data.data[cell_index].position & 0x7FF, (cell_data.data[cell_index].position >> 11) & 0x3FF, cell_data.data[cell_index].position >> 21); - vec4 albedo = unpackUnorm4x8(cell_data.data[cell_index].albedo); - -#endif - - /////////////////COMPUTE LIGHT/////////////////////////////// - -#ifdef MODE_COMPUTE_LIGHT - - vec3 pos = vec3(posu) + vec3(0.5); - - vec3 emission = vec3(uvec3(cell_data.data[cell_index].emission & 0x1ff, (cell_data.data[cell_index].emission >> 9) & 0x1ff, (cell_data.data[cell_index].emission >> 18) & 0x1ff)) * pow(2.0, float(cell_data.data[cell_index].emission >> 27) - 15.0 - 9.0); - vec3 normal = unpackSnorm4x8(cell_data.data[cell_index].normal).xyz; - -#ifdef MODE_ANISOTROPIC - vec3 accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); - const vec3 accum_dirs[6] = vec3[](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0)); -#else - vec3 accum = vec3(0.0); -#endif - - for (uint i = 0; i < params.light_count; i++) { - vec3 light; - vec3 light_dir; - if (!compute_light_at_pos(i, pos, normal.xyz, light, light_dir)) { - continue; - } - - light *= albedo.rgb; - -#ifdef MODE_ANISOTROPIC - for (uint j = 0; j < 6; j++) { - accum[j] += max(0.0, dot(accum_dirs[j], -light_dir)) * light; - } -#else - if (length(normal) > 0.2) { - accum += max(0.0, dot(normal, -light_dir)) * light; - } else { - //all directions - accum += light; - } -#endif - } - -#ifdef MODE_ANISOTROPIC - - for (uint i = 0; i < 6; i++) { - vec3 light = accum[i]; - if (length(normal) > 0.2) { - light += max(0.0, dot(accum_dirs[i], -normal)) * emission; - } else { - light += emission; - } - - outputs.data[cell_index * 6 + i] = vec4(light, 0.0); - } - -#else - outputs.data[cell_index] = vec4(accum + emission, 0.0); - -#endif - -#endif //MODE_COMPUTE_LIGHT - - /////////////////SECOND BOUNCE/////////////////////////////// - -#ifdef MODE_SECOND_BOUNCE - vec3 pos = vec3(posu) + vec3(0.5); - ivec3 ipos = ivec3(posu); - vec4 normal = unpackSnorm4x8(cell_data.data[cell_index].normal); - -#ifdef MODE_ANISOTROPIC - vec3 accum[6]; - const vec3 accum_dirs[6] = vec3[](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0)); - - /*vec3 src_color = texelFetch(sampler3D(color_texture,texture_sampler),ipos,0).rgb * params.dynamic_range; - vec3 src_aniso_pos = texelFetch(sampler3D(aniso_pos_texture,texture_sampler),ipos,0).rgb; - vec3 src_anisp_neg = texelFetch(sampler3D(anisp_neg_texture,texture_sampler),ipos,0).rgb; - accum[0]=src_col * src_aniso_pos.x; - accum[1]=src_col * src_aniso_neg.x; - accum[2]=src_col * src_aniso_pos.y; - accum[3]=src_col * src_aniso_neg.y; - accum[4]=src_col * src_aniso_pos.z; - accum[5]=src_col * src_aniso_neg.z;*/ - - accum[0] = outputs.data[cell_index * 6 + 0].rgb; - accum[1] = outputs.data[cell_index * 6 + 1].rgb; - accum[2] = outputs.data[cell_index * 6 + 2].rgb; - accum[3] = outputs.data[cell_index * 6 + 3].rgb; - accum[4] = outputs.data[cell_index * 6 + 4].rgb; - accum[5] = outputs.data[cell_index * 6 + 5].rgb; - -#else - vec3 accum = outputs.data[cell_index].rgb; - -#endif - - if (length(normal.xyz) > 0.2) { - vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); - vec3 tangent = normalize(cross(v0, normal.xyz)); - vec3 bitangent = normalize(cross(tangent, normal.xyz)); - mat3 normal_mat = mat3(tangent, bitangent, normal.xyz); - -#define MAX_CONE_DIRS 6 - - vec3 cone_dirs[MAX_CONE_DIRS] = vec3[]( - vec3(0.0, 0.0, 1.0), - vec3(0.866025, 0.0, 0.5), - vec3(0.267617, 0.823639, 0.5), - vec3(-0.700629, 0.509037, 0.5), - vec3(-0.700629, -0.509037, 0.5), - vec3(0.267617, -0.823639, 0.5)); - - float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15); - float tan_half_angle = 0.577; - - for (int i = 0; i < MAX_CONE_DIRS; i++) { - vec3 direction = normal_mat * cone_dirs[i]; - vec4 color = vec4(0.0); - { - float dist = 1.5; - float max_distance = length(vec3(params.limits)); - vec3 cell_size = 1.0 / vec3(params.limits); - -#ifdef MODE_ANISOTROPIC - vec3 aniso_normal = mix(direction, normal.xyz, params.aniso_strength); -#endif - while (dist < max_distance && color.a < 0.95) { - float diameter = max(1.0, 2.0 * tan_half_angle * dist); - vec3 uvw_pos = (pos + dist * direction) * cell_size; - float half_diameter = diameter * 0.5; - //check if outside, then break - //if ( any(greaterThan(abs(uvw_pos - 0.5),vec3(0.5f + half_diameter * cell_size)) ) ) { - // break; - //} - - float log2_diameter = log2(diameter); - vec4 scolor = textureLod(sampler3D(color_texture, texture_sampler), uvw_pos, log2_diameter); -#ifdef MODE_ANISOTROPIC - - vec3 aniso_neg = textureLod(sampler3D(aniso_neg_texture, texture_sampler), uvw_pos, log2_diameter).rgb; - vec3 aniso_pos = textureLod(sampler3D(aniso_pos_texture, texture_sampler), uvw_pos, log2_diameter).rgb; - - scolor.rgb *= dot(max(vec3(0.0), (aniso_normal * aniso_pos)), vec3(1.0)) + dot(max(vec3(0.0), (-aniso_normal * aniso_neg)), vec3(1.0)); -#endif - float a = (1.0 - color.a); - color += a * scolor; - dist += half_diameter; - } - } - color *= cone_weights[i] * vec4(albedo.rgb, 1.0) * params.dynamic_range; //restore range -#ifdef MODE_ANISOTROPIC - for (uint j = 0; j < 6; j++) { - accum[j] += max(0.0, dot(accum_dirs[j], direction)) * color.rgb; - } -#else - accum += color.rgb; -#endif - } - } - -#ifdef MODE_ANISOTROPIC - - outputs.data[cell_index * 6 + 0] = vec4(accum[0], 0.0); - outputs.data[cell_index * 6 + 1] = vec4(accum[1], 0.0); - outputs.data[cell_index * 6 + 2] = vec4(accum[2], 0.0); - outputs.data[cell_index * 6 + 3] = vec4(accum[3], 0.0); - outputs.data[cell_index * 6 + 4] = vec4(accum[4], 0.0); - outputs.data[cell_index * 6 + 5] = vec4(accum[5], 0.0); -#else - outputs.data[cell_index] = vec4(accum, 0.0); - -#endif - -#endif // MODE_SECOND_BOUNCE - - /////////////////UPDATE MIPMAPS/////////////////////////////// - -#ifdef MODE_UPDATE_MIPMAPS - - { -#ifdef MODE_ANISOTROPIC - vec3 light_accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); -#else - vec3 light_accum = vec3(0.0); -#endif - float count = 0.0; - for (uint i = 0; i < 8; i++) { - uint child_index = cell_children.data[cell_index].children[i]; - if (child_index == NO_CHILDREN) { - continue; - } -#ifdef MODE_ANISOTROPIC - light_accum[0] += outputs.data[child_index * 6 + 0].rgb; - light_accum[1] += outputs.data[child_index * 6 + 1].rgb; - light_accum[2] += outputs.data[child_index * 6 + 2].rgb; - light_accum[3] += outputs.data[child_index * 6 + 3].rgb; - light_accum[4] += outputs.data[child_index * 6 + 4].rgb; - light_accum[5] += outputs.data[child_index * 6 + 5].rgb; - -#else - light_accum += outputs.data[child_index].rgb; - -#endif - - count += 1.0; - } - - float divisor = mix(8.0, count, params.propagation); -#ifdef MODE_ANISOTROPIC - outputs.data[cell_index * 6 + 0] = vec4(light_accum[0] / divisor, 0.0); - outputs.data[cell_index * 6 + 1] = vec4(light_accum[1] / divisor, 0.0); - outputs.data[cell_index * 6 + 2] = vec4(light_accum[2] / divisor, 0.0); - outputs.data[cell_index * 6 + 3] = vec4(light_accum[3] / divisor, 0.0); - outputs.data[cell_index * 6 + 4] = vec4(light_accum[4] / divisor, 0.0); - outputs.data[cell_index * 6 + 5] = vec4(light_accum[5] / divisor, 0.0); - -#else - outputs.data[cell_index] = vec4(light_accum / divisor, 0.0); -#endif - } -#endif - - ///////////////////WRITE TEXTURE///////////////////////////// - -#ifdef MODE_WRITE_TEXTURE - { -#ifdef MODE_ANISOTROPIC - vec3 accum_total = vec3(0.0); - accum_total += outputs.data[cell_index * 6 + 0].rgb; - accum_total += outputs.data[cell_index * 6 + 1].rgb; - accum_total += outputs.data[cell_index * 6 + 2].rgb; - accum_total += outputs.data[cell_index * 6 + 3].rgb; - accum_total += outputs.data[cell_index * 6 + 4].rgb; - accum_total += outputs.data[cell_index * 6 + 5].rgb; - - float accum_total_energy = max(dot(accum_total, GREY_VEC), 0.00001); - vec3 iso_positive = vec3(dot(outputs.data[cell_index * 6 + 0].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 2].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 4].rgb, GREY_VEC)) / vec3(accum_total_energy); - vec3 iso_negative = vec3(dot(outputs.data[cell_index * 6 + 1].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 3].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 5].rgb, GREY_VEC)) / vec3(accum_total_energy); - - { - uint aniso_pos = uint(clamp(iso_positive.b * 31.0, 0.0, 31.0)); - aniso_pos |= uint(clamp(iso_positive.g * 63.0, 0.0, 63.0)) << 5; - aniso_pos |= uint(clamp(iso_positive.r * 31.0, 0.0, 31.0)) << 11; - imageStore(aniso_pos_tex, ivec3(posu), uvec4(aniso_pos)); - } - - { - uint aniso_neg = uint(clamp(iso_negative.b * 31.0, 0.0, 31.0)); - aniso_neg |= uint(clamp(iso_negative.g * 63.0, 0.0, 63.0)) << 5; - aniso_neg |= uint(clamp(iso_negative.r * 31.0, 0.0, 31.0)) << 11; - imageStore(aniso_neg_tex, ivec3(posu), uvec4(aniso_neg)); - } - - imageStore(color_tex, ivec3(posu), vec4(accum_total / params.dynamic_range, albedo.a)); - -#else - - imageStore(color_tex, ivec3(posu), vec4(outputs.data[cell_index].rgb / params.dynamic_range, albedo.a)); - -#endif - } -#endif - - ///////////////////DYNAMIC LIGHTING///////////////////////////// - -#ifdef MODE_DYNAMIC - - ivec2 pos_xy = ivec2(gl_GlobalInvocationID.xy); - if (any(greaterThanEqual(pos_xy, params.rect_size))) { - return; //out of bounds - } - - ivec2 uv_xy = pos_xy; - if (params.flip_x) { - uv_xy.x = params.rect_size.x - pos_xy.x - 1; - } - if (params.flip_y) { - uv_xy.y = params.rect_size.y - pos_xy.y - 1; - } - -#ifdef MODE_DYNAMIC_LIGHTING - - { - float z = params.z_base + imageLoad(depth, uv_xy).x * params.z_sign; - - ivec3 pos = params.x_dir * (params.rect_pos.x + pos_xy.x) + params.y_dir * (params.rect_pos.y + pos_xy.y) + abs(params.z_dir) * int(z); - - vec3 normal = imageLoad(source_normal, uv_xy).xyz * 2.0 - 1.0; - normal = vec3(params.x_dir) * normal.x * mix(1.0, -1.0, params.flip_x) + vec3(params.y_dir) * normal.y * mix(1.0, -1.0, params.flip_y) - vec3(params.z_dir) * normal.z; - - vec4 albedo = imageLoad(source_albedo, uv_xy); - - //determine the position in space - - vec3 accum = vec3(0.0); - for (uint i = 0; i < params.light_count; i++) { - vec3 light; - vec3 light_dir; - if (!compute_light_at_pos(i, vec3(pos) * params.pos_multiplier, normal, light, light_dir)) { - continue; - } - - light *= albedo.rgb; - - accum += max(0.0, dot(normal, -light_dir)) * light; - } - - accum += imageLoad(emission, uv_xy).xyz; - - imageStore(emission, uv_xy, vec4(accum, albedo.a)); - imageStore(depth, uv_xy, vec4(z)); - } - -#endif // MODE DYNAMIC LIGHTING - -#ifdef MODE_DYNAMIC_SHRINK - - { - vec4 accum = vec4(0.0); - float accum_z = 0.0; - float count = 0.0; - - for (int i = 0; i < 4; i++) { - ivec2 ofs = pos_xy * 2 + ivec2(i & 1, i >> 1) - params.prev_rect_ofs; - if (any(lessThan(ofs, ivec2(0))) || any(greaterThanEqual(ofs, params.prev_rect_size))) { - continue; - } - if (params.flip_x) { - ofs.x = params.prev_rect_size.x - ofs.x - 1; - } - if (params.flip_y) { - ofs.y = params.prev_rect_size.y - ofs.y - 1; - } - - vec4 light = imageLoad(source_light, ofs); - if (light.a == 0.0) { //ignore empty - continue; - } - accum += light; - float z = imageLoad(source_depth, ofs).x; - accum_z += z * 0.5; //shrink half too - count += 1.0; - } - - if (params.on_mipmap) { - accum.rgb /= mix(8.0, count, params.propagation); - accum.a /= 8.0; - } else { - accum /= 4.0; - } - - if (count == 0.0) { - accum_z = 0.0; //avoid nan - } else { - accum_z /= count; - } - -#ifdef MODE_DYNAMIC_SHRINK_WRITE - - imageStore(light, uv_xy, accum); - imageStore(depth, uv_xy, vec4(accum_z)); -#endif - -#ifdef MODE_DYNAMIC_SHRINK_PLOT - - if (accum.a < 0.001) { - return; //do not blit if alpha is too low - } - - ivec3 pos = params.x_dir * (params.rect_pos.x + pos_xy.x) + params.y_dir * (params.rect_pos.y + pos_xy.y) + abs(params.z_dir) * int(accum_z); - - float z_frac = fract(accum_z); - - for (int i = 0; i < 2; i++) { - ivec3 pos3d = pos + abs(params.z_dir) * i; - if (any(lessThan(pos3d, ivec3(0))) || any(greaterThanEqual(pos3d, params.limits))) { - //skip if offlimits - continue; - } - vec4 color_blit = accum * (i == 0 ? 1.0 - z_frac : z_frac); - vec4 color = imageLoad(color_texture, pos3d); - color.rgb *= params.dynamic_range; - -#if 0 - color.rgb = mix(color.rgb,color_blit.rgb,color_blit.a); - color.a+=color_blit.a; -#else - - float sa = 1.0 - color_blit.a; - vec4 result; - result.a = color.a * sa + color_blit.a; - if (result.a == 0.0) { - result = vec4(0.0); - } else { - result.rgb = (color.rgb * color.a * sa + color_blit.rgb * color_blit.a) / result.a; - color = result; - } - -#endif - color.rgb /= params.dynamic_range; - imageStore(color_texture, pos3d, color); - //imageStore(color_texture,pos3d,vec4(1,1,1,1)); - -#ifdef MODE_ANISOTROPIC - //do not care about anisotropy for dynamic objects, just store full lit in all directions - imageStore(aniso_pos_texture, pos3d, uvec4(0xFFFF)); - imageStore(aniso_neg_texture, pos3d, uvec4(0xFFFF)); - -#endif // ANISOTROPIC - } -#endif // MODE_DYNAMIC_SHRINK_PLOT - } -#endif - -#endif // MODE DYNAMIC -} diff --git a/servers/rendering/renderer_rd/shaders/giprobe_debug.glsl b/servers/rendering/renderer_rd/shaders/giprobe_debug.glsl deleted file mode 100644 index 7d4d72967a..0000000000 --- a/servers/rendering/renderer_rd/shaders/giprobe_debug.glsl +++ /dev/null @@ -1,229 +0,0 @@ -#[vertex] - -#version 450 - -#VERSION_DEFINES - -struct CellData { - uint position; // xyz 10 bits - uint albedo; //rgb albedo - uint emission; //rgb normalized with e as multiplier - uint normal; //RGB normal encoded -}; - -layout(set = 0, binding = 1, std140) buffer CellDataBuffer { - CellData data[]; -} -cell_data; - -layout(set = 0, binding = 2) uniform texture3D color_tex; - -layout(set = 0, binding = 3) uniform sampler tex_sampler; - -#ifdef USE_ANISOTROPY -layout(set = 0, binding = 4) uniform texture3D aniso_pos_tex; -layout(set = 0, binding = 5) uniform texture3D aniso_neg_tex; -#endif - -layout(push_constant, binding = 0, std430) uniform Params { - mat4 projection; - uint cell_offset; - float dynamic_range; - float alpha; - uint level; - ivec3 bounds; - uint pad; -} -params; - -layout(location = 0) out vec4 color_interp; - -void main() { - const vec3 cube_triangles[36] = vec3[]( - vec3(-1.0f, -1.0f, -1.0f), - vec3(-1.0f, -1.0f, 1.0f), - vec3(-1.0f, 1.0f, 1.0f), - vec3(1.0f, 1.0f, -1.0f), - vec3(-1.0f, -1.0f, -1.0f), - vec3(-1.0f, 1.0f, -1.0f), - vec3(1.0f, -1.0f, 1.0f), - vec3(-1.0f, -1.0f, -1.0f), - vec3(1.0f, -1.0f, -1.0f), - vec3(1.0f, 1.0f, -1.0f), - vec3(1.0f, -1.0f, -1.0f), - vec3(-1.0f, -1.0f, -1.0f), - vec3(-1.0f, -1.0f, -1.0f), - vec3(-1.0f, 1.0f, 1.0f), - vec3(-1.0f, 1.0f, -1.0f), - vec3(1.0f, -1.0f, 1.0f), - vec3(-1.0f, -1.0f, 1.0f), - vec3(-1.0f, -1.0f, -1.0f), - vec3(-1.0f, 1.0f, 1.0f), - vec3(-1.0f, -1.0f, 1.0f), - vec3(1.0f, -1.0f, 1.0f), - vec3(1.0f, 1.0f, 1.0f), - vec3(1.0f, -1.0f, -1.0f), - vec3(1.0f, 1.0f, -1.0f), - vec3(1.0f, -1.0f, -1.0f), - vec3(1.0f, 1.0f, 1.0f), - vec3(1.0f, -1.0f, 1.0f), - vec3(1.0f, 1.0f, 1.0f), - vec3(1.0f, 1.0f, -1.0f), - vec3(-1.0f, 1.0f, -1.0f), - vec3(1.0f, 1.0f, 1.0f), - vec3(-1.0f, 1.0f, -1.0f), - vec3(-1.0f, 1.0f, 1.0f), - vec3(1.0f, 1.0f, 1.0f), - vec3(-1.0f, 1.0f, 1.0f), - vec3(1.0f, -1.0f, 1.0f)); - - vec3 vertex = cube_triangles[gl_VertexIndex] * 0.5 + 0.5; -#ifdef MODE_DEBUG_LIGHT_FULL - uvec3 posu = uvec3(gl_InstanceIndex % params.bounds.x, (gl_InstanceIndex / params.bounds.x) % params.bounds.y, gl_InstanceIndex / (params.bounds.y * params.bounds.x)); -#else - uint cell_index = gl_InstanceIndex + params.cell_offset; - - uvec3 posu = uvec3(cell_data.data[cell_index].position & 0x7FF, (cell_data.data[cell_index].position >> 11) & 0x3FF, cell_data.data[cell_index].position >> 21); -#endif - -#ifdef MODE_DEBUG_EMISSION - color_interp.xyz = vec3(uvec3(cell_data.data[cell_index].emission & 0x1ff, (cell_data.data[cell_index].emission >> 9) & 0x1ff, (cell_data.data[cell_index].emission >> 18) & 0x1ff)) * pow(2.0, float(cell_data.data[cell_index].emission >> 27) - 15.0 - 9.0); -#endif - -#ifdef MODE_DEBUG_COLOR - color_interp.xyz = unpackUnorm4x8(cell_data.data[cell_index].albedo).xyz; -#endif - -#ifdef MODE_DEBUG_LIGHT - -#ifdef USE_ANISOTROPY - -#define POS_X 0 -#define POS_Y 1 -#define POS_Z 2 -#define NEG_X 3 -#define NEG_Y 4 -#define NEG_Z 5 - - const uint triangle_aniso[12] = uint[]( - NEG_X, - NEG_Z, - NEG_Y, - NEG_Z, - NEG_X, - NEG_Y, - POS_Z, - POS_X, - POS_X, - POS_Y, - POS_Y, - POS_Z); - - color_interp.xyz = texelFetch(sampler3D(color_tex, tex_sampler), ivec3(posu), int(params.level)).xyz * params.dynamic_range; - vec3 aniso_pos = texelFetch(sampler3D(aniso_pos_tex, tex_sampler), ivec3(posu), int(params.level)).xyz; - vec3 aniso_neg = texelFetch(sampler3D(aniso_neg_tex, tex_sampler), ivec3(posu), int(params.level)).xyz; - uint side = triangle_aniso[gl_VertexIndex / 3]; - - float strength = 0.0; - switch (side) { - case POS_X: - strength = aniso_pos.x; - break; - case POS_Y: - strength = aniso_pos.y; - break; - case POS_Z: - strength = aniso_pos.z; - break; - case NEG_X: - strength = aniso_neg.x; - break; - case NEG_Y: - strength = aniso_neg.y; - break; - case NEG_Z: - strength = aniso_neg.z; - break; - } - - color_interp.xyz *= strength; - -#else - color_interp = texelFetch(sampler3D(color_tex, tex_sampler), ivec3(posu), int(params.level)); - color_interp.xyz *params.dynamic_range; - -#endif - -#endif - float scale = (1 << params.level); - - gl_Position = params.projection * vec4((vec3(posu) + vertex) * scale, 1.0); - -#ifdef MODE_DEBUG_LIGHT_FULL - if (color_interp.a == 0.0) { - gl_Position = vec4(0.0); //force clip and not draw - } -#else - color_interp.a = params.alpha; -#endif -} - -#[fragment] - -#version 450 - -#VERSION_DEFINES - -layout(location = 0) in vec4 color_interp; -layout(location = 0) out vec4 frag_color; - -void main() { - frag_color = color_interp; - -#ifdef MODE_DEBUG_LIGHT_FULL - - //there really is no alpha, so use dither - - int x = int(gl_FragCoord.x) % 4; - int y = int(gl_FragCoord.y) % 4; - int index = x + y * 4; - float limit = 0.0; - if (x < 8) { - if (index == 0) - limit = 0.0625; - if (index == 1) - limit = 0.5625; - if (index == 2) - limit = 0.1875; - if (index == 3) - limit = 0.6875; - if (index == 4) - limit = 0.8125; - if (index == 5) - limit = 0.3125; - if (index == 6) - limit = 0.9375; - if (index == 7) - limit = 0.4375; - if (index == 8) - limit = 0.25; - if (index == 9) - limit = 0.75; - if (index == 10) - limit = 0.125; - if (index == 11) - limit = 0.625; - if (index == 12) - limit = 1.0; - if (index == 13) - limit = 0.5; - if (index == 14) - limit = 0.875; - if (index == 15) - limit = 0.375; - } - if (frag_color.a < limit) { - discard; - } -#endif -} diff --git a/servers/rendering/renderer_rd/shaders/giprobe_sdf.glsl b/servers/rendering/renderer_rd/shaders/giprobe_sdf.glsl deleted file mode 100644 index e20b3f680d..0000000000 --- a/servers/rendering/renderer_rd/shaders/giprobe_sdf.glsl +++ /dev/null @@ -1,181 +0,0 @@ -#[compute] - -#version 450 - -#VERSION_DEFINES - -layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in; - -#define MAX_DISTANCE 100000 - -#define NO_CHILDREN 0xFFFFFFFF -#define GREY_VEC vec3(0.33333, 0.33333, 0.33333) - -struct CellChildren { - uint children[8]; -}; - -layout(set = 0, binding = 1, std430) buffer CellChildrenBuffer { - CellChildren data[]; -} -cell_children; - -struct CellData { - uint position; // xyz 10 bits - uint albedo; //rgb albedo - uint emission; //rgb normalized with e as multiplier - uint normal; //RGB normal encoded -}; - -layout(set = 0, binding = 2, std430) buffer CellDataBuffer { - CellData data[]; -} -cell_data; - -layout(r8ui, set = 0, binding = 3) uniform restrict writeonly uimage3D sdf_tex; - -layout(push_constant, binding = 0, std430) uniform Params { - uint offset; - uint end; - uint pad0; - uint pad1; -} -params; - -void main() { - vec3 pos = vec3(gl_GlobalInvocationID); - float closest_dist = 100000.0; - - for (uint i = params.offset; i < params.end; i++) { - vec3 posu = vec3(uvec3(cell_data.data[i].position & 0x7FF, (cell_data.data[i].position >> 11) & 0x3FF, cell_data.data[i].position >> 21)); - float dist = length(pos - posu); - if (dist < closest_dist) { - closest_dist = dist; - } - } - - uint dist_8; - - if (closest_dist < 0.0001) { // same cell - dist_8 = 0; //equals to -1 - } else { - dist_8 = clamp(uint(closest_dist), 0, 254) + 1; //conservative, 0 is 1, so <1 is considered solid - } - - imageStore(sdf_tex, ivec3(gl_GlobalInvocationID), uvec4(dist_8)); - //imageStore(sdf_tex,pos,uvec4(pos*2,0)); -} - -#if 0 -layout(push_constant, binding = 0, std430) uniform Params { - ivec3 limits; - uint stack_size; -} -params; - -float distance_to_aabb(ivec3 pos, ivec3 aabb_pos, ivec3 aabb_size) { - vec3 delta = vec3(max(ivec3(0), max(aabb_pos - pos, pos - (aabb_pos + aabb_size - ivec3(1))))); - return length(delta); -} - -void main() { - ivec3 pos = ivec3(gl_GlobalInvocationID); - - uint stack[10] = uint[](0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - uint stack_indices[10] = uint[](0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - ivec3 stack_positions[10] = ivec3[](ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0)); - - const uint cell_orders[8] = uint[]( - 0x11f58d1, - 0xe2e70a, - 0xd47463, - 0xbb829c, - 0x8d11f5, - 0x70ae2e, - 0x463d47, - 0x29cbb8); - - bool cell_found = false; - bool cell_found_exact = false; - ivec3 closest_cell_pos; - float closest_distance = MAX_DISTANCE; - int stack_pos = 0; - - while (true) { - uint index = stack_indices[stack_pos] >> 24; - - if (index == 8) { - //go up - if (stack_pos == 0) { - break; //done going through octree - } - stack_pos--; - continue; - } - - stack_indices[stack_pos] = (stack_indices[stack_pos] & ((1 << 24) - 1)) | ((index + 1) << 24); - - uint cell_index = (stack_indices[stack_pos] >> (index * 3)) & 0x7; - uint child_cell = cell_children.data[stack[stack_pos]].children[cell_index]; - - if (child_cell == NO_CHILDREN) { - continue; - } - - ivec3 child_cell_size = params.limits >> (stack_pos + 1); - ivec3 child_cell_pos = stack_positions[stack_pos]; - - child_cell_pos += mix(ivec3(0), child_cell_size, bvec3(uvec3(index & 1, index & 2, index & 4) != uvec3(0))); - - bool is_leaf = stack_pos == (params.stack_size - 2); - - if (child_cell_pos == pos && is_leaf) { - //we may actually end up in the exact cell. - //if this happens, just abort - cell_found_exact = true; - break; - } - - if (cell_found) { - //discard by distance - float distance = distance_to_aabb(pos, child_cell_pos, child_cell_size); - if (distance >= closest_distance) { - continue; //pointless, just test next child - } else if (is_leaf) { - //closer than what we have AND end of stack, save and continue - closest_cell_pos = child_cell_pos; - closest_distance = distance; - continue; - } - } else if (is_leaf) { - //first solid cell we find, save and continue - closest_distance = distance_to_aabb(pos, child_cell_pos, child_cell_size); - closest_cell_pos = child_cell_pos; - cell_found = true; - continue; - } - - bvec3 direction = greaterThan((pos - (child_cell_pos + (child_cell_size >> 1))), ivec3(0)); - uint cell_order = 0; - cell_order |= mix(0, 1, direction.x); - cell_order |= mix(0, 2, direction.y); - cell_order |= mix(0, 4, direction.z); - - stack[stack_pos + 1] = child_cell; - stack_indices[stack_pos + 1] = cell_orders[cell_order]; //start counting - stack_positions[stack_pos + 1] = child_cell_pos; - stack_pos++; //go up stack - } - - uint dist_8; - - if (cell_found_exact) { - dist_8 = 0; //equals to -1 - } else { - float closest_distance = length(vec3(pos - closest_cell_pos)); - dist_8 = clamp(uint(closest_distance), 0, 254) + 1; //conservative, 0 is 1, so <1 is considered solid - } - - imageStore(sdf_tex, pos, uvec4(dist_8)); -} -#endif diff --git a/servers/rendering/renderer_rd/shaders/resolve.glsl b/servers/rendering/renderer_rd/shaders/resolve.glsl index 2286a26485..a4610e081c 100644 --- a/servers/rendering/renderer_rd/shaders/resolve.glsl +++ b/servers/rendering/renderer_rd/shaders/resolve.glsl @@ -13,9 +13,9 @@ layout(set = 0, binding = 1) uniform sampler2DMS source_normal_roughness; layout(r32f, set = 1, binding = 0) uniform restrict writeonly image2D dest_depth; layout(rgba8, set = 1, binding = 1) uniform restrict writeonly image2D dest_normal_roughness; -#ifdef GIPROBE_RESOLVE -layout(set = 2, binding = 0) uniform usampler2DMS source_giprobe; -layout(rg8ui, set = 3, binding = 0) uniform restrict writeonly uimage2D dest_giprobe; +#ifdef VOXEL_GI_RESOLVE +layout(set = 2, binding = 0) uniform usampler2DMS source_voxel_gi; +layout(rg8ui, set = 3, binding = 0) uniform restrict writeonly uimage2D dest_voxel_gi; #endif #endif @@ -38,8 +38,8 @@ void main() { float best_depth = 1e20; vec4 best_normal_roughness = vec4(0.0); -#ifdef GIPROBE_RESOLVE - uvec2 best_giprobe; +#ifdef VOXEL_GI_RESOLVE + uvec2 best_voxel_gi; #endif #if 0 @@ -50,8 +50,8 @@ void main() { best_depth = depth; best_normal_roughness = texelFetch(source_normal_roughness,pos,i); -#ifdef GIPROBE_RESOLVE - best_giprobe = texelFetch(source_giprobe,pos,i).rg; +#ifdef VOXEL_GI_RESOLVE + best_voxel_gi = texelFetch(source_voxel_gi,pos,i).rg; #endif } } @@ -204,16 +204,16 @@ void main() { #endif best_depth = texelFetch(source_depth, pos, best_index).r; best_normal_roughness = texelFetch(source_normal_roughness, pos, best_index); -#ifdef GIPROBE_RESOLVE - best_giprobe = texelFetch(source_giprobe, pos, best_index).rg; +#ifdef VOXEL_GI_RESOLVE + best_voxel_gi = texelFetch(source_voxel_gi, pos, best_index).rg; #endif #endif imageStore(dest_depth, pos, vec4(best_depth)); imageStore(dest_normal_roughness, pos, vec4(best_normal_roughness)); -#ifdef GIPROBE_RESOLVE - imageStore(dest_giprobe, pos, uvec4(best_giprobe, 0, 0)); +#ifdef VOXEL_GI_RESOLVE + imageStore(dest_voxel_gi, pos, uvec4(best_voxel_gi, 0, 0)); #endif #endif diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index e09b8f15be..23f56fd42d 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -426,8 +426,8 @@ layout(location = 4) out float depth_output_buffer; #ifdef MODE_RENDER_NORMAL_ROUGHNESS layout(location = 0) out vec4 normal_roughness_output_buffer; -#ifdef MODE_RENDER_GIPROBE -layout(location = 1) out uvec2 giprobe_buffer; +#ifdef MODE_RENDER_VOXEL_GI +layout(location = 1) out uvec2 voxel_gi_buffer; #endif #endif //MODE_RENDER_NORMAL @@ -1042,7 +1042,7 @@ void main() { } } - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes + if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances uint index1 = instances.data[instance_index].gi_offset & 0xFFFF; vec3 ref_vec = normalize(reflect(normalize(vertex), normal)); @@ -1054,12 +1054,12 @@ void main() { vec4 amb_accum = vec4(0.0); vec4 spec_accum = vec4(0.0); - gi_probe_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); + voxel_gi_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); uint index2 = instances.data[instance_index].gi_offset >> 16; if (index2 != 0xFFFF) { - gi_probe_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); + voxel_gi_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); } if (amb_accum.a > 0.0) { @@ -1929,15 +1929,15 @@ void main() { #ifdef MODE_RENDER_NORMAL_ROUGHNESS normal_roughness_output_buffer = vec4(normal * 0.5 + 0.5, roughness); -#ifdef MODE_RENDER_GIPROBE - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes +#ifdef MODE_RENDER_VOXEL_GI + if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances uint index1 = instances.data[instance_index].gi_offset & 0xFFFF; uint index2 = instances.data[instance_index].gi_offset >> 16; - giprobe_buffer.x = index1 & 0xFF; - giprobe_buffer.y = index2 & 0xFF; + voxel_gi_buffer.x = index1 & 0xFF; + voxel_gi_buffer.y = index2 & 0xFF; } else { - giprobe_buffer.x = 0xFF; - giprobe_buffer.y = 0xFF; + voxel_gi_buffer.x = 0xFF; + voxel_gi_buffer.y = 0xFF; } #endif diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl index ca75d6300e..e64e52623e 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl @@ -1,7 +1,7 @@ #define M_PI 3.14159265359 #define ROUGHNESS_MAX_LOD 5 -#define MAX_GI_PROBES 8 +#define MAX_VOXEL_GI_INSTANCES 8 #if defined(has_GL_KHR_shader_subgroup_ballot) && defined(has_GL_KHR_shader_subgroup_arithmetic) @@ -15,7 +15,7 @@ #include "cluster_data_inc.glsl" #include "decal_data_inc.glsl" -#if !defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) || defined(MODE_RENDER_SDF) || defined(MODE_RENDER_NORMAL_ROUGHNESS) || defined(MODE_RENDER_GIPROBE) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) +#if !defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) || defined(MODE_RENDER_SDF) || defined(MODE_RENDER_NORMAL_ROUGHNESS) || defined(MODE_RENDER_VOXEL_GI) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) #ifndef NORMAL_USED #define NORMAL_USED #endif @@ -57,7 +57,7 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler; #define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 8) #define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 9) #define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 10) -#define INSTANCE_FLAGS_USE_GIPROBE (1 << 11) +#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 11) #define INSTANCE_FLAGS_MULTIMESH (1 << 12) #define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13) #define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14) @@ -122,7 +122,7 @@ layout(set = 0, binding = 12, std430) restrict readonly buffer GlobalVariableDat } global_variables; -struct SDFGIProbeCascadeData { +struct SDFVoxelGICascadeData { vec3 position; float to_probe; ivec3 probe_world_offset; @@ -153,7 +153,7 @@ layout(set = 0, binding = 13, std140) uniform SDFGI { vec3 cascade_probe_size; uint pad5; - SDFGIProbeCascadeData cascades[SDFGI_MAX_CASCADES]; + SDFVoxelGICascadeData cascades[SDFGI_MAX_CASCADES]; } sdfgi; @@ -275,7 +275,7 @@ layout(set = 1, binding = 5) uniform texture2D directional_shadow_atlas; layout(set = 1, binding = 6) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES]; -layout(set = 1, binding = 7) uniform texture3D gi_probe_textures[MAX_GI_PROBES]; +layout(set = 1, binding = 7) uniform texture3D voxel_gi_textures[MAX_VOXEL_GI_INSTANCES]; layout(set = 1, binding = 8, std430) buffer restrict readonly ClusterBuffer { uint data[]; @@ -306,7 +306,7 @@ layout(set = 1, binding = 14) uniform texture2D reflection_buffer; layout(set = 1, binding = 15) uniform texture2DArray sdfgi_lightprobe_texture; layout(set = 1, binding = 16) uniform texture3D sdfgi_occlusion_cascades; -struct GIProbeData { +struct VoxelGIData { mat4 xform; vec3 bounds; float dynamic_range; @@ -322,10 +322,10 @@ struct GIProbeData { uint mipmaps; }; -layout(set = 1, binding = 17, std140) uniform GIProbes { - GIProbeData data[MAX_GI_PROBES]; +layout(set = 1, binding = 17, std140) uniform VoxelGIs { + VoxelGIData data[MAX_VOXEL_GI_INSTANCES]; } -gi_probes; +voxel_gi_instances; layout(set = 1, binding = 18) uniform texture3D volumetric_fog_texture; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl index b41f16cbe7..c88bd0a14b 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl @@ -48,24 +48,24 @@ vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3 return color; } -void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 normal_xform, float roughness, vec3 ambient, vec3 environment, inout vec4 out_spec, inout vec4 out_diff) { - position = (gi_probes.data[index].xform * vec4(position, 1.0)).xyz; - ref_vec = normalize((gi_probes.data[index].xform * vec4(ref_vec, 0.0)).xyz); - normal = normalize((gi_probes.data[index].xform * vec4(normal, 0.0)).xyz); +void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 normal_xform, float roughness, vec3 ambient, vec3 environment, inout vec4 out_spec, inout vec4 out_diff) { + position = (voxel_gi_instances.data[index].xform * vec4(position, 1.0)).xyz; + ref_vec = normalize((voxel_gi_instances.data[index].xform * vec4(ref_vec, 0.0)).xyz); + normal = normalize((voxel_gi_instances.data[index].xform * vec4(normal, 0.0)).xyz); - position += normal * gi_probes.data[index].normal_bias; + position += normal * voxel_gi_instances.data[index].normal_bias; //this causes corrupted pixels, i have no idea why.. - if (any(bvec2(any(lessThan(position, vec3(0.0))), any(greaterThan(position, gi_probes.data[index].bounds))))) { + if (any(bvec2(any(lessThan(position, vec3(0.0))), any(greaterThan(position, voxel_gi_instances.data[index].bounds))))) { return; } - vec3 blendv = abs(position / gi_probes.data[index].bounds * 2.0 - 1.0); + vec3 blendv = abs(position / voxel_gi_instances.data[index].bounds * 2.0 - 1.0); float blend = clamp(1.0 - max(blendv.x, max(blendv.y, blendv.z)), 0.0, 1.0); //float blend=1.0; - float max_distance = length(gi_probes.data[index].bounds); - vec3 cell_size = 1.0 / gi_probes.data[index].bounds; + float max_distance = length(voxel_gi_instances.data[index].bounds); + vec3 cell_size = 1.0 / voxel_gi_instances.data[index].bounds; //radiance @@ -83,26 +83,26 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 vec3 light = vec3(0.0); for (int i = 0; i < MAX_CONE_DIRS; i++) { - vec3 dir = normalize((gi_probes.data[index].xform * vec4(normal_xform * cone_dirs[i], 0.0)).xyz); + vec3 dir = normalize((voxel_gi_instances.data[index].xform * vec4(normal_xform * cone_dirs[i], 0.0)).xyz); - vec4 cone_light = voxel_cone_trace_45_degrees(gi_probe_textures[index], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias); + vec4 cone_light = voxel_cone_trace_45_degrees(voxel_gi_textures[index], cell_size, position, dir, cone_angle_tan, max_distance, voxel_gi_instances.data[index].bias); - if (gi_probes.data[index].blend_ambient) { + if (voxel_gi_instances.data[index].blend_ambient) { cone_light.rgb = mix(ambient, cone_light.rgb, min(1.0, cone_light.a / 0.95)); } light += cone_weights[i] * cone_light.rgb; } - light *= gi_probes.data[index].dynamic_range; + light *= voxel_gi_instances.data[index].dynamic_range; out_diff += vec4(light * blend, blend); //irradiance - vec4 irr_light = voxel_cone_trace(gi_probe_textures[index], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, gi_probes.data[index].bias); - if (gi_probes.data[index].blend_ambient) { + vec4 irr_light = voxel_cone_trace(voxel_gi_textures[index], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, voxel_gi_instances.data[index].bias); + if (voxel_gi_instances.data[index].blend_ambient) { irr_light.rgb = mix(environment, irr_light.rgb, min(1.0, irr_light.a / 0.95)); } - irr_light.rgb *= gi_probes.data[index].dynamic_range; + irr_light.rgb *= voxel_gi_instances.data[index].dynamic_range; //irr_light=vec3(0.0); out_spec += vec4(irr_light.rgb * blend, blend); diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl index 0156b58574..656a764a89 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl @@ -51,7 +51,7 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler; #define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 8) #define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 9) #define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 10) -#define INSTANCE_FLAGS_USE_GIPROBE (1 << 11) +#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 11) #define INSTANCE_FLAGS_MULTIMESH (1 << 12) #define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13) #define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14) diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl index c793b6ebe1..f2010222e5 100644 --- a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl +++ b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl @@ -72,9 +72,9 @@ layout(rgba16f, set = 0, binding = 9) uniform restrict writeonly image3D dest_ma layout(set = 0, binding = 10) uniform sampler shadow_sampler; -#define MAX_GI_PROBES 8 +#define MAX_VOXEL_GI_INSTANCES 8 -struct GIProbeData { +struct VoxelGIData { mat4 xform; vec3 bounds; float dynamic_range; @@ -90,12 +90,12 @@ struct GIProbeData { uint mipmaps; }; -layout(set = 0, binding = 11, std140) uniform GIProbes { - GIProbeData data[MAX_GI_PROBES]; +layout(set = 0, binding = 11, std140) uniform VoxelGIs { + VoxelGIData data[MAX_VOXEL_GI_INSTANCES]; } -gi_probes; +voxel_gi_instances; -layout(set = 0, binding = 12) uniform texture3D gi_probe_textures[MAX_GI_PROBES]; +layout(set = 0, binding = 12) uniform texture3D voxel_gi_textures[MAX_VOXEL_GI_INSTANCES]; layout(set = 0, binding = 13) uniform sampler linear_sampler_with_mipmaps; @@ -104,7 +104,7 @@ layout(set = 0, binding = 13) uniform sampler linear_sampler_with_mipmaps; // SDFGI Integration on set 1 #define SDFGI_MAX_CASCADES 8 -struct SDFGIProbeCascadeData { +struct SDFVoxelGICascadeData { vec3 position; float to_probe; ivec3 probe_world_offset; @@ -135,7 +135,7 @@ layout(set = 1, binding = 0, std140) uniform SDFGI { vec3 cascade_probe_size; uint pad5; - SDFGIProbeCascadeData cascades[SDFGI_MAX_CASCADES]; + SDFVoxelGICascadeData cascades[SDFGI_MAX_CASCADES]; } sdfgi; @@ -162,7 +162,7 @@ layout(set = 0, binding = 14, std140) uniform Params { float detail_spread; float gi_inject; - uint max_gi_probes; + uint max_voxel_gi_instances; uint cluster_type_size; vec2 screen_size; @@ -533,21 +533,21 @@ void main() { vec3 world_pos = mat3(params.cam_rotation) * view_pos; - for (uint i = 0; i < params.max_gi_probes; i++) { - vec3 position = (gi_probes.data[i].xform * vec4(world_pos, 1.0)).xyz; + for (uint i = 0; i < params.max_voxel_gi_instances; i++) { + vec3 position = (voxel_gi_instances.data[i].xform * vec4(world_pos, 1.0)).xyz; //this causes corrupted pixels, i have no idea why.. - if (all(bvec2(all(greaterThanEqual(position, vec3(0.0))), all(lessThan(position, gi_probes.data[i].bounds))))) { - position /= gi_probes.data[i].bounds; + if (all(bvec2(all(greaterThanEqual(position, vec3(0.0))), all(lessThan(position, voxel_gi_instances.data[i].bounds))))) { + position /= voxel_gi_instances.data[i].bounds; vec4 light = vec4(0.0); - for (uint j = 0; j < gi_probes.data[i].mipmaps; j++) { - vec4 slight = textureLod(sampler3D(gi_probe_textures[i], linear_sampler_with_mipmaps), position, float(j)); + for (uint j = 0; j < voxel_gi_instances.data[i].mipmaps; j++) { + vec4 slight = textureLod(sampler3D(voxel_gi_textures[i], linear_sampler_with_mipmaps), position, float(j)); float a = (1.0 - light.a); light += a * slight; } - light.rgb *= gi_probes.data[i].dynamic_range * params.gi_inject; + light.rgb *= voxel_gi_instances.data[i].dynamic_range * params.gi_inject; total_light += light.rgb; } diff --git a/servers/rendering/renderer_rd/shaders/voxel_gi.glsl b/servers/rendering/renderer_rd/shaders/voxel_gi.glsl new file mode 100644 index 0000000000..49a493cdc7 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/voxel_gi.glsl @@ -0,0 +1,779 @@ +#[compute] + +#version 450 + +#VERSION_DEFINES + +#ifdef MODE_DYNAMIC +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; +#else +layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; +#endif + +#ifndef MODE_DYNAMIC + +#define NO_CHILDREN 0xFFFFFFFF +#define GREY_VEC vec3(0.33333, 0.33333, 0.33333) + +struct CellChildren { + uint children[8]; +}; + +layout(set = 0, binding = 1, std430) buffer CellChildrenBuffer { + CellChildren data[]; +} +cell_children; + +struct CellData { + uint position; // xyz 10 bits + uint albedo; //rgb albedo + uint emission; //rgb normalized with e as multiplier + uint normal; //RGB normal encoded +}; + +layout(set = 0, binding = 2, std430) buffer CellDataBuffer { + CellData data[]; +} +cell_data; + +#endif // MODE DYNAMIC + +#define LIGHT_TYPE_DIRECTIONAL 0 +#define LIGHT_TYPE_OMNI 1 +#define LIGHT_TYPE_SPOT 2 + +#if defined(MODE_COMPUTE_LIGHT) || defined(MODE_DYNAMIC_LIGHTING) + +struct Light { + uint type; + float energy; + float radius; + float attenuation; + + vec3 color; + float cos_spot_angle; + + vec3 position; + float inv_spot_attenuation; + + vec3 direction; + bool has_shadow; +}; + +layout(set = 0, binding = 3, std140) uniform Lights { + Light data[MAX_LIGHTS]; +} +lights; + +#endif // MODE COMPUTE LIGHT + +#ifdef MODE_SECOND_BOUNCE + +layout(set = 0, binding = 5) uniform texture3D color_texture; + +#ifdef MODE_ANISOTROPIC +layout(set = 0, binding = 7) uniform texture3D aniso_pos_texture; +layout(set = 0, binding = 8) uniform texture3D aniso_neg_texture; +#endif // MODE ANISOTROPIC + +#endif // MODE_SECOND_BOUNCE + +#ifndef MODE_DYNAMIC + +layout(push_constant, binding = 0, std430) uniform Params { + ivec3 limits; + uint stack_size; + + float emission_scale; + float propagation; + float dynamic_range; + + uint light_count; + uint cell_offset; + uint cell_count; + float aniso_strength; + uint pad; +} +params; + +layout(set = 0, binding = 4, std430) buffer Outputs { + vec4 data[]; +} +outputs; + +#endif // MODE DYNAMIC + +layout(set = 0, binding = 9) uniform texture3D texture_sdf; +layout(set = 0, binding = 10) uniform sampler texture_sampler; + +#ifdef MODE_WRITE_TEXTURE + +layout(rgba8, set = 0, binding = 5) uniform restrict writeonly image3D color_tex; + +#ifdef MODE_ANISOTROPIC + +layout(r16ui, set = 0, binding = 6) uniform restrict writeonly uimage3D aniso_pos_tex; +layout(r16ui, set = 0, binding = 7) uniform restrict writeonly uimage3D aniso_neg_tex; + +#endif + +#endif + +#ifdef MODE_DYNAMIC + +layout(push_constant, binding = 0, std430) uniform Params { + ivec3 limits; + uint light_count; //when not lighting + ivec3 x_dir; + float z_base; + ivec3 y_dir; + float z_sign; + ivec3 z_dir; + float pos_multiplier; + ivec2 rect_pos; + ivec2 rect_size; + ivec2 prev_rect_ofs; + ivec2 prev_rect_size; + bool flip_x; + bool flip_y; + float dynamic_range; + bool on_mipmap; + float propagation; + float pad[3]; +} +params; + +#ifdef MODE_DYNAMIC_LIGHTING + +layout(rgba8, set = 0, binding = 5) uniform restrict readonly image2D source_albedo; +layout(rgba8, set = 0, binding = 6) uniform restrict readonly image2D source_normal; +layout(rgba8, set = 0, binding = 7) uniform restrict readonly image2D source_orm; +//layout (set=0,binding=8) uniform texture2D source_depth; +layout(rgba16f, set = 0, binding = 11) uniform restrict image2D emission; +layout(r32f, set = 0, binding = 12) uniform restrict image2D depth; + +#endif + +#ifdef MODE_DYNAMIC_SHRINK + +layout(rgba16f, set = 0, binding = 5) uniform restrict readonly image2D source_light; +layout(r32f, set = 0, binding = 6) uniform restrict readonly image2D source_depth; + +#ifdef MODE_DYNAMIC_SHRINK_WRITE + +layout(rgba16f, set = 0, binding = 7) uniform restrict writeonly image2D light; +layout(r32f, set = 0, binding = 8) uniform restrict writeonly image2D depth; + +#endif // MODE_DYNAMIC_SHRINK_WRITE + +#ifdef MODE_DYNAMIC_SHRINK_PLOT + +layout(rgba8, set = 0, binding = 11) uniform restrict image3D color_texture; + +#ifdef MODE_ANISOTROPIC + +layout(r16ui, set = 0, binding = 12) uniform restrict writeonly uimage3D aniso_pos_texture; +layout(r16ui, set = 0, binding = 13) uniform restrict writeonly uimage3D aniso_neg_texture; + +#endif // MODE ANISOTROPIC + +#endif //MODE_DYNAMIC_SHRINK_PLOT + +#endif // MODE_DYNAMIC_SHRINK + +//layout (rgba8,set=0,binding=5) uniform restrict writeonly image3D color_tex; + +#endif // MODE DYNAMIC + +#if defined(MODE_COMPUTE_LIGHT) || defined(MODE_DYNAMIC_LIGHTING) + +float raymarch(float distance, float distance_adv, vec3 from, vec3 direction) { + vec3 cell_size = 1.0 / vec3(params.limits); + float occlusion = 1.0; + while (distance > 0.5) { //use this to avoid precision errors + float advance = texture(sampler3D(texture_sdf, texture_sampler), from * cell_size).r * 255.0 - 1.0; + if (advance < 0.0) { + occlusion = 0.0; + break; + } + + occlusion = min(advance, occlusion); + + advance = max(distance_adv, advance - mod(advance, distance_adv)); //should always advance in multiples of distance_adv + + from += direction * advance; + distance -= advance; + } + + return occlusion; //max(0.0,distance); +} + +float get_omni_attenuation(float distance, float inv_range, float decay) { + float nd = distance * inv_range; + nd *= nd; + nd *= nd; // nd^4 + nd = max(1.0 - nd, 0.0); + nd *= nd; // nd^2 + return nd * pow(max(distance, 0.0001), -decay); +} + +bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3 light_pos) { + if (lights.data[light].type == LIGHT_TYPE_DIRECTIONAL) { + light_pos = pos - lights.data[light].direction * length(vec3(params.limits)); + attenuation = 1.0; + + } else { + light_pos = lights.data[light].position; + float distance = length(pos - light_pos); + if (distance >= lights.data[light].radius) { + return false; + } + + attenuation = get_omni_attenuation(distance, 1.0 / lights.data[light].radius, lights.data[light].attenuation); + + if (lights.data[light].type == LIGHT_TYPE_SPOT) { + vec3 rel = normalize(pos - light_pos); + float cos_spot_angle = lights.data[light].cos_spot_angle; + float cos_angle = dot(rel, lights.data[light].direction); + if (cos_angle < cos_spot_angle) { + return false; + } + + float scos = max(cos_angle, cos_spot_angle); + float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cos_spot_angle)); + attenuation *= 1.0 - pow(spot_rim, lights.data[light].inv_spot_attenuation); + } + } + + return true; +} + +float get_normal_advance(vec3 p_normal) { + vec3 normal = p_normal; + vec3 unorm = abs(normal); + + if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) { + // x code + unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0); + } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) { + // y code + unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0); + } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) { + // z code + unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0); + } else { + // oh-no we messed up code + // has to be + unorm = vec3(1.0, 0.0, 0.0); + } + + return 1.0 / dot(normal, unorm); +} + +void clip_segment(vec4 plane, vec3 begin, inout vec3 end) { + vec3 segment = begin - end; + float den = dot(plane.xyz, segment); + + //printf("den is %i\n",den); + if (den < 0.0001) { + return; + } + + float dist = (dot(plane.xyz, begin) - plane.w) / den; + + if (dist < 0.0001 || dist > 1.0001) { + return; + } + + end = begin + segment * -dist; +} + +bool compute_light_at_pos(uint index, vec3 pos, vec3 normal, inout vec3 light, inout vec3 light_dir) { + float attenuation; + vec3 light_pos; + + if (!compute_light_vector(index, pos, attenuation, light_pos)) { + return false; + } + + light_dir = normalize(pos - light_pos); + + if (attenuation < 0.01 || (length(normal) > 0.2 && dot(normal, light_dir) >= 0)) { + return false; //not facing the light, or attenuation is near zero + } + + if (lights.data[index].has_shadow) { + float distance_adv = get_normal_advance(light_dir); + + vec3 to = pos; + if (length(normal) > 0.2) { + to += normal * distance_adv * 0.51; + } else { + to -= sign(light_dir) * 0.45; //go near the edge towards the light direction to avoid self occlusion + } + + //clip + clip_segment(mix(vec4(-1.0, 0.0, 0.0, 0.0), vec4(1.0, 0.0, 0.0, float(params.limits.x - 1)), bvec4(light_dir.x < 0.0)), to, light_pos); + clip_segment(mix(vec4(0.0, -1.0, 0.0, 0.0), vec4(0.0, 1.0, 0.0, float(params.limits.y - 1)), bvec4(light_dir.y < 0.0)), to, light_pos); + clip_segment(mix(vec4(0.0, 0.0, -1.0, 0.0), vec4(0.0, 0.0, 1.0, float(params.limits.z - 1)), bvec4(light_dir.z < 0.0)), to, light_pos); + + float distance = length(to - light_pos); + if (distance < 0.1) { + return false; // hit + } + + distance += distance_adv - mod(distance, distance_adv); //make it reach the center of the box always + light_pos = to - light_dir * distance; + + //from -= sign(light_dir)*0.45; //go near the edge towards the light direction to avoid self occlusion + + /*float dist = raymarch(distance,distance_adv,light_pos,light_dir); + + if (dist > distance_adv) { + return false; + } + + attenuation *= 1.0 - smoothstep(0.1*distance_adv,distance_adv,dist); + */ + + float occlusion = raymarch(distance, distance_adv, light_pos, light_dir); + + if (occlusion == 0.0) { + return false; + } + + attenuation *= occlusion; //1.0 - smoothstep(0.1*distance_adv,distance_adv,dist); + } + + light = lights.data[index].color * attenuation * lights.data[index].energy; + return true; +} + +#endif // MODE COMPUTE LIGHT + +void main() { +#ifndef MODE_DYNAMIC + + uint cell_index = gl_GlobalInvocationID.x; + if (cell_index >= params.cell_count) { + return; + } + cell_index += params.cell_offset; + + uvec3 posu = uvec3(cell_data.data[cell_index].position & 0x7FF, (cell_data.data[cell_index].position >> 11) & 0x3FF, cell_data.data[cell_index].position >> 21); + vec4 albedo = unpackUnorm4x8(cell_data.data[cell_index].albedo); + +#endif + + /////////////////COMPUTE LIGHT/////////////////////////////// + +#ifdef MODE_COMPUTE_LIGHT + + vec3 pos = vec3(posu) + vec3(0.5); + + vec3 emission = vec3(uvec3(cell_data.data[cell_index].emission & 0x1ff, (cell_data.data[cell_index].emission >> 9) & 0x1ff, (cell_data.data[cell_index].emission >> 18) & 0x1ff)) * pow(2.0, float(cell_data.data[cell_index].emission >> 27) - 15.0 - 9.0); + vec3 normal = unpackSnorm4x8(cell_data.data[cell_index].normal).xyz; + +#ifdef MODE_ANISOTROPIC + vec3 accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); + const vec3 accum_dirs[6] = vec3[](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0)); +#else + vec3 accum = vec3(0.0); +#endif + + for (uint i = 0; i < params.light_count; i++) { + vec3 light; + vec3 light_dir; + if (!compute_light_at_pos(i, pos, normal.xyz, light, light_dir)) { + continue; + } + + light *= albedo.rgb; + +#ifdef MODE_ANISOTROPIC + for (uint j = 0; j < 6; j++) { + accum[j] += max(0.0, dot(accum_dirs[j], -light_dir)) * light; + } +#else + if (length(normal) > 0.2) { + accum += max(0.0, dot(normal, -light_dir)) * light; + } else { + //all directions + accum += light; + } +#endif + } + +#ifdef MODE_ANISOTROPIC + + for (uint i = 0; i < 6; i++) { + vec3 light = accum[i]; + if (length(normal) > 0.2) { + light += max(0.0, dot(accum_dirs[i], -normal)) * emission; + } else { + light += emission; + } + + outputs.data[cell_index * 6 + i] = vec4(light, 0.0); + } + +#else + outputs.data[cell_index] = vec4(accum + emission, 0.0); + +#endif + +#endif //MODE_COMPUTE_LIGHT + + /////////////////SECOND BOUNCE/////////////////////////////// + +#ifdef MODE_SECOND_BOUNCE + vec3 pos = vec3(posu) + vec3(0.5); + ivec3 ipos = ivec3(posu); + vec4 normal = unpackSnorm4x8(cell_data.data[cell_index].normal); + +#ifdef MODE_ANISOTROPIC + vec3 accum[6]; + const vec3 accum_dirs[6] = vec3[](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0)); + + /*vec3 src_color = texelFetch(sampler3D(color_texture,texture_sampler),ipos,0).rgb * params.dynamic_range; + vec3 src_aniso_pos = texelFetch(sampler3D(aniso_pos_texture,texture_sampler),ipos,0).rgb; + vec3 src_anisp_neg = texelFetch(sampler3D(anisp_neg_texture,texture_sampler),ipos,0).rgb; + accum[0]=src_col * src_aniso_pos.x; + accum[1]=src_col * src_aniso_neg.x; + accum[2]=src_col * src_aniso_pos.y; + accum[3]=src_col * src_aniso_neg.y; + accum[4]=src_col * src_aniso_pos.z; + accum[5]=src_col * src_aniso_neg.z;*/ + + accum[0] = outputs.data[cell_index * 6 + 0].rgb; + accum[1] = outputs.data[cell_index * 6 + 1].rgb; + accum[2] = outputs.data[cell_index * 6 + 2].rgb; + accum[3] = outputs.data[cell_index * 6 + 3].rgb; + accum[4] = outputs.data[cell_index * 6 + 4].rgb; + accum[5] = outputs.data[cell_index * 6 + 5].rgb; + +#else + vec3 accum = outputs.data[cell_index].rgb; + +#endif + + if (length(normal.xyz) > 0.2) { + vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); + vec3 tangent = normalize(cross(v0, normal.xyz)); + vec3 bitangent = normalize(cross(tangent, normal.xyz)); + mat3 normal_mat = mat3(tangent, bitangent, normal.xyz); + +#define MAX_CONE_DIRS 6 + + vec3 cone_dirs[MAX_CONE_DIRS] = vec3[]( + vec3(0.0, 0.0, 1.0), + vec3(0.866025, 0.0, 0.5), + vec3(0.267617, 0.823639, 0.5), + vec3(-0.700629, 0.509037, 0.5), + vec3(-0.700629, -0.509037, 0.5), + vec3(0.267617, -0.823639, 0.5)); + + float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15); + float tan_half_angle = 0.577; + + for (int i = 0; i < MAX_CONE_DIRS; i++) { + vec3 direction = normal_mat * cone_dirs[i]; + vec4 color = vec4(0.0); + { + float dist = 1.5; + float max_distance = length(vec3(params.limits)); + vec3 cell_size = 1.0 / vec3(params.limits); + +#ifdef MODE_ANISOTROPIC + vec3 aniso_normal = mix(direction, normal.xyz, params.aniso_strength); +#endif + while (dist < max_distance && color.a < 0.95) { + float diameter = max(1.0, 2.0 * tan_half_angle * dist); + vec3 uvw_pos = (pos + dist * direction) * cell_size; + float half_diameter = diameter * 0.5; + //check if outside, then break + //if ( any(greaterThan(abs(uvw_pos - 0.5),vec3(0.5f + half_diameter * cell_size)) ) ) { + // break; + //} + + float log2_diameter = log2(diameter); + vec4 scolor = textureLod(sampler3D(color_texture, texture_sampler), uvw_pos, log2_diameter); +#ifdef MODE_ANISOTROPIC + + vec3 aniso_neg = textureLod(sampler3D(aniso_neg_texture, texture_sampler), uvw_pos, log2_diameter).rgb; + vec3 aniso_pos = textureLod(sampler3D(aniso_pos_texture, texture_sampler), uvw_pos, log2_diameter).rgb; + + scolor.rgb *= dot(max(vec3(0.0), (aniso_normal * aniso_pos)), vec3(1.0)) + dot(max(vec3(0.0), (-aniso_normal * aniso_neg)), vec3(1.0)); +#endif + float a = (1.0 - color.a); + color += a * scolor; + dist += half_diameter; + } + } + color *= cone_weights[i] * vec4(albedo.rgb, 1.0) * params.dynamic_range; //restore range +#ifdef MODE_ANISOTROPIC + for (uint j = 0; j < 6; j++) { + accum[j] += max(0.0, dot(accum_dirs[j], direction)) * color.rgb; + } +#else + accum += color.rgb; +#endif + } + } + +#ifdef MODE_ANISOTROPIC + + outputs.data[cell_index * 6 + 0] = vec4(accum[0], 0.0); + outputs.data[cell_index * 6 + 1] = vec4(accum[1], 0.0); + outputs.data[cell_index * 6 + 2] = vec4(accum[2], 0.0); + outputs.data[cell_index * 6 + 3] = vec4(accum[3], 0.0); + outputs.data[cell_index * 6 + 4] = vec4(accum[4], 0.0); + outputs.data[cell_index * 6 + 5] = vec4(accum[5], 0.0); +#else + outputs.data[cell_index] = vec4(accum, 0.0); + +#endif + +#endif // MODE_SECOND_BOUNCE + + /////////////////UPDATE MIPMAPS/////////////////////////////// + +#ifdef MODE_UPDATE_MIPMAPS + + { +#ifdef MODE_ANISOTROPIC + vec3 light_accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); +#else + vec3 light_accum = vec3(0.0); +#endif + float count = 0.0; + for (uint i = 0; i < 8; i++) { + uint child_index = cell_children.data[cell_index].children[i]; + if (child_index == NO_CHILDREN) { + continue; + } +#ifdef MODE_ANISOTROPIC + light_accum[0] += outputs.data[child_index * 6 + 0].rgb; + light_accum[1] += outputs.data[child_index * 6 + 1].rgb; + light_accum[2] += outputs.data[child_index * 6 + 2].rgb; + light_accum[3] += outputs.data[child_index * 6 + 3].rgb; + light_accum[4] += outputs.data[child_index * 6 + 4].rgb; + light_accum[5] += outputs.data[child_index * 6 + 5].rgb; + +#else + light_accum += outputs.data[child_index].rgb; + +#endif + + count += 1.0; + } + + float divisor = mix(8.0, count, params.propagation); +#ifdef MODE_ANISOTROPIC + outputs.data[cell_index * 6 + 0] = vec4(light_accum[0] / divisor, 0.0); + outputs.data[cell_index * 6 + 1] = vec4(light_accum[1] / divisor, 0.0); + outputs.data[cell_index * 6 + 2] = vec4(light_accum[2] / divisor, 0.0); + outputs.data[cell_index * 6 + 3] = vec4(light_accum[3] / divisor, 0.0); + outputs.data[cell_index * 6 + 4] = vec4(light_accum[4] / divisor, 0.0); + outputs.data[cell_index * 6 + 5] = vec4(light_accum[5] / divisor, 0.0); + +#else + outputs.data[cell_index] = vec4(light_accum / divisor, 0.0); +#endif + } +#endif + + ///////////////////WRITE TEXTURE///////////////////////////// + +#ifdef MODE_WRITE_TEXTURE + { +#ifdef MODE_ANISOTROPIC + vec3 accum_total = vec3(0.0); + accum_total += outputs.data[cell_index * 6 + 0].rgb; + accum_total += outputs.data[cell_index * 6 + 1].rgb; + accum_total += outputs.data[cell_index * 6 + 2].rgb; + accum_total += outputs.data[cell_index * 6 + 3].rgb; + accum_total += outputs.data[cell_index * 6 + 4].rgb; + accum_total += outputs.data[cell_index * 6 + 5].rgb; + + float accum_total_energy = max(dot(accum_total, GREY_VEC), 0.00001); + vec3 iso_positive = vec3(dot(outputs.data[cell_index * 6 + 0].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 2].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 4].rgb, GREY_VEC)) / vec3(accum_total_energy); + vec3 iso_negative = vec3(dot(outputs.data[cell_index * 6 + 1].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 3].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 5].rgb, GREY_VEC)) / vec3(accum_total_energy); + + { + uint aniso_pos = uint(clamp(iso_positive.b * 31.0, 0.0, 31.0)); + aniso_pos |= uint(clamp(iso_positive.g * 63.0, 0.0, 63.0)) << 5; + aniso_pos |= uint(clamp(iso_positive.r * 31.0, 0.0, 31.0)) << 11; + imageStore(aniso_pos_tex, ivec3(posu), uvec4(aniso_pos)); + } + + { + uint aniso_neg = uint(clamp(iso_negative.b * 31.0, 0.0, 31.0)); + aniso_neg |= uint(clamp(iso_negative.g * 63.0, 0.0, 63.0)) << 5; + aniso_neg |= uint(clamp(iso_negative.r * 31.0, 0.0, 31.0)) << 11; + imageStore(aniso_neg_tex, ivec3(posu), uvec4(aniso_neg)); + } + + imageStore(color_tex, ivec3(posu), vec4(accum_total / params.dynamic_range, albedo.a)); + +#else + + imageStore(color_tex, ivec3(posu), vec4(outputs.data[cell_index].rgb / params.dynamic_range, albedo.a)); + +#endif + } +#endif + + ///////////////////DYNAMIC LIGHTING///////////////////////////// + +#ifdef MODE_DYNAMIC + + ivec2 pos_xy = ivec2(gl_GlobalInvocationID.xy); + if (any(greaterThanEqual(pos_xy, params.rect_size))) { + return; //out of bounds + } + + ivec2 uv_xy = pos_xy; + if (params.flip_x) { + uv_xy.x = params.rect_size.x - pos_xy.x - 1; + } + if (params.flip_y) { + uv_xy.y = params.rect_size.y - pos_xy.y - 1; + } + +#ifdef MODE_DYNAMIC_LIGHTING + + { + float z = params.z_base + imageLoad(depth, uv_xy).x * params.z_sign; + + ivec3 pos = params.x_dir * (params.rect_pos.x + pos_xy.x) + params.y_dir * (params.rect_pos.y + pos_xy.y) + abs(params.z_dir) * int(z); + + vec3 normal = imageLoad(source_normal, uv_xy).xyz * 2.0 - 1.0; + normal = vec3(params.x_dir) * normal.x * mix(1.0, -1.0, params.flip_x) + vec3(params.y_dir) * normal.y * mix(1.0, -1.0, params.flip_y) - vec3(params.z_dir) * normal.z; + + vec4 albedo = imageLoad(source_albedo, uv_xy); + + //determine the position in space + + vec3 accum = vec3(0.0); + for (uint i = 0; i < params.light_count; i++) { + vec3 light; + vec3 light_dir; + if (!compute_light_at_pos(i, vec3(pos) * params.pos_multiplier, normal, light, light_dir)) { + continue; + } + + light *= albedo.rgb; + + accum += max(0.0, dot(normal, -light_dir)) * light; + } + + accum += imageLoad(emission, uv_xy).xyz; + + imageStore(emission, uv_xy, vec4(accum, albedo.a)); + imageStore(depth, uv_xy, vec4(z)); + } + +#endif // MODE DYNAMIC LIGHTING + +#ifdef MODE_DYNAMIC_SHRINK + + { + vec4 accum = vec4(0.0); + float accum_z = 0.0; + float count = 0.0; + + for (int i = 0; i < 4; i++) { + ivec2 ofs = pos_xy * 2 + ivec2(i & 1, i >> 1) - params.prev_rect_ofs; + if (any(lessThan(ofs, ivec2(0))) || any(greaterThanEqual(ofs, params.prev_rect_size))) { + continue; + } + if (params.flip_x) { + ofs.x = params.prev_rect_size.x - ofs.x - 1; + } + if (params.flip_y) { + ofs.y = params.prev_rect_size.y - ofs.y - 1; + } + + vec4 light = imageLoad(source_light, ofs); + if (light.a == 0.0) { //ignore empty + continue; + } + accum += light; + float z = imageLoad(source_depth, ofs).x; + accum_z += z * 0.5; //shrink half too + count += 1.0; + } + + if (params.on_mipmap) { + accum.rgb /= mix(8.0, count, params.propagation); + accum.a /= 8.0; + } else { + accum /= 4.0; + } + + if (count == 0.0) { + accum_z = 0.0; //avoid nan + } else { + accum_z /= count; + } + +#ifdef MODE_DYNAMIC_SHRINK_WRITE + + imageStore(light, uv_xy, accum); + imageStore(depth, uv_xy, vec4(accum_z)); +#endif + +#ifdef MODE_DYNAMIC_SHRINK_PLOT + + if (accum.a < 0.001) { + return; //do not blit if alpha is too low + } + + ivec3 pos = params.x_dir * (params.rect_pos.x + pos_xy.x) + params.y_dir * (params.rect_pos.y + pos_xy.y) + abs(params.z_dir) * int(accum_z); + + float z_frac = fract(accum_z); + + for (int i = 0; i < 2; i++) { + ivec3 pos3d = pos + abs(params.z_dir) * i; + if (any(lessThan(pos3d, ivec3(0))) || any(greaterThanEqual(pos3d, params.limits))) { + //skip if offlimits + continue; + } + vec4 color_blit = accum * (i == 0 ? 1.0 - z_frac : z_frac); + vec4 color = imageLoad(color_texture, pos3d); + color.rgb *= params.dynamic_range; + +#if 0 + color.rgb = mix(color.rgb,color_blit.rgb,color_blit.a); + color.a+=color_blit.a; +#else + + float sa = 1.0 - color_blit.a; + vec4 result; + result.a = color.a * sa + color_blit.a; + if (result.a == 0.0) { + result = vec4(0.0); + } else { + result.rgb = (color.rgb * color.a * sa + color_blit.rgb * color_blit.a) / result.a; + color = result; + } + +#endif + color.rgb /= params.dynamic_range; + imageStore(color_texture, pos3d, color); + //imageStore(color_texture,pos3d,vec4(1,1,1,1)); + +#ifdef MODE_ANISOTROPIC + //do not care about anisotropy for dynamic objects, just store full lit in all directions + imageStore(aniso_pos_texture, pos3d, uvec4(0xFFFF)); + imageStore(aniso_neg_texture, pos3d, uvec4(0xFFFF)); + +#endif // ANISOTROPIC + } +#endif // MODE_DYNAMIC_SHRINK_PLOT + } +#endif + +#endif // MODE DYNAMIC +} diff --git a/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl b/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl new file mode 100644 index 0000000000..7d4d72967a --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl @@ -0,0 +1,229 @@ +#[vertex] + +#version 450 + +#VERSION_DEFINES + +struct CellData { + uint position; // xyz 10 bits + uint albedo; //rgb albedo + uint emission; //rgb normalized with e as multiplier + uint normal; //RGB normal encoded +}; + +layout(set = 0, binding = 1, std140) buffer CellDataBuffer { + CellData data[]; +} +cell_data; + +layout(set = 0, binding = 2) uniform texture3D color_tex; + +layout(set = 0, binding = 3) uniform sampler tex_sampler; + +#ifdef USE_ANISOTROPY +layout(set = 0, binding = 4) uniform texture3D aniso_pos_tex; +layout(set = 0, binding = 5) uniform texture3D aniso_neg_tex; +#endif + +layout(push_constant, binding = 0, std430) uniform Params { + mat4 projection; + uint cell_offset; + float dynamic_range; + float alpha; + uint level; + ivec3 bounds; + uint pad; +} +params; + +layout(location = 0) out vec4 color_interp; + +void main() { + const vec3 cube_triangles[36] = vec3[]( + vec3(-1.0f, -1.0f, -1.0f), + vec3(-1.0f, -1.0f, 1.0f), + vec3(-1.0f, 1.0f, 1.0f), + vec3(1.0f, 1.0f, -1.0f), + vec3(-1.0f, -1.0f, -1.0f), + vec3(-1.0f, 1.0f, -1.0f), + vec3(1.0f, -1.0f, 1.0f), + vec3(-1.0f, -1.0f, -1.0f), + vec3(1.0f, -1.0f, -1.0f), + vec3(1.0f, 1.0f, -1.0f), + vec3(1.0f, -1.0f, -1.0f), + vec3(-1.0f, -1.0f, -1.0f), + vec3(-1.0f, -1.0f, -1.0f), + vec3(-1.0f, 1.0f, 1.0f), + vec3(-1.0f, 1.0f, -1.0f), + vec3(1.0f, -1.0f, 1.0f), + vec3(-1.0f, -1.0f, 1.0f), + vec3(-1.0f, -1.0f, -1.0f), + vec3(-1.0f, 1.0f, 1.0f), + vec3(-1.0f, -1.0f, 1.0f), + vec3(1.0f, -1.0f, 1.0f), + vec3(1.0f, 1.0f, 1.0f), + vec3(1.0f, -1.0f, -1.0f), + vec3(1.0f, 1.0f, -1.0f), + vec3(1.0f, -1.0f, -1.0f), + vec3(1.0f, 1.0f, 1.0f), + vec3(1.0f, -1.0f, 1.0f), + vec3(1.0f, 1.0f, 1.0f), + vec3(1.0f, 1.0f, -1.0f), + vec3(-1.0f, 1.0f, -1.0f), + vec3(1.0f, 1.0f, 1.0f), + vec3(-1.0f, 1.0f, -1.0f), + vec3(-1.0f, 1.0f, 1.0f), + vec3(1.0f, 1.0f, 1.0f), + vec3(-1.0f, 1.0f, 1.0f), + vec3(1.0f, -1.0f, 1.0f)); + + vec3 vertex = cube_triangles[gl_VertexIndex] * 0.5 + 0.5; +#ifdef MODE_DEBUG_LIGHT_FULL + uvec3 posu = uvec3(gl_InstanceIndex % params.bounds.x, (gl_InstanceIndex / params.bounds.x) % params.bounds.y, gl_InstanceIndex / (params.bounds.y * params.bounds.x)); +#else + uint cell_index = gl_InstanceIndex + params.cell_offset; + + uvec3 posu = uvec3(cell_data.data[cell_index].position & 0x7FF, (cell_data.data[cell_index].position >> 11) & 0x3FF, cell_data.data[cell_index].position >> 21); +#endif + +#ifdef MODE_DEBUG_EMISSION + color_interp.xyz = vec3(uvec3(cell_data.data[cell_index].emission & 0x1ff, (cell_data.data[cell_index].emission >> 9) & 0x1ff, (cell_data.data[cell_index].emission >> 18) & 0x1ff)) * pow(2.0, float(cell_data.data[cell_index].emission >> 27) - 15.0 - 9.0); +#endif + +#ifdef MODE_DEBUG_COLOR + color_interp.xyz = unpackUnorm4x8(cell_data.data[cell_index].albedo).xyz; +#endif + +#ifdef MODE_DEBUG_LIGHT + +#ifdef USE_ANISOTROPY + +#define POS_X 0 +#define POS_Y 1 +#define POS_Z 2 +#define NEG_X 3 +#define NEG_Y 4 +#define NEG_Z 5 + + const uint triangle_aniso[12] = uint[]( + NEG_X, + NEG_Z, + NEG_Y, + NEG_Z, + NEG_X, + NEG_Y, + POS_Z, + POS_X, + POS_X, + POS_Y, + POS_Y, + POS_Z); + + color_interp.xyz = texelFetch(sampler3D(color_tex, tex_sampler), ivec3(posu), int(params.level)).xyz * params.dynamic_range; + vec3 aniso_pos = texelFetch(sampler3D(aniso_pos_tex, tex_sampler), ivec3(posu), int(params.level)).xyz; + vec3 aniso_neg = texelFetch(sampler3D(aniso_neg_tex, tex_sampler), ivec3(posu), int(params.level)).xyz; + uint side = triangle_aniso[gl_VertexIndex / 3]; + + float strength = 0.0; + switch (side) { + case POS_X: + strength = aniso_pos.x; + break; + case POS_Y: + strength = aniso_pos.y; + break; + case POS_Z: + strength = aniso_pos.z; + break; + case NEG_X: + strength = aniso_neg.x; + break; + case NEG_Y: + strength = aniso_neg.y; + break; + case NEG_Z: + strength = aniso_neg.z; + break; + } + + color_interp.xyz *= strength; + +#else + color_interp = texelFetch(sampler3D(color_tex, tex_sampler), ivec3(posu), int(params.level)); + color_interp.xyz *params.dynamic_range; + +#endif + +#endif + float scale = (1 << params.level); + + gl_Position = params.projection * vec4((vec3(posu) + vertex) * scale, 1.0); + +#ifdef MODE_DEBUG_LIGHT_FULL + if (color_interp.a == 0.0) { + gl_Position = vec4(0.0); //force clip and not draw + } +#else + color_interp.a = params.alpha; +#endif +} + +#[fragment] + +#version 450 + +#VERSION_DEFINES + +layout(location = 0) in vec4 color_interp; +layout(location = 0) out vec4 frag_color; + +void main() { + frag_color = color_interp; + +#ifdef MODE_DEBUG_LIGHT_FULL + + //there really is no alpha, so use dither + + int x = int(gl_FragCoord.x) % 4; + int y = int(gl_FragCoord.y) % 4; + int index = x + y * 4; + float limit = 0.0; + if (x < 8) { + if (index == 0) + limit = 0.0625; + if (index == 1) + limit = 0.5625; + if (index == 2) + limit = 0.1875; + if (index == 3) + limit = 0.6875; + if (index == 4) + limit = 0.8125; + if (index == 5) + limit = 0.3125; + if (index == 6) + limit = 0.9375; + if (index == 7) + limit = 0.4375; + if (index == 8) + limit = 0.25; + if (index == 9) + limit = 0.75; + if (index == 10) + limit = 0.125; + if (index == 11) + limit = 0.625; + if (index == 12) + limit = 1.0; + if (index == 13) + limit = 0.5; + if (index == 14) + limit = 0.875; + if (index == 15) + limit = 0.375; + } + if (frag_color.a < limit) { + discard; + } +#endif +} diff --git a/servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl b/servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl new file mode 100644 index 0000000000..e20b3f680d --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl @@ -0,0 +1,181 @@ +#[compute] + +#version 450 + +#VERSION_DEFINES + +layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in; + +#define MAX_DISTANCE 100000 + +#define NO_CHILDREN 0xFFFFFFFF +#define GREY_VEC vec3(0.33333, 0.33333, 0.33333) + +struct CellChildren { + uint children[8]; +}; + +layout(set = 0, binding = 1, std430) buffer CellChildrenBuffer { + CellChildren data[]; +} +cell_children; + +struct CellData { + uint position; // xyz 10 bits + uint albedo; //rgb albedo + uint emission; //rgb normalized with e as multiplier + uint normal; //RGB normal encoded +}; + +layout(set = 0, binding = 2, std430) buffer CellDataBuffer { + CellData data[]; +} +cell_data; + +layout(r8ui, set = 0, binding = 3) uniform restrict writeonly uimage3D sdf_tex; + +layout(push_constant, binding = 0, std430) uniform Params { + uint offset; + uint end; + uint pad0; + uint pad1; +} +params; + +void main() { + vec3 pos = vec3(gl_GlobalInvocationID); + float closest_dist = 100000.0; + + for (uint i = params.offset; i < params.end; i++) { + vec3 posu = vec3(uvec3(cell_data.data[i].position & 0x7FF, (cell_data.data[i].position >> 11) & 0x3FF, cell_data.data[i].position >> 21)); + float dist = length(pos - posu); + if (dist < closest_dist) { + closest_dist = dist; + } + } + + uint dist_8; + + if (closest_dist < 0.0001) { // same cell + dist_8 = 0; //equals to -1 + } else { + dist_8 = clamp(uint(closest_dist), 0, 254) + 1; //conservative, 0 is 1, so <1 is considered solid + } + + imageStore(sdf_tex, ivec3(gl_GlobalInvocationID), uvec4(dist_8)); + //imageStore(sdf_tex,pos,uvec4(pos*2,0)); +} + +#if 0 +layout(push_constant, binding = 0, std430) uniform Params { + ivec3 limits; + uint stack_size; +} +params; + +float distance_to_aabb(ivec3 pos, ivec3 aabb_pos, ivec3 aabb_size) { + vec3 delta = vec3(max(ivec3(0), max(aabb_pos - pos, pos - (aabb_pos + aabb_size - ivec3(1))))); + return length(delta); +} + +void main() { + ivec3 pos = ivec3(gl_GlobalInvocationID); + + uint stack[10] = uint[](0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + uint stack_indices[10] = uint[](0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + ivec3 stack_positions[10] = ivec3[](ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0)); + + const uint cell_orders[8] = uint[]( + 0x11f58d1, + 0xe2e70a, + 0xd47463, + 0xbb829c, + 0x8d11f5, + 0x70ae2e, + 0x463d47, + 0x29cbb8); + + bool cell_found = false; + bool cell_found_exact = false; + ivec3 closest_cell_pos; + float closest_distance = MAX_DISTANCE; + int stack_pos = 0; + + while (true) { + uint index = stack_indices[stack_pos] >> 24; + + if (index == 8) { + //go up + if (stack_pos == 0) { + break; //done going through octree + } + stack_pos--; + continue; + } + + stack_indices[stack_pos] = (stack_indices[stack_pos] & ((1 << 24) - 1)) | ((index + 1) << 24); + + uint cell_index = (stack_indices[stack_pos] >> (index * 3)) & 0x7; + uint child_cell = cell_children.data[stack[stack_pos]].children[cell_index]; + + if (child_cell == NO_CHILDREN) { + continue; + } + + ivec3 child_cell_size = params.limits >> (stack_pos + 1); + ivec3 child_cell_pos = stack_positions[stack_pos]; + + child_cell_pos += mix(ivec3(0), child_cell_size, bvec3(uvec3(index & 1, index & 2, index & 4) != uvec3(0))); + + bool is_leaf = stack_pos == (params.stack_size - 2); + + if (child_cell_pos == pos && is_leaf) { + //we may actually end up in the exact cell. + //if this happens, just abort + cell_found_exact = true; + break; + } + + if (cell_found) { + //discard by distance + float distance = distance_to_aabb(pos, child_cell_pos, child_cell_size); + if (distance >= closest_distance) { + continue; //pointless, just test next child + } else if (is_leaf) { + //closer than what we have AND end of stack, save and continue + closest_cell_pos = child_cell_pos; + closest_distance = distance; + continue; + } + } else if (is_leaf) { + //first solid cell we find, save and continue + closest_distance = distance_to_aabb(pos, child_cell_pos, child_cell_size); + closest_cell_pos = child_cell_pos; + cell_found = true; + continue; + } + + bvec3 direction = greaterThan((pos - (child_cell_pos + (child_cell_size >> 1))), ivec3(0)); + uint cell_order = 0; + cell_order |= mix(0, 1, direction.x); + cell_order |= mix(0, 2, direction.y); + cell_order |= mix(0, 4, direction.z); + + stack[stack_pos + 1] = child_cell; + stack_indices[stack_pos + 1] = cell_orders[cell_order]; //start counting + stack_positions[stack_pos + 1] = child_cell_pos; + stack_pos++; //go up stack + } + + uint dist_8; + + if (cell_found_exact) { + dist_8 = 0; //equals to -1 + } else { + float closest_distance = length(vec3(pos - closest_cell_pos)); + dist_8 = clamp(uint(closest_distance), 0, 254) + 1; //conservative, 0 is 1, so <1 is considered solid + } + + imageStore(sdf_tex, pos, uvec4(dist_8)); +} +#endif diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h index 2acbc38fda..355c092dba 100644 --- a/servers/rendering/renderer_scene.h +++ b/servers/rendering/renderer_scene.h @@ -196,7 +196,7 @@ public: virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0; virtual TypedArray bake_render_uv2(RID p_base, const Vector &p_material_overrides, const Size2i &p_image_size) = 0; - virtual void gi_probe_set_quality(RS::GIProbeQuality) = 0; + virtual void voxel_gi_set_quality(RS::VoxelGIQuality) = 0; virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0; diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index ce3f736837..a001aea5f4 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -190,26 +190,26 @@ void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) { ((RendererSceneCull *)self)->_instance_queue_update(A, false, false); //need to update capture } - } else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_GI_PROBE) && B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { - InstanceGIProbeData *gi_probe = static_cast(B->base_data); + } else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_VOXEL_GI) && B->base_type == RS::INSTANCE_VOXEL_GI && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + InstanceVoxelGIData *voxel_gi = static_cast(B->base_data); InstanceGeometryData *geom = static_cast(A->base_data); - geom->gi_probes.insert(B); + geom->voxel_gi_instances.insert(B); if (A->dynamic_gi) { - gi_probe->dynamic_geometries.insert(A); + voxel_gi->dynamic_geometries.insert(A); } else { - gi_probe->geometries.insert(A); + voxel_gi->geometries.insert(A); } if (A->scenario && A->array_index >= 0) { InstanceData &idata = A->scenario->instance_data[A->array_index]; - idata.flags |= InstanceData::FLAG_GEOM_GI_PROBE_DIRTY; + idata.flags |= InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY; } - } else if (B->base_type == RS::INSTANCE_GI_PROBE && A->base_type == RS::INSTANCE_LIGHT) { - InstanceGIProbeData *gi_probe = static_cast(B->base_data); - gi_probe->lights.insert(A); + } else if (B->base_type == RS::INSTANCE_VOXEL_GI && A->base_type == RS::INSTANCE_LIGHT) { + InstanceVoxelGIData *voxel_gi = static_cast(B->base_data); + voxel_gi->lights.insert(A); } else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) { InstanceParticlesCollisionData *collision = static_cast(B->base_data); RSG::storage->particles_add_collision(A->base, collision->instance); @@ -281,25 +281,25 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) { ((RendererSceneCull *)self)->_instance_queue_update(A, false, false); //need to update capture } - } else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_GI_PROBE) && B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { - InstanceGIProbeData *gi_probe = static_cast(B->base_data); + } else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_VOXEL_GI) && B->base_type == RS::INSTANCE_VOXEL_GI && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + InstanceVoxelGIData *voxel_gi = static_cast(B->base_data); InstanceGeometryData *geom = static_cast(A->base_data); - geom->gi_probes.erase(B); + geom->voxel_gi_instances.erase(B); if (A->dynamic_gi) { - gi_probe->dynamic_geometries.erase(A); + voxel_gi->dynamic_geometries.erase(A); } else { - gi_probe->geometries.erase(A); + voxel_gi->geometries.erase(A); } if (A->scenario && A->array_index >= 0) { InstanceData &idata = A->scenario->instance_data[A->array_index]; - idata.flags |= InstanceData::FLAG_GEOM_GI_PROBE_DIRTY; + idata.flags |= InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY; } - } else if (B->base_type == RS::INSTANCE_GI_PROBE && A->base_type == RS::INSTANCE_LIGHT) { - InstanceGIProbeData *gi_probe = static_cast(B->base_data); - gi_probe->lights.erase(A); + } else if (B->base_type == RS::INSTANCE_VOXEL_GI && A->base_type == RS::INSTANCE_LIGHT) { + InstanceVoxelGIData *voxel_gi = static_cast(B->base_data); + voxel_gi->lights.erase(A); } else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) { InstanceParticlesCollisionData *collision = static_cast(B->base_data); RSG::storage->particles_remove_collision(A->base, collision->instance); @@ -494,23 +494,23 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { } scene_render->free(lightmap_data->instance); } break; - case RS::INSTANCE_GI_PROBE: { - InstanceGIProbeData *gi_probe = static_cast(instance->base_data); + case RS::INSTANCE_VOXEL_GI: { + InstanceVoxelGIData *voxel_gi = static_cast(instance->base_data); #ifdef DEBUG_ENABLED - if (gi_probe->geometries.size()) { - ERR_PRINT("BUG, indexing did not unpair geometries from GIProbe."); + if (voxel_gi->geometries.size()) { + ERR_PRINT("BUG, indexing did not unpair geometries from VoxelGI."); } #endif #ifdef DEBUG_ENABLED - if (gi_probe->lights.size()) { - ERR_PRINT("BUG, indexing did not unpair lights from GIProbe."); + if (voxel_gi->lights.size()) { + ERR_PRINT("BUG, indexing did not unpair lights from VoxelGI."); } #endif - if (gi_probe->update_element.in_list()) { - gi_probe_update_list.remove(&gi_probe->update_element); + if (voxel_gi->update_element.in_list()) { + voxel_gi_update_list.remove(&voxel_gi->update_element); } - scene_render->free(gi_probe->probe_instance); + scene_render->free(voxel_gi->probe_instance); } break; case RS::INSTANCE_OCCLUDER: { @@ -602,16 +602,16 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { instance->base_data = lightmap_data; lightmap_data->instance = scene_render->lightmap_instance_create(p_base); } break; - case RS::INSTANCE_GI_PROBE: { - InstanceGIProbeData *gi_probe = memnew(InstanceGIProbeData); - instance->base_data = gi_probe; - gi_probe->owner = instance; + case RS::INSTANCE_VOXEL_GI: { + InstanceVoxelGIData *voxel_gi = memnew(InstanceVoxelGIData); + instance->base_data = voxel_gi; + voxel_gi->owner = instance; - if (scenario && !gi_probe->update_element.in_list()) { - gi_probe_update_list.add(&gi_probe->update_element); + if (scenario && !voxel_gi->update_element.in_list()) { + voxel_gi_update_list.add(&voxel_gi->update_element); } - gi_probe->probe_instance = scene_render->gi_probe_instance_create(p_base); + voxel_gi->probe_instance = scene_render->voxel_gi_instance_create(p_base); } break; case RS::INSTANCE_OCCLUDER: { @@ -668,22 +668,22 @@ void RendererSceneCull::instance_set_scenario(RID p_instance, RID p_scenario) { case RS::INSTANCE_PARTICLES_COLLISION: { heightfield_particle_colliders_update_list.erase(instance); } break; - case RS::INSTANCE_GI_PROBE: { - InstanceGIProbeData *gi_probe = static_cast(instance->base_data); + case RS::INSTANCE_VOXEL_GI: { + InstanceVoxelGIData *voxel_gi = static_cast(instance->base_data); #ifdef DEBUG_ENABLED - if (gi_probe->geometries.size()) { - ERR_PRINT("BUG, indexing did not unpair geometries from GIProbe."); + if (voxel_gi->geometries.size()) { + ERR_PRINT("BUG, indexing did not unpair geometries from VoxelGI."); } #endif #ifdef DEBUG_ENABLED - if (gi_probe->lights.size()) { - ERR_PRINT("BUG, indexing did not unpair lights from GIProbe."); + if (voxel_gi->lights.size()) { + ERR_PRINT("BUG, indexing did not unpair lights from VoxelGI."); } #endif - if (gi_probe->update_element.in_list()) { - gi_probe_update_list.remove(&gi_probe->update_element); + if (voxel_gi->update_element.in_list()) { + voxel_gi_update_list.remove(&voxel_gi->update_element); } } break; case RS::INSTANCE_OCCLUDER: { @@ -714,10 +714,10 @@ void RendererSceneCull::instance_set_scenario(RID p_instance, RID p_scenario) { light->D = scenario->directional_lights.push_back(instance); } } break; - case RS::INSTANCE_GI_PROBE: { - InstanceGIProbeData *gi_probe = static_cast(instance->base_data); - if (!gi_probe->update_element.in_list()) { - gi_probe_update_list.add(&gi_probe->update_element); + case RS::INSTANCE_VOXEL_GI: { + InstanceVoxelGIData *voxel_gi = static_cast(instance->base_data); + if (!voxel_gi->update_element.in_list()) { + voxel_gi_update_list.add(&voxel_gi->update_element); } } break; case RS::INSTANCE_OCCLUDER: { @@ -1253,10 +1253,10 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { InstanceLightmapData *lightmap = static_cast(p_instance->base_data); scene_render->lightmap_instance_set_transform(lightmap->instance, p_instance->transform); - } else if (p_instance->base_type == RS::INSTANCE_GI_PROBE) { - InstanceGIProbeData *gi_probe = static_cast(p_instance->base_data); + } else if (p_instance->base_type == RS::INSTANCE_VOXEL_GI) { + InstanceVoxelGIData *voxel_gi = static_cast(p_instance->base_data); - scene_render->gi_probe_instance_set_transform_to_data(gi_probe->probe_instance, p_instance->transform); + scene_render->voxel_gi_instance_set_transform_to_data(voxel_gi->probe_instance, p_instance->transform); } else if (p_instance->base_type == RS::INSTANCE_PARTICLES) { RSG::storage->particles_set_emission_transform(p_instance->base, p_instance->transform); } else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) { @@ -1371,8 +1371,8 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { case RS::INSTANCE_LIGHTMAP: { idata.instance_data_rid = static_cast(p_instance->base_data)->instance.get_id(); } break; - case RS::INSTANCE_GI_PROBE: { - idata.instance_data_rid = static_cast(p_instance->base_data)->probe_instance.get_id(); + case RS::INSTANCE_VOXEL_GI: { + idata.instance_data_rid = static_cast(p_instance->base_data)->probe_instance.get_id(); } break; default: { } @@ -1425,7 +1425,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { pair.pair_mask |= 1 << RS::INSTANCE_LIGHT; - pair.pair_mask |= 1 << RS::INSTANCE_GI_PROBE; + pair.pair_mask |= 1 << RS::INSTANCE_VOXEL_GI; pair.pair_mask |= 1 << RS::INSTANCE_LIGHTMAP; if (p_instance->base_type == RS::INSTANCE_PARTICLES) { pair.pair_mask |= 1 << RS::INSTANCE_PARTICLES_COLLISION; @@ -1439,7 +1439,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY]; if (RSG::storage->light_get_bake_mode(p_instance->base) == RS::LIGHT_BAKE_DYNAMIC) { - pair.pair_mask |= (1 << RS::INSTANCE_GI_PROBE); + pair.pair_mask |= (1 << RS::INSTANCE_VOXEL_GI); pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES]; } } else if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE)) { @@ -1451,7 +1451,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { } else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) { pair.pair_mask = (1 << RS::INSTANCE_PARTICLES); pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY]; - } else if (p_instance->base_type == RS::INSTANCE_GI_PROBE) { + } else if (p_instance->base_type == RS::INSTANCE_VOXEL_GI) { //lights and geometries pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK | (1 << RS::INSTANCE_LIGHT); pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY]; @@ -1504,7 +1504,7 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) { scene_render->geometry_instance_pair_light_instances(geom->geometry_instance, nullptr, 0); scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, nullptr, 0); scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, nullptr, 0); - scene_render->geometry_instance_pair_gi_probe_instances(geom->geometry_instance, nullptr, 0); + scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, nullptr, 0); } } @@ -1566,8 +1566,8 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) { new_aabb = RSG::storage->decal_get_aabb(p_instance->base); } break; - case RenderingServer::INSTANCE_GI_PROBE: { - new_aabb = RSG::storage->gi_probe_get_bounds(p_instance->base); + case RenderingServer::INSTANCE_VOXEL_GI: { + new_aabb = RSG::storage->voxel_gi_get_bounds(p_instance->base); } break; case RenderingServer::INSTANCE_LIGHTMAP: { @@ -2384,14 +2384,14 @@ void RendererSceneCull::_frustum_cull(CullData &cull_data, FrustumCullResult &cu } else if (base_type == RS::INSTANCE_DECAL) { cull_result.decals.push_back(RID::from_uint64(idata.instance_data_rid)); - } else if (base_type == RS::INSTANCE_GI_PROBE) { - InstanceGIProbeData *gi_probe = static_cast(idata.instance->base_data); + } else if (base_type == RS::INSTANCE_VOXEL_GI) { + InstanceVoxelGIData *voxel_gi = static_cast(idata.instance->base_data); cull_data.cull->lock.lock(); - if (!gi_probe->update_element.in_list()) { - gi_probe_update_list.add(&gi_probe->update_element); + if (!voxel_gi->update_element.in_list()) { + voxel_gi_update_list.add(&voxel_gi->update_element); } cull_data.cull->lock.unlock(); - cull_result.gi_probes.push_back(RID::from_uint64(idata.instance_data_rid)); + cull_result.voxel_gi_instances.push_back(RID::from_uint64(idata.instance_data_rid)); } else if (base_type == RS::INSTANCE_LIGHTMAP) { cull_result.lightmaps.push_back(RID::from_uint64(idata.instance_data_rid)); @@ -2468,20 +2468,20 @@ void RendererSceneCull::_frustum_cull(CullData &cull_data, FrustumCullResult &cu idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_DECAL_DIRTY); } - if (idata.flags & InstanceData::FLAG_GEOM_GI_PROBE_DIRTY) { + if (idata.flags & InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY) { InstanceGeometryData *geom = static_cast(idata.instance->base_data); uint32_t idx = 0; - for (Set::Element *E = geom->gi_probes.front(); E; E = E->next()) { - InstanceGIProbeData *gi_probe = static_cast(E->get()->base_data); + for (Set::Element *E = geom->voxel_gi_instances.front(); E; E = E->next()) { + InstanceVoxelGIData *voxel_gi = static_cast(E->get()->base_data); - instance_pair_buffer[idx++] = gi_probe->probe_instance; + instance_pair_buffer[idx++] = voxel_gi->probe_instance; if (idx == MAX_INSTANCE_PAIRS) { break; } } - scene_render->geometry_instance_pair_gi_probe_instances(geom->geometry_instance, instance_pair_buffer, idx); - idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_GI_PROBE_DIRTY); + scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, instance_pair_buffer, idx); + idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY); } if ((idata.flags & InstanceData::FLAG_LIGHTMAP_CAPTURE) && idata.instance->last_frame_pass != frame_number && !idata.instance->lightmap_target_sh.is_empty() && !idata.instance->lightmap_sh.is_empty()) { @@ -2864,7 +2864,7 @@ void RendererSceneCull::_render_scene(const Transform3D &p_cam_transform, const } RENDER_TIMESTAMP("Render Scene "); - scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, frustum_cull_result.geometry_instances, frustum_cull_result.light_instances, frustum_cull_result.reflections, frustum_cull_result.gi_probes, frustum_cull_result.decals, frustum_cull_result.lightmaps, p_environment, camera_effects, p_shadow_atlas, occluders_tex, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_lod_threshold, render_shadow_data, max_shadows_used, render_sdfgi_data, cull.sdfgi.region_count, &sdfgi_update_data); + scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, frustum_cull_result.geometry_instances, frustum_cull_result.light_instances, frustum_cull_result.reflections, frustum_cull_result.voxel_gi_instances, frustum_cull_result.decals, frustum_cull_result.lightmaps, p_environment, camera_effects, p_shadow_atlas, occluders_tex, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_lod_threshold, render_shadow_data, max_shadows_used, render_sdfgi_data, cull.sdfgi.region_count, &sdfgi_update_data); for (uint32_t i = 0; i < max_shadows_used; i++) { render_shadow_data[i].instances.clear(); @@ -2875,7 +2875,7 @@ void RendererSceneCull::_render_scene(const Transform3D &p_cam_transform, const render_sdfgi_data[i].instances.clear(); } - // virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray &p_instances, const PagedArray &p_lights, const PagedArray &p_reflection_probes, const PagedArray &p_gi_probes, const PagedArray &p_decals, const PagedArray &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0; + // virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray &p_instances, const PagedArray &p_lights, const PagedArray &p_reflection_probes, const PagedArray &p_voxel_gi_instances, const PagedArray &p_decals, const PagedArray &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0; } RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) { @@ -3033,18 +3033,18 @@ void RendererSceneCull::render_probes() { ref_probe = next; } - /* GI PROBES */ + /* VOXEL GIS */ - SelfList *gi_probe = gi_probe_update_list.first(); + SelfList *voxel_gi = voxel_gi_update_list.first(); - if (gi_probe) { + if (voxel_gi) { RENDER_TIMESTAMP("Render GI Probes"); } - while (gi_probe) { - SelfList *next = gi_probe->next(); + while (voxel_gi) { + SelfList *next = voxel_gi->next(); - InstanceGIProbeData *probe = gi_probe->self(); + InstanceVoxelGIData *probe = voxel_gi->self(); //Instance *instance_probe = probe->owner; //check if probe must be setup, but don't do if on the lighting thread @@ -3053,7 +3053,7 @@ void RendererSceneCull::render_probes() { int cache_count = 0; { int light_cache_size = probe->light_cache.size(); - const InstanceGIProbeData::LightCache *caches = probe->light_cache.ptr(); + const InstanceVoxelGIData::LightCache *caches = probe->light_cache.ptr(); const RID *instance_caches = probe->light_instances.ptr(); int idx = 0; //must count visible lights @@ -3068,7 +3068,7 @@ void RendererSceneCull::render_probes() { } else if (idx >= light_cache_size) { cache_dirty = true; } else { - const InstanceGIProbeData::LightCache *cache = &caches[idx]; + const InstanceVoxelGIData::LightCache *cache = &caches[idx]; if ( instance_caches[idx] != instance_light->instance || @@ -3100,7 +3100,7 @@ void RendererSceneCull::render_probes() { } else if (idx >= light_cache_size) { cache_dirty = true; } else { - const InstanceGIProbeData::LightCache *cache = &caches[idx]; + const InstanceVoxelGIData::LightCache *cache = &caches[idx]; if ( instance_caches[idx] != instance_light->instance || @@ -3129,14 +3129,14 @@ void RendererSceneCull::render_probes() { cache_count = idx; } - bool update_lights = scene_render->gi_probe_needs_update(probe->probe_instance); + bool update_lights = scene_render->voxel_gi_needs_update(probe->probe_instance); if (cache_dirty) { probe->light_cache.resize(cache_count); probe->light_instances.resize(cache_count); if (cache_count) { - InstanceGIProbeData::LightCache *caches = probe->light_cache.ptrw(); + InstanceVoxelGIData::LightCache *caches = probe->light_cache.ptrw(); RID *instance_caches = probe->light_instances.ptrw(); int idx = 0; //must count visible lights @@ -3147,7 +3147,7 @@ void RendererSceneCull::render_probes() { continue; } - InstanceGIProbeData::LightCache *cache = &caches[idx]; + InstanceVoxelGIData::LightCache *cache = &caches[idx]; instance_caches[idx] = instance_light->instance; cache->has_shadow = RSG::storage->light_has_shadow(instance->base); @@ -3170,7 +3170,7 @@ void RendererSceneCull::render_probes() { continue; } - InstanceGIProbeData::LightCache *cache = &caches[idx]; + InstanceVoxelGIData::LightCache *cache = &caches[idx]; instance_caches[idx] = instance_light->instance; cache->has_shadow = RSG::storage->light_has_shadow(instance->base); @@ -3203,30 +3203,30 @@ void RendererSceneCull::render_probes() { } InstanceGeometryData *geom = (InstanceGeometryData *)ins->base_data; - if (ins->scenario && ins->array_index >= 0 && (ins->scenario->instance_data[ins->array_index].flags & InstanceData::FLAG_GEOM_GI_PROBE_DIRTY)) { + if (ins->scenario && ins->array_index >= 0 && (ins->scenario->instance_data[ins->array_index].flags & InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY)) { uint32_t idx = 0; - for (Set::Element *F = geom->gi_probes.front(); F; F = F->next()) { - InstanceGIProbeData *gi_probe2 = static_cast(F->get()->base_data); + for (Set::Element *F = geom->voxel_gi_instances.front(); F; F = F->next()) { + InstanceVoxelGIData *voxel_gi2 = static_cast(F->get()->base_data); - instance_pair_buffer[idx++] = gi_probe2->probe_instance; + instance_pair_buffer[idx++] = voxel_gi2->probe_instance; if (idx == MAX_INSTANCE_PAIRS) { break; } } - scene_render->geometry_instance_pair_gi_probe_instances(geom->geometry_instance, instance_pair_buffer, idx); + scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, instance_pair_buffer, idx); - ins->scenario->instance_data[ins->array_index].flags &= ~uint32_t(InstanceData::FLAG_GEOM_GI_PROBE_DIRTY); + ins->scenario->instance_data[ins->array_index].flags &= ~uint32_t(InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY); } frustum_cull_result.geometry_instances.push_back(geom->geometry_instance); } - scene_render->gi_probe_update(probe->probe_instance, update_lights, probe->light_instances, frustum_cull_result.geometry_instances); + scene_render->voxel_gi_update(probe->probe_instance, update_lights, probe->light_instances, frustum_cull_result.geometry_instances); - gi_probe_update_list.remove(gi_probe); + voxel_gi_update_list.remove(voxel_gi); - gi_probe = next; + voxel_gi = next; } } diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index a89b9da587..f10eb67828 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -253,7 +253,7 @@ public: FLAG_GEOM_LIGHTING_DIRTY = (1 << 11), FLAG_GEOM_REFLECTION_DIRTY = (1 << 12), FLAG_GEOM_DECAL_DIRTY = (1 << 13), - FLAG_GEOM_GI_PROBE_DIRTY = (1 << 14), + FLAG_GEOM_VOXEL_GI_DIRTY = (1 << 14), FLAG_LIGHTMAP_CAPTURE = (1 << 15), FLAG_USES_BAKED_LIGHT = (1 << 16), FLAG_USES_MESH_INSTANCE = (1 << 17), @@ -535,7 +535,7 @@ public: Set decals; Set reflection_probes; - Set gi_probes; + Set voxel_gi_instances; Set lightmap_captures; InstanceGeometryData() { @@ -599,7 +599,7 @@ public: } }; - struct InstanceGIProbeData : public InstanceBaseData { + struct InstanceVoxelGIData : public InstanceBaseData { Instance *owner; Set geometries; @@ -629,16 +629,16 @@ public: bool invalid; uint32_t base_version; - SelfList update_element; + SelfList update_element; - InstanceGIProbeData() : + InstanceVoxelGIData() : update_element(this) { invalid = true; base_version = 0; } }; - SelfList::List gi_probe_update_list; + SelfList::List voxel_gi_update_list; struct InstanceLightmapData : public InstanceBaseData { RID instance; @@ -724,7 +724,7 @@ public: PagedArray lightmaps; PagedArray reflections; PagedArray decals; - PagedArray gi_probes; + PagedArray voxel_gi_instances; PagedArray mesh_instances; struct DirectionalShadow { @@ -741,7 +741,7 @@ public: lightmaps.clear(); reflections.clear(); decals.clear(); - gi_probes.clear(); + voxel_gi_instances.clear(); mesh_instances.clear(); for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) { for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) { @@ -765,7 +765,7 @@ public: lightmaps.reset(); reflections.reset(); decals.reset(); - gi_probes.reset(); + voxel_gi_instances.reset(); mesh_instances.reset(); for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) { for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) { @@ -789,7 +789,7 @@ public: lightmaps.merge_unordered(p_cull_result.lightmaps); reflections.merge_unordered(p_cull_result.reflections); decals.merge_unordered(p_cull_result.decals); - gi_probes.merge_unordered(p_cull_result.gi_probes); + voxel_gi_instances.merge_unordered(p_cull_result.voxel_gi_instances); mesh_instances.merge_unordered(p_cull_result.mesh_instances); for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) { @@ -814,7 +814,7 @@ public: lightmaps.set_page_pool(p_rid_pool); reflections.set_page_pool(p_rid_pool); decals.set_page_pool(p_rid_pool); - gi_probes.set_page_pool(p_rid_pool); + voxel_gi_instances.set_page_pool(p_rid_pool); mesh_instances.set_page_pool(p_rid_pool); for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) { for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) { @@ -975,7 +975,7 @@ public: #define PASSBASE scene_render PASS2(directional_shadow_atlas_set_size, int, bool) - PASS1(gi_probe_set_quality, RS::GIProbeQuality) + PASS1(voxel_gi_set_quality, RS::VoxelGIQuality) /* SKY API */ diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h index 0a9cf13e4a..5f3e6df4e3 100644 --- a/servers/rendering/renderer_scene_render.h +++ b/servers/rendering/renderer_scene_render.h @@ -65,7 +65,7 @@ public: virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) = 0; virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) = 0; virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) = 0; - virtual void geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) = 0; + virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) = 0; virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) = 0; @@ -187,12 +187,12 @@ public: virtual RID lightmap_instance_create(RID p_lightmap) = 0; virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) = 0; - virtual RID gi_probe_instance_create(RID p_gi_probe) = 0; - virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) = 0; - virtual bool gi_probe_needs_update(RID p_probe) const = 0; - virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector &p_light_instances, const PagedArray &p_dynamic_objects) = 0; + virtual RID voxel_gi_instance_create(RID p_voxel_gi) = 0; + virtual void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) = 0; + virtual bool voxel_gi_needs_update(RID p_probe) const = 0; + virtual void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector &p_light_instances, const PagedArray &p_dynamic_objects) = 0; - virtual void gi_probe_set_quality(RS::GIProbeQuality) = 0; + virtual void voxel_gi_set_quality(RS::VoxelGIQuality) = 0; struct RenderShadowData { RID light; @@ -216,7 +216,7 @@ public: uint32_t positional_light_count; }; - virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray &p_instances, const PagedArray &p_lights, const PagedArray &p_reflection_probes, const PagedArray &p_gi_probes, const PagedArray &p_decals, const PagedArray &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr) = 0; + virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray &p_instances, const PagedArray &p_lights, const PagedArray &p_reflection_probes, const PagedArray &p_voxel_gi_instances, const PagedArray &p_decals, const PagedArray &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr) = 0; virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray &p_instances) = 0; diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h index a3fe4b663a..0b9b82cba0 100644 --- a/servers/rendering/renderer_storage.h +++ b/servers/rendering/renderer_storage.h @@ -413,53 +413,53 @@ public: virtual AABB decal_get_aabb(RID p_decal) const = 0; - /* GI PROBE API */ + /* VOXEL GI API */ - virtual RID gi_probe_allocate() = 0; - virtual void gi_probe_initialize(RID p_rid) = 0; + virtual RID voxel_gi_allocate() = 0; + virtual void voxel_gi_initialize(RID p_rid) = 0; - virtual void gi_probe_allocate_data(RID p_gi_probe, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts) = 0; + virtual void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts) = 0; - virtual AABB gi_probe_get_bounds(RID p_gi_probe) const = 0; - virtual Vector3i gi_probe_get_octree_size(RID p_gi_probe) const = 0; - virtual Vector gi_probe_get_octree_cells(RID p_gi_probe) const = 0; - virtual Vector gi_probe_get_data_cells(RID p_gi_probe) const = 0; - virtual Vector gi_probe_get_distance_field(RID p_gi_probe) const = 0; + virtual AABB voxel_gi_get_bounds(RID p_voxel_gi) const = 0; + virtual Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const = 0; + virtual Vector voxel_gi_get_octree_cells(RID p_voxel_gi) const = 0; + virtual Vector voxel_gi_get_data_cells(RID p_voxel_gi) const = 0; + virtual Vector voxel_gi_get_distance_field(RID p_voxel_gi) const = 0; - virtual Vector gi_probe_get_level_counts(RID p_gi_probe) const = 0; - virtual Transform3D gi_probe_get_to_cell_xform(RID p_gi_probe) const = 0; + virtual Vector voxel_gi_get_level_counts(RID p_voxel_gi) const = 0; + virtual Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const = 0; - virtual void gi_probe_set_dynamic_range(RID p_gi_probe, float p_range) = 0; - virtual float gi_probe_get_dynamic_range(RID p_gi_probe) const = 0; + virtual void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) = 0; + virtual float voxel_gi_get_dynamic_range(RID p_voxel_gi) const = 0; - virtual void gi_probe_set_propagation(RID p_gi_probe, float p_range) = 0; - virtual float gi_probe_get_propagation(RID p_gi_probe) const = 0; + virtual void voxel_gi_set_propagation(RID p_voxel_gi, float p_range) = 0; + virtual float voxel_gi_get_propagation(RID p_voxel_gi) const = 0; - virtual void gi_probe_set_energy(RID p_gi_probe, float p_energy) = 0; - virtual float gi_probe_get_energy(RID p_gi_probe) const = 0; + virtual void voxel_gi_set_energy(RID p_voxel_gi, float p_energy) = 0; + virtual float voxel_gi_get_energy(RID p_voxel_gi) const = 0; - virtual void gi_probe_set_ao(RID p_gi_probe, float p_ao) = 0; - virtual float gi_probe_get_ao(RID p_gi_probe) const = 0; + virtual void voxel_gi_set_ao(RID p_voxel_gi, float p_ao) = 0; + virtual float voxel_gi_get_ao(RID p_voxel_gi) const = 0; - virtual void gi_probe_set_ao_size(RID p_gi_probe, float p_strength) = 0; - virtual float gi_probe_get_ao_size(RID p_gi_probe) const = 0; + virtual void voxel_gi_set_ao_size(RID p_voxel_gi, float p_strength) = 0; + virtual float voxel_gi_get_ao_size(RID p_voxel_gi) const = 0; - virtual void gi_probe_set_bias(RID p_gi_probe, float p_bias) = 0; - virtual float gi_probe_get_bias(RID p_gi_probe) const = 0; + virtual void voxel_gi_set_bias(RID p_voxel_gi, float p_bias) = 0; + virtual float voxel_gi_get_bias(RID p_voxel_gi) const = 0; - virtual void gi_probe_set_normal_bias(RID p_gi_probe, float p_range) = 0; - virtual float gi_probe_get_normal_bias(RID p_gi_probe) const = 0; + virtual void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) = 0; + virtual float voxel_gi_get_normal_bias(RID p_voxel_gi) const = 0; - virtual void gi_probe_set_interior(RID p_gi_probe, bool p_enable) = 0; - virtual bool gi_probe_is_interior(RID p_gi_probe) const = 0; + virtual void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) = 0; + virtual bool voxel_gi_is_interior(RID p_voxel_gi) const = 0; - virtual void gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable) = 0; - virtual bool gi_probe_is_using_two_bounces(RID p_gi_probe) const = 0; + virtual void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) = 0; + virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const = 0; - virtual void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) = 0; - virtual float gi_probe_get_anisotropy_strength(RID p_gi_probe) const = 0; + virtual void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) = 0; + virtual float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const = 0; - virtual uint32_t gi_probe_get_version(RID p_probe) = 0; + virtual uint32_t voxel_gi_get_version(RID p_probe) = 0; /* LIGHTMAP */ diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 4f4a8e7bf6..6476d7c75d 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -418,47 +418,47 @@ public: /* BAKED LIGHT API */ - FUNCRIDSPLIT(gi_probe) + FUNCRIDSPLIT(voxel_gi) - FUNC8(gi_probe_allocate_data, RID, const Transform3D &, const AABB &, const Vector3i &, const Vector &, const Vector &, const Vector &, const Vector &) + FUNC8(voxel_gi_allocate_data, RID, const Transform3D &, const AABB &, const Vector3i &, const Vector &, const Vector &, const Vector &, const Vector &) - FUNC1RC(AABB, gi_probe_get_bounds, RID) - FUNC1RC(Vector3i, gi_probe_get_octree_size, RID) - FUNC1RC(Vector, gi_probe_get_octree_cells, RID) - FUNC1RC(Vector, gi_probe_get_data_cells, RID) - FUNC1RC(Vector, gi_probe_get_distance_field, RID) - FUNC1RC(Vector, gi_probe_get_level_counts, RID) - FUNC1RC(Transform3D, gi_probe_get_to_cell_xform, RID) + FUNC1RC(AABB, voxel_gi_get_bounds, RID) + FUNC1RC(Vector3i, voxel_gi_get_octree_size, RID) + FUNC1RC(Vector, voxel_gi_get_octree_cells, RID) + FUNC1RC(Vector, voxel_gi_get_data_cells, RID) + FUNC1RC(Vector, voxel_gi_get_distance_field, RID) + FUNC1RC(Vector, voxel_gi_get_level_counts, RID) + FUNC1RC(Transform3D, voxel_gi_get_to_cell_xform, RID) - FUNC2(gi_probe_set_dynamic_range, RID, float) - FUNC1RC(float, gi_probe_get_dynamic_range, RID) + FUNC2(voxel_gi_set_dynamic_range, RID, float) + FUNC1RC(float, voxel_gi_get_dynamic_range, RID) - FUNC2(gi_probe_set_propagation, RID, float) - FUNC1RC(float, gi_probe_get_propagation, RID) + FUNC2(voxel_gi_set_propagation, RID, float) + FUNC1RC(float, voxel_gi_get_propagation, RID) - FUNC2(gi_probe_set_energy, RID, float) - FUNC1RC(float, gi_probe_get_energy, RID) + FUNC2(voxel_gi_set_energy, RID, float) + FUNC1RC(float, voxel_gi_get_energy, RID) - FUNC2(gi_probe_set_ao, RID, float) - FUNC1RC(float, gi_probe_get_ao, RID) + FUNC2(voxel_gi_set_ao, RID, float) + FUNC1RC(float, voxel_gi_get_ao, RID) - FUNC2(gi_probe_set_ao_size, RID, float) - FUNC1RC(float, gi_probe_get_ao_size, RID) + FUNC2(voxel_gi_set_ao_size, RID, float) + FUNC1RC(float, voxel_gi_get_ao_size, RID) - FUNC2(gi_probe_set_bias, RID, float) - FUNC1RC(float, gi_probe_get_bias, RID) + FUNC2(voxel_gi_set_bias, RID, float) + FUNC1RC(float, voxel_gi_get_bias, RID) - FUNC2(gi_probe_set_normal_bias, RID, float) - FUNC1RC(float, gi_probe_get_normal_bias, RID) + FUNC2(voxel_gi_set_normal_bias, RID, float) + FUNC1RC(float, voxel_gi_get_normal_bias, RID) - FUNC2(gi_probe_set_interior, RID, bool) - FUNC1RC(bool, gi_probe_is_interior, RID) + FUNC2(voxel_gi_set_interior, RID, bool) + FUNC1RC(bool, voxel_gi_is_interior, RID) - FUNC2(gi_probe_set_use_two_bounces, RID, bool) - FUNC1RC(bool, gi_probe_is_using_two_bounces, RID) + FUNC2(voxel_gi_set_use_two_bounces, RID, bool) + FUNC1RC(bool, voxel_gi_is_using_two_bounces, RID) - FUNC2(gi_probe_set_anisotropy_strength, RID, float) - FUNC1RC(float, gi_probe_get_anisotropy_strength, RID) + FUNC2(voxel_gi_set_anisotropy_strength, RID, float) + FUNC1RC(float, voxel_gi_get_anisotropy_strength, RID) /* LIGHTMAP */ @@ -624,7 +624,7 @@ public: #define server_name RSG::scene FUNC2(directional_shadow_atlas_set_size, int, bool) - FUNC1(gi_probe_set_quality, GIProbeQuality) + FUNC1(voxel_gi_set_quality, VoxelGIQuality) /* SKY API */ diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 4741e90a81..0471990ed7 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -1569,32 +1569,32 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("reflection_probe_set_cull_mask", "probe", "layers"), &RenderingServer::reflection_probe_set_cull_mask); #ifndef _MSC_VER -#warning TODO all giprobe methods need re-binding +#warning TODO all voxel_gi methods need re-binding #endif #if 0 - ClassDB::bind_method(D_METHOD("gi_probe_create"), &RenderingServer::gi_probe_create); - ClassDB::bind_method(D_METHOD("gi_probe_set_bounds", "probe", "bounds"), &RenderingServer::gi_probe_set_bounds); - ClassDB::bind_method(D_METHOD("gi_probe_get_bounds", "probe"), &RenderingServer::gi_probe_get_bounds); - ClassDB::bind_method(D_METHOD("gi_probe_set_cell_size", "probe", "range"), &RenderingServer::gi_probe_set_cell_size); - ClassDB::bind_method(D_METHOD("gi_probe_get_cell_size", "probe"), &RenderingServer::gi_probe_get_cell_size); - ClassDB::bind_method(D_METHOD("gi_probe_set_to_cell_xform", "probe", "xform"), &RenderingServer::gi_probe_set_to_cell_xform); - ClassDB::bind_method(D_METHOD("gi_probe_get_to_cell_xform", "probe"), &RenderingServer::gi_probe_get_to_cell_xform); - ClassDB::bind_method(D_METHOD("gi_probe_set_dynamic_data", "probe", "data"), &RenderingServer::gi_probe_set_dynamic_data); - ClassDB::bind_method(D_METHOD("gi_probe_get_dynamic_data", "probe"), &RenderingServer::gi_probe_get_dynamic_data); - ClassDB::bind_method(D_METHOD("gi_probe_set_dynamic_range", "probe", "range"), &RenderingServer::gi_probe_set_dynamic_range); - ClassDB::bind_method(D_METHOD("gi_probe_get_dynamic_range", "probe"), &RenderingServer::gi_probe_get_dynamic_range); - ClassDB::bind_method(D_METHOD("gi_probe_set_energy", "probe", "energy"), &RenderingServer::gi_probe_set_energy); - ClassDB::bind_method(D_METHOD("gi_probe_get_energy", "probe"), &RenderingServer::gi_probe_get_energy); - ClassDB::bind_method(D_METHOD("gi_probe_set_bias", "probe", "bias"), &RenderingServer::gi_probe_set_bias); - ClassDB::bind_method(D_METHOD("gi_probe_get_bias", "probe"), &RenderingServer::gi_probe_get_bias); - ClassDB::bind_method(D_METHOD("gi_probe_set_normal_bias", "probe", "bias"), &RenderingServer::gi_probe_set_normal_bias); - ClassDB::bind_method(D_METHOD("gi_probe_get_normal_bias", "probe"), &RenderingServer::gi_probe_get_normal_bias); - ClassDB::bind_method(D_METHOD("gi_probe_set_propagation", "probe", "propagation"), &RenderingServer::gi_probe_set_propagation); - ClassDB::bind_method(D_METHOD("gi_probe_get_propagation", "probe"), &RenderingServer::gi_probe_get_propagation); - ClassDB::bind_method(D_METHOD("gi_probe_set_interior", "probe", "enable"), &RenderingServer::gi_probe_set_interior); - ClassDB::bind_method(D_METHOD("gi_probe_is_interior", "probe"), &RenderingServer::gi_probe_is_interior); - ClassDB::bind_method(D_METHOD("gi_probe_set_compress", "probe", "enable"), &RenderingServer::gi_probe_set_compress); - ClassDB::bind_method(D_METHOD("gi_probe_is_compressed", "probe"), &RenderingServer::gi_probe_is_compressed); + ClassDB::bind_method(D_METHOD("voxel_gi_create"), &RenderingServer::voxel_gi_create); + ClassDB::bind_method(D_METHOD("voxel_gi_set_bounds", "probe", "bounds"), &RenderingServer::voxel_gi_set_bounds); + ClassDB::bind_method(D_METHOD("voxel_gi_get_bounds", "probe"), &RenderingServer::voxel_gi_get_bounds); + ClassDB::bind_method(D_METHOD("voxel_gi_set_cell_size", "probe", "range"), &RenderingServer::voxel_gi_set_cell_size); + ClassDB::bind_method(D_METHOD("voxel_gi_get_cell_size", "probe"), &RenderingServer::voxel_gi_get_cell_size); + ClassDB::bind_method(D_METHOD("voxel_gi_set_to_cell_xform", "probe", "xform"), &RenderingServer::voxel_gi_set_to_cell_xform); + ClassDB::bind_method(D_METHOD("voxel_gi_get_to_cell_xform", "probe"), &RenderingServer::voxel_gi_get_to_cell_xform); + ClassDB::bind_method(D_METHOD("voxel_gi_set_dynamic_data", "probe", "data"), &RenderingServer::voxel_gi_set_dynamic_data); + ClassDB::bind_method(D_METHOD("voxel_gi_get_dynamic_data", "probe"), &RenderingServer::voxel_gi_get_dynamic_data); + ClassDB::bind_method(D_METHOD("voxel_gi_set_dynamic_range", "probe", "range"), &RenderingServer::voxel_gi_set_dynamic_range); + ClassDB::bind_method(D_METHOD("voxel_gi_get_dynamic_range", "probe"), &RenderingServer::voxel_gi_get_dynamic_range); + ClassDB::bind_method(D_METHOD("voxel_gi_set_energy", "probe", "energy"), &RenderingServer::voxel_gi_set_energy); + ClassDB::bind_method(D_METHOD("voxel_gi_get_energy", "probe"), &RenderingServer::voxel_gi_get_energy); + ClassDB::bind_method(D_METHOD("voxel_gi_set_bias", "probe", "bias"), &RenderingServer::voxel_gi_set_bias); + ClassDB::bind_method(D_METHOD("voxel_gi_get_bias", "probe"), &RenderingServer::voxel_gi_get_bias); + ClassDB::bind_method(D_METHOD("voxel_gi_set_normal_bias", "probe", "bias"), &RenderingServer::voxel_gi_set_normal_bias); + ClassDB::bind_method(D_METHOD("voxel_gi_get_normal_bias", "probe"), &RenderingServer::voxel_gi_get_normal_bias); + ClassDB::bind_method(D_METHOD("voxel_gi_set_propagation", "probe", "propagation"), &RenderingServer::voxel_gi_set_propagation); + ClassDB::bind_method(D_METHOD("voxel_gi_get_propagation", "probe"), &RenderingServer::voxel_gi_get_propagation); + ClassDB::bind_method(D_METHOD("voxel_gi_set_interior", "probe", "enable"), &RenderingServer::voxel_gi_set_interior); + ClassDB::bind_method(D_METHOD("voxel_gi_is_interior", "probe"), &RenderingServer::voxel_gi_is_interior); + ClassDB::bind_method(D_METHOD("voxel_gi_set_compress", "probe", "enable"), &RenderingServer::voxel_gi_set_compress); + ClassDB::bind_method(D_METHOD("voxel_gi_is_compressed", "probe"), &RenderingServer::voxel_gi_is_compressed); #endif /* ClassDB::bind_method(D_METHOD("lightmap_create()"), &RenderingServer::lightmap_capture_create); @@ -2022,9 +2022,9 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_OVERDRAW); BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_WIREFRAME); BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER); - BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO); - BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING); - BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_VOXEL_GI_ALBEDO); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION); BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS); BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS); BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE); @@ -2117,7 +2117,7 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(INSTANCE_LIGHT); BIND_ENUM_CONSTANT(INSTANCE_REFLECTION_PROBE); BIND_ENUM_CONSTANT(INSTANCE_DECAL); - BIND_ENUM_CONSTANT(INSTANCE_GI_PROBE); + BIND_ENUM_CONSTANT(INSTANCE_VOXEL_GI); BIND_ENUM_CONSTANT(INSTANCE_LIGHTMAP); BIND_ENUM_CONSTANT(INSTANCE_OCCLUDER); BIND_ENUM_CONSTANT(INSTANCE_MAX); @@ -2324,9 +2324,9 @@ RenderingServer::RenderingServer() { GLOBAL_DEF("rendering/global_illumination/gi/use_half_resolution", false); - GLOBAL_DEF("rendering/global_illumination/gi_probes/anisotropic", false); - GLOBAL_DEF("rendering/global_illumination/gi_probes/quality", 1); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/global_illumination/gi_probes/quality", PropertyInfo(Variant::INT, "rendering/global_illumination/gi_probes/quality", PROPERTY_HINT_ENUM, "Low (4 Cones - Fast),High (6 Cones - Slow)")); + GLOBAL_DEF("rendering/global_illumination/voxel_gi/anisotropic", false); + GLOBAL_DEF("rendering/global_illumination/voxel_gi/quality", 1); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/global_illumination/voxel_gi/quality", PropertyInfo(Variant::INT, "rendering/global_illumination/voxel_gi/quality", PROPERTY_HINT_ENUM, "Low (4 Cones - Fast),High (6 Cones - Slow)")); GLOBAL_DEF("rendering/shading/overrides/force_vertex_shading", false); GLOBAL_DEF("rendering/shading/overrides/force_vertex_shading.mobile", true); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 975b2401f4..3247717e98 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -548,56 +548,56 @@ public: virtual void decal_set_fade(RID p_decal, float p_above, float p_below) = 0; virtual void decal_set_normal_fade(RID p_decal, float p_fade) = 0; - /* GI PROBE API */ + /* VOXEL GI API */ - virtual RID gi_probe_create() = 0; + virtual RID voxel_gi_create() = 0; - virtual void gi_probe_allocate_data(RID p_gi_probe, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts) = 0; + virtual void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts) = 0; - virtual AABB gi_probe_get_bounds(RID p_gi_probe) const = 0; - virtual Vector3i gi_probe_get_octree_size(RID p_gi_probe) const = 0; - virtual Vector gi_probe_get_octree_cells(RID p_gi_probe) const = 0; - virtual Vector gi_probe_get_data_cells(RID p_gi_probe) const = 0; - virtual Vector gi_probe_get_distance_field(RID p_gi_probe) const = 0; - virtual Vector gi_probe_get_level_counts(RID p_gi_probe) const = 0; - virtual Transform3D gi_probe_get_to_cell_xform(RID p_gi_probe) const = 0; + virtual AABB voxel_gi_get_bounds(RID p_voxel_gi) const = 0; + virtual Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const = 0; + virtual Vector voxel_gi_get_octree_cells(RID p_voxel_gi) const = 0; + virtual Vector voxel_gi_get_data_cells(RID p_voxel_gi) const = 0; + virtual Vector voxel_gi_get_distance_field(RID p_voxel_gi) const = 0; + virtual Vector voxel_gi_get_level_counts(RID p_voxel_gi) const = 0; + virtual Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const = 0; - virtual void gi_probe_set_dynamic_range(RID p_gi_probe, float p_range) = 0; - virtual float gi_probe_get_dynamic_range(RID p_gi_probe) const = 0; + virtual void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) = 0; + virtual float voxel_gi_get_dynamic_range(RID p_voxel_gi) const = 0; - virtual void gi_probe_set_propagation(RID p_gi_probe, float p_range) = 0; - virtual float gi_probe_get_propagation(RID p_gi_probe) const = 0; + virtual void voxel_gi_set_propagation(RID p_voxel_gi, float p_range) = 0; + virtual float voxel_gi_get_propagation(RID p_voxel_gi) const = 0; - virtual void gi_probe_set_energy(RID p_gi_probe, float p_energy) = 0; - virtual float gi_probe_get_energy(RID p_gi_probe) const = 0; + virtual void voxel_gi_set_energy(RID p_voxel_gi, float p_energy) = 0; + virtual float voxel_gi_get_energy(RID p_voxel_gi) const = 0; - virtual void gi_probe_set_ao(RID p_gi_probe, float p_ao) = 0; - virtual float gi_probe_get_ao(RID p_gi_probe) const = 0; + virtual void voxel_gi_set_ao(RID p_voxel_gi, float p_ao) = 0; + virtual float voxel_gi_get_ao(RID p_voxel_gi) const = 0; - virtual void gi_probe_set_ao_size(RID p_gi_probe, float p_strength) = 0; - virtual float gi_probe_get_ao_size(RID p_gi_probe) const = 0; + virtual void voxel_gi_set_ao_size(RID p_voxel_gi, float p_strength) = 0; + virtual float voxel_gi_get_ao_size(RID p_voxel_gi) const = 0; - virtual void gi_probe_set_bias(RID p_gi_probe, float p_bias) = 0; - virtual float gi_probe_get_bias(RID p_gi_probe) const = 0; + virtual void voxel_gi_set_bias(RID p_voxel_gi, float p_bias) = 0; + virtual float voxel_gi_get_bias(RID p_voxel_gi) const = 0; - virtual void gi_probe_set_normal_bias(RID p_gi_probe, float p_range) = 0; - virtual float gi_probe_get_normal_bias(RID p_gi_probe) const = 0; + virtual void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) = 0; + virtual float voxel_gi_get_normal_bias(RID p_voxel_gi) const = 0; - virtual void gi_probe_set_interior(RID p_gi_probe, bool p_enable) = 0; - virtual bool gi_probe_is_interior(RID p_gi_probe) const = 0; + virtual void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) = 0; + virtual bool voxel_gi_is_interior(RID p_voxel_gi) const = 0; - virtual void gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable) = 0; - virtual bool gi_probe_is_using_two_bounces(RID p_gi_probe) const = 0; + virtual void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) = 0; + virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const = 0; - virtual void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) = 0; - virtual float gi_probe_get_anisotropy_strength(RID p_gi_probe) const = 0; + virtual void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) = 0; + virtual float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const = 0; - enum GIProbeQuality { - GI_PROBE_QUALITY_LOW, - GI_PROBE_QUALITY_HIGH, + enum VoxelGIQuality { + VOXEL_GI_QUALITY_LOW, + VOXEL_GI_QUALITY_HIGH, }; - virtual void gi_probe_set_quality(GIProbeQuality) = 0; + virtual void voxel_gi_set_quality(VoxelGIQuality) = 0; /* LIGHTMAP */ @@ -882,9 +882,9 @@ public: VIEWPORT_DEBUG_DRAW_OVERDRAW, VIEWPORT_DEBUG_DRAW_WIREFRAME, VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER, - VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO, - VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, - VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, + VIEWPORT_DEBUG_DRAW_VOXEL_GI_ALBEDO, + VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING, + VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION, VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS, VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS, VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE, @@ -1145,7 +1145,7 @@ public: INSTANCE_LIGHT, INSTANCE_REFLECTION_PROBE, INSTANCE_DECAL, - INSTANCE_GI_PROBE, + INSTANCE_VOXEL_GI, INSTANCE_LIGHTMAP, INSTANCE_OCCLUDER, INSTANCE_MAX, -- cgit v1.2.3