From 5a98845655900a7884bf5a73c5406318f1106d77 Mon Sep 17 00:00:00 2001 From: Bastiaan Olij Date: Thu, 3 Aug 2023 22:10:03 +1000 Subject: [PATCH] Implement hooks into renderer --- doc/classes/Camera3D.xml | 3 + doc/classes/Compositor.xml | 17 ++ doc/classes/CompositorEffect.xml | 85 ++++++ doc/classes/FramebufferCacheRD.xml | 22 ++ doc/classes/RenderData.xml | 38 +++ doc/classes/RenderDataExtension.xml | 36 +++ doc/classes/RenderDataRD.xml | 13 + doc/classes/RenderSceneBuffers.xml | 2 +- doc/classes/RenderSceneBuffersRD.xml | 21 +- doc/classes/RenderSceneData.xml | 55 ++++ doc/classes/RenderSceneDataExtension.xml | 51 ++++ doc/classes/RenderSceneDataRD.xml | 12 + doc/classes/RenderingServer.xml | 96 +++++++ doc/classes/UniformSetCacheRD.xml | 22 ++ doc/classes/WorldEnvironment.xml | 3 + drivers/gles3/rasterizer_scene_gles3.cpp | 2 +- drivers/gles3/rasterizer_scene_gles3.h | 2 +- .../4.2-stable.expected | 13 + scene/3d/camera_3d.cpp | 17 ++ scene/3d/camera_3d.h | 5 + scene/3d/world_environment.cpp | 54 ++++ scene/3d/world_environment.h | 6 + scene/register_scene_types.cpp | 4 + scene/resources/compositor.cpp | 250 ++++++++++++++++++ scene/resources/compositor.h | 125 +++++++++ scene/resources/world_3d.cpp | 13 + scene/resources/world_3d.h | 5 + servers/register_server_types.cpp | 19 +- .../rendering/dummy/rasterizer_scene_dummy.h | 8 +- .../rendering/renderer_rd/environment/gi.h | 2 +- .../render_forward_clustered.cpp | 128 +++++++-- .../render_forward_clustered.h | 14 +- .../forward_mobile/render_forward_mobile.cpp | 44 ++- .../renderer_rd/framebuffer_cache_rd.cpp | 23 ++ .../renderer_rd/framebuffer_cache_rd.h | 6 + .../renderer_rd/renderer_scene_render_rd.cpp | 74 +++++- .../renderer_rd/renderer_scene_render_rd.h | 52 +--- .../renderer_rd/storage_rd/light_storage.h | 2 +- .../renderer_rd/storage_rd/render_data_rd.cpp | 50 ++++ .../renderer_rd/storage_rd/render_data_rd.h | 97 +++++++ .../render_scene_buffers_rd.compat.inc | 66 +++++ .../storage_rd/render_scene_buffers_rd.cpp | 15 +- .../storage_rd/render_scene_buffers_rd.h | 76 ++++-- .../storage_rd/render_scene_data_rd.cpp | 29 +- .../storage_rd/render_scene_data_rd.h | 16 +- .../renderer_rd/uniform_set_cache_rd.cpp | 17 ++ .../renderer_rd/uniform_set_cache_rd.h | 6 + servers/rendering/renderer_scene_cull.cpp | 39 ++- servers/rendering/renderer_scene_cull.h | 29 +- servers/rendering/renderer_scene_render.cpp | 58 ++++ servers/rendering/renderer_scene_render.h | 25 +- servers/rendering/rendering_device_binds.h | 2 + servers/rendering/rendering_method.h | 23 ++ servers/rendering/rendering_server_default.h | 19 +- .../rendering/storage/compositor_storage.cpp | 160 +++++++++++ .../rendering/storage/compositor_storage.h | 98 +++++++ .../rendering/storage/environment_storage.cpp | 14 + .../rendering/storage/environment_storage.h | 9 + servers/rendering/storage/render_data.cpp | 69 +++++ servers/rendering/storage/render_data.h | 70 +++++ .../rendering/storage/render_scene_data.cpp | 88 ++++++ servers/rendering/storage/render_scene_data.h | 82 ++++++ servers/rendering_server.cpp | 28 ++ servers/rendering_server.h | 35 +++ 64 files changed, 2432 insertions(+), 132 deletions(-) create mode 100644 doc/classes/Compositor.xml create mode 100644 doc/classes/CompositorEffect.xml create mode 100644 doc/classes/FramebufferCacheRD.xml create mode 100644 doc/classes/RenderData.xml create mode 100644 doc/classes/RenderDataExtension.xml create mode 100644 doc/classes/RenderDataRD.xml create mode 100644 doc/classes/RenderSceneData.xml create mode 100644 doc/classes/RenderSceneDataExtension.xml create mode 100644 doc/classes/RenderSceneDataRD.xml create mode 100644 doc/classes/UniformSetCacheRD.xml create mode 100644 scene/resources/compositor.cpp create mode 100644 scene/resources/compositor.h create mode 100644 servers/rendering/renderer_rd/storage_rd/render_data_rd.cpp create mode 100644 servers/rendering/renderer_rd/storage_rd/render_data_rd.h create mode 100644 servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.compat.inc create mode 100644 servers/rendering/storage/compositor_storage.cpp create mode 100644 servers/rendering/storage/compositor_storage.h create mode 100644 servers/rendering/storage/render_data.cpp create mode 100644 servers/rendering/storage/render_data.h create mode 100644 servers/rendering/storage/render_scene_data.cpp create mode 100644 servers/rendering/storage/render_scene_data.h diff --git a/doc/classes/Camera3D.xml b/doc/classes/Camera3D.xml index 07b23e025203..01890b471c3b 100644 --- a/doc/classes/Camera3D.xml +++ b/doc/classes/Camera3D.xml @@ -159,6 +159,9 @@ The [CameraAttributes] to use for this camera. + + The [Compositor] to use for this camera. + The culling mask that describes which [member VisualInstance3D.layers] are rendered by this camera. By default, all 20 user-visible layers are rendered. [b]Note:[/b] Since the [member cull_mask] allows for 32 layers to be stored in total, there are an additional 12 layers that are only used internally by the engine and aren't exposed in the editor. Setting [member cull_mask] using a script allows you to toggle those reserved layers, which can be useful for editor plugins. diff --git a/doc/classes/Compositor.xml b/doc/classes/Compositor.xml new file mode 100644 index 000000000000..51336322a3c5 --- /dev/null +++ b/doc/classes/Compositor.xml @@ -0,0 +1,17 @@ + + + + The compositor resource holds the configuration with which rendering of a viewport can be customised. + + + The compositor resource holds the configuration with which rendering of a viewport can be customised. + [b]Note:[/b] This functionality is still experimental as more customisation of the rendering pipeline will be added in the near future. + + + + + + The custom [CompositorEffect]s that are applied during rendering of viewports using this compositor. + + + diff --git a/doc/classes/CompositorEffect.xml b/doc/classes/CompositorEffect.xml new file mode 100644 index 000000000000..38307e2f1093 --- /dev/null +++ b/doc/classes/CompositorEffect.xml @@ -0,0 +1,85 @@ + + + + This resource allows for creating a custom rendering effect. + + + This resource defines a custom rendering effect that can be applied to [Viewport]s through the viewports' [Environment]. You can implement a callback that is called during rendering at a given stage of the rendering pipeline and allows you to insert additional passes. Note that this callback happens on the rendering thread. + [b]Note:[/b] This functionality is still experimental, there will be changes to the implementation as we expose more of the rendering internals. + + + + + + + + + + Implement this function with your custom rendering code. [param effect_callback_type] should always match the effect callback type you've specified in [member effect_callback_type]. [param render_data] provides access to the rendering state, it is only valid during rendering and should not be stored. + + + + + + If [code]true[/code] and MSAA is enabled, this will trigger a color buffer resolve before the effect is run. + [b]Note:[/b] In [method _render_callback], to access the resolved buffer use: + [codeblock] + var render_scene_buffers : RenderSceneBuffersRD = render_data.get_render_scene_buffers() + var color_buffer = render_scene_buffers.get_texture("render_buffers", "color") + [/codeblock] + + + If [code]true[/code] and MSAA is enabled, this will trigger a depth buffer resolve before the effect is run. + [b]Note:[/b] In [method _render_callback], to access the resolved buffer use: + [codeblock] + var render_scene_buffers : RenderSceneBuffersRD = render_data.get_render_scene_buffers() + var depth_buffer = render_scene_buffers.get_texture("render_buffers", "depth") + [/codeblock] + + + The type of effect that is implemented, determines at what stage of rendering the callback is called. + + + If [code]true[/code] this rendering effect is applied to any viewport it is added to. + + + If [code]true[/code] this triggers motion vectors being calculated during the opaque render state. + [b]Note:[/b] In [method _render_callback], to access the motion vector buffer use: + [codeblock] + var render_scene_buffers : RenderSceneBuffersRD = render_data.get_render_scene_buffers() + var motion_buffer = render_scene_buffers.get_velocity_texture() + [/codeblock] + + + If [code]true[/code] this triggers normal and roughness data to be output during our depth pre-pass, only applicable for the Forward+ renderer. + [b]Note:[/b] In [method _render_callback], to access the roughness buffer use: + [codeblock] + var render_scene_buffers : RenderSceneBuffersRD = render_data.get_render_scene_buffers() + var roughness_buffer = render_scene_buffers.get_texture("forward_clustered", "normal_roughness") + [/codeblock] + + + If [code]true[/code] this triggers specular data being rendered to a separate buffer and combined after effects have been applied, only applicable for the Forward+ renderer. + + + + + The callback is called before our opaque rendering pass, but after depth prepass (if applicable). + + + The callback is called after our opaque rendering pass, but before our sky is rendered. + + + The callback is called after our sky is rendered, but before our back buffers are created (and if enabled, before subsurface scattering and/or screen space reflections). + + + The callback is called before our transparent rendering pass, but after our sky is rendered and we've created our back buffers. + + + The callback is called after our transparent rendering pass, but before any build in post effects and output to our render target. + + + Represents the size of the [enum EffectCallbackType] enum. + + + diff --git a/doc/classes/FramebufferCacheRD.xml b/doc/classes/FramebufferCacheRD.xml new file mode 100644 index 000000000000..f4424311bf4a --- /dev/null +++ b/doc/classes/FramebufferCacheRD.xml @@ -0,0 +1,22 @@ + + + + Framebuffer cache manager for Rendering Device based renderers. + + + Framebuffer cache manager for Rendering Device based renderers. Provides a way to create a framebuffer and reuse it in subsequent calls for as long as the used textures exists. Framebuffers will automatically be cleaned up when dependent objects are freed. + + + + + + + + + + + Creates, or obtains a cached, framebuffer. [param textures] lists textures accessed. [param passes] defines the subpasses and texture allocation, if left empty a single pass is created and textures are allocated depending on their usage flags. [param views] defines the number of views used when rendering. + + + + diff --git a/doc/classes/RenderData.xml b/doc/classes/RenderData.xml new file mode 100644 index 000000000000..065505e6c6ea --- /dev/null +++ b/doc/classes/RenderData.xml @@ -0,0 +1,38 @@ + + + + Abstract render data object, holds frame data related to rendering a single frame of a viewport. + + + Abstract render data object, exists for the duration of rendering a single viewport. + [b]Note:[/b] This is an internal rendering server object, do not instantiate this from script. + + + + + + + + Returns the [RID] of the camera attributes object in the [RenderingServer] being used to render this viewport. + + + + + + Returns the [RID] of the environments object in the [RenderingServer] being used to render this viewport. + + + + + + Returns the [RenderSceneBuffers] object managing the scene buffers for rendering this viewport. + + + + + + Returns the [RenderSceneData] object managing this frames scene data. + + + + diff --git a/doc/classes/RenderDataExtension.xml b/doc/classes/RenderDataExtension.xml new file mode 100644 index 000000000000..9bdab8e10140 --- /dev/null +++ b/doc/classes/RenderDataExtension.xml @@ -0,0 +1,36 @@ + + + + This class allows for a RenderData implementation to be made in GDExtension. + + + This class allows for a RenderData implementation to be made in GDExtension. + + + + + + + + Implement this in GDExtension to return the [RID] for the implementations camera attributes object. + + + + + + + + + + + Implement this in GDExtension to return the [RID] of the implementations environment object. + + + + + + Implement this in GDExtension to return the implementations [RenderSceneDataExtension] object. + + + + diff --git a/doc/classes/RenderDataRD.xml b/doc/classes/RenderDataRD.xml new file mode 100644 index 000000000000..eb32c2964818 --- /dev/null +++ b/doc/classes/RenderDataRD.xml @@ -0,0 +1,13 @@ + + + + Render data implementation for the RenderingDevice based renderers. + [b]Note:[/b] This is an internal rendering server object, do not instantiate this from script. + + + This object manages all render data for the rendering device based renderers. + [b]Note:[/b] This is an internal rendering server object only exposed for GDExtension plugins. + + + + diff --git a/doc/classes/RenderSceneBuffers.xml b/doc/classes/RenderSceneBuffers.xml index b2a5213dba90..1a1c3f413bbd 100644 --- a/doc/classes/RenderSceneBuffers.xml +++ b/doc/classes/RenderSceneBuffers.xml @@ -5,7 +5,7 @@ Abstract scene buffers object, created for each viewport for which 3D rendering is done. It manages any additional buffers used during rendering and will discard buffers when the viewport is resized. - [b]Note:[/b] this is an internal rendering server object only exposed for GDExtension plugins. + [b]Note:[/b] This is an internal rendering server object, do not instantiate this from script. diff --git a/doc/classes/RenderSceneBuffersRD.xml b/doc/classes/RenderSceneBuffersRD.xml index 6ab1e6bbbd3b..359f0b33a821 100644 --- a/doc/classes/RenderSceneBuffersRD.xml +++ b/doc/classes/RenderSceneBuffersRD.xml @@ -1,13 +1,13 @@ - Abstract render scene buffer implementation for the RenderingDevice based renderers. + Render scene buffer implementation for the RenderingDevice based renderers. This object manages all 3D rendering buffers for the rendering device based renderers. An instance of this object is created for every viewport that has 3D rendering enabled. All buffers are organized in [b]contexts[/b]. The default context is called [b]render_buffers[/b] and can contain amongst others the color buffer, depth buffer, velocity buffers, VRS density map and MSAA variants of these buffers. Buffers are only guaranteed to exist during rendering of the viewport. - [b]Note:[/b] this is an internal rendering server object only exposed for GDExtension plugins. + [b]Note:[/b] This is an internal rendering server object, do not instantiate this from script. @@ -58,27 +58,35 @@ + Returns the specified layer from the color texture we are rendering 3D content to. + If [param msaa] is [b]true[/b] and MSAA is enabled, this returns the MSAA variant of the buffer. + Returns the color texture we are rendering 3D content to. If multiview is used this will be a texture array with all views. + If [param msaa] is [b]true[/b] and MSAA is enabled, this returns the MSAA variant of the buffer. + Returns the specified layer from the depth texture we are rendering 3D content to. + If [param msaa] is [b]true[/b] and MSAA is enabled, this returns the MSAA variant of the buffer. + Returns the depth texture we are rendering 3D content to. If multiview is used this will be a texture array with all views. + If [param msaa] is [b]true[/b] and MSAA is enabled, this returns the MSAA variant of the buffer. @@ -87,6 +95,12 @@ Returns the internal size of the render buffer (size before upscaling) with which textures are created by default. + + + + Returns the applied 3D MSAA mode for this viewport. + + @@ -152,14 +166,17 @@ + Returns the specified layer from the velocity texture we are rendering 3D content to. + Returns the velocity texture we are rendering 3D content to. If multiview is used this will be a texture array with all views. + If [param msaa] is [b]true[/b] and MSAA is enabled, this returns the MSAA variant of the buffer. diff --git a/doc/classes/RenderSceneData.xml b/doc/classes/RenderSceneData.xml new file mode 100644 index 000000000000..0ac13ca6d84f --- /dev/null +++ b/doc/classes/RenderSceneData.xml @@ -0,0 +1,55 @@ + + + + Abstract render data object, holds scene data related to rendering a single frame of a viewport. + + + Abstract scene data object, exists for the duration of rendering a single viewport. + [b]Note:[/b] This is an internal rendering server object, do not instantiate this from script. + + + + + + + + Returns the camera projection used to render this frame. + [b]Note:[/b] If more than one view is rendered, this will return a combined projection. + + + + + + Returns the camera transform used to render this frame. + [b]Note:[/b] If more than one view is rendered, this will return a centered transform. + + + + + + Return the [RID] of the uniform buffer containing the scene data as a UBO. + + + + + + Returns the number of views being rendered. + + + + + + + Returns the eye offset per view used to render this frame. This is the offset between our camera transform and the eye transform. + + + + + + + Returns the view projection per view used to render this frame. + [b]Note:[/b] If a single view is rendered, this returns the camera projection. If more than one view is rendered, this will return a projection for the given view including the eye offset. + + + + diff --git a/doc/classes/RenderSceneDataExtension.xml b/doc/classes/RenderSceneDataExtension.xml new file mode 100644 index 000000000000..72eb7fc54dcf --- /dev/null +++ b/doc/classes/RenderSceneDataExtension.xml @@ -0,0 +1,51 @@ + + + + This class allows for a RenderSceneData implementation to be made in GDExtension. + + + This class allows for a RenderSceneData implementation to be made in GDExtension. + + + + + + + + Implement this in GDExtension to return the camera [Projection]. + + + + + + Implement this in GDExtension to return the camera [Transform3D]. + + + + + + Implement this in GDExtension to return the [RID] of the uniform buffer containing the scene data as a UBO. + + + + + + Implement this in GDExtension to return the view count. + + + + + + + Implement this in GDExtension to return the eye offset for the given [param view]. + + + + + + + Implement this in GDExtension to return the view [Projection] for the given [param view]. + + + + diff --git a/doc/classes/RenderSceneDataRD.xml b/doc/classes/RenderSceneDataRD.xml new file mode 100644 index 000000000000..d9a382a982df --- /dev/null +++ b/doc/classes/RenderSceneDataRD.xml @@ -0,0 +1,12 @@ + + + + Render scene data implementation for the RenderingDevice based renderers. + + + Object holds scene data related to rendering a single frame of a viewport. + [b]Note:[/b] This is an internal rendering server object, do not instantiate this from script. + + + + diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 11614b1c2fd5..64cdcc46ae34 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -118,6 +118,14 @@ Sets the camera_attributes created with [method camera_attributes_create] to the given camera. + + + + + + Sets the compositor used by this camera. Equivalent to [member Camera3D.compositor]. + + @@ -918,6 +926,54 @@ Sets the texture [param repeat] mode to use for the canvas texture specified by the [param canvas_texture] RID. + + + + Creates a new compositor and adds it to the RenderingServer. It can be accessed with the RID that is returned. + Once finished with your RID, you will want to free the RID using the RenderingServer's [method free_rid] method. + + + + + + Creates a new rendering effect and adds it to the RenderingServer. It can be accessed with the RID that is returned. + Once finished with your RID, you will want to free the RID using the RenderingServer's [method free_rid] method. + + + + + + + + + Sets the callback type ([param callback_type]) and callback method([param callback]) for this rendering effect. + + + + + + + + Enables/disables this rendering effect. + + + + + + + + + Sets the flag ([param flag]) for this rendering effect to [code]true[/code] or [code]false[/code] ([param set]). + + + + + + + + Sets the compositor effects for the specified compositor RID. [param effects] should be an array containing RIDs created with [method compositor_effect_create]. + + @@ -3016,6 +3072,14 @@ Sets the camera attributes ([param effects]) that will be used with this scenario. See also [CameraAttributes]. + + + + + + Sets the compositor ([param compositor]) that will be used with this scenario. See also [Compositor]. + + @@ -4833,6 +4897,38 @@ Uses the fast filtering algorithm to process the radiance map. In general this results in lower quality, but substantially faster run times. If you need better quality, but still need to update the sky every frame, consider turning on [member ProjectSettings.rendering/reflections/sky_reflections/fast_filter_high_quality]. [b]Note:[/b] The fast filtering algorithm is limited to 256×256 cubemaps, so [method sky_set_radiance_size] must be set to [code]256[/code]. Otherwise, a warning is printed and the overridden radiance size is ignored. + + The rendering effect requires the color buffer to be resolved if MSAA is enabled. + + + The rendering effect requires the depth buffer to be resolved if MSAA is enabled. + + + The rendering effect requires motion vectors to be produced. + + + The rendering effect requires normals and roughness g-buffer to be produced (Forward+ only). + + + The rendering effect requires specular data to be separated out (Forward+ only). + + + The callback is called before our opaque rendering pass, but after depth prepass (if applicable). + + + The callback is called after our opaque rendering pass, but before our sky is rendered. + + + The callback is called after our sky is rendered, but before our back buffers are created (and if enabled, before subsurface scattering and/or screen space reflections). + + + The callback is called before our transparent rendering pass, but after our sky is rendered and we've created our back buffers. + + + The callback is called after our transparent rendering pass, but before any build in post effects and output to our render target. + + + Use the clear color as background. diff --git a/doc/classes/UniformSetCacheRD.xml b/doc/classes/UniformSetCacheRD.xml new file mode 100644 index 000000000000..32e516c295e8 --- /dev/null +++ b/doc/classes/UniformSetCacheRD.xml @@ -0,0 +1,22 @@ + + + + Uniform set cache manager for Rendering Device based renderers. + + + Uniform set cache manager for Rendering Device based renderers. Provides a way to create a uniform set and reuse it in subsequent calls for as long as the uniform set exists. Uniform set will automatically be cleaned up when dependent objects are freed. + + + + + + + + + + + Creates/returns a cached uniform set based on the provided uniforms for a given shader. + + + + diff --git a/doc/classes/WorldEnvironment.xml b/doc/classes/WorldEnvironment.xml index bceb91ab6870..27b07821b1fb 100644 --- a/doc/classes/WorldEnvironment.xml +++ b/doc/classes/WorldEnvironment.xml @@ -18,6 +18,9 @@ The default [CameraAttributes] resource to use if none set on the [Camera3D]. + + The default [Compositor] resource to use if none set on the [Camera3D]. + The [Environment] resource used by this [WorldEnvironment], defining the default properties. diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index efd554eac9fe..9d9af978ebab 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -2310,7 +2310,7 @@ void RasterizerSceneGLES3::_render_shadow_pass(RID p_light, RID p_shadow_atlas, glBindFramebuffer(GL_FRAMEBUFFER, 0); } -void RasterizerSceneGLES3::render_scene(const Ref &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, 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, const PagedArray &p_fog_volumes, RID p_environment, RID p_camera_attributes, 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_mesh_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, RenderingMethod::RenderInfo *r_render_info) { +void RasterizerSceneGLES3::render_scene(const Ref &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, 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, const PagedArray &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_compositor, 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_mesh_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, RenderingMethod::RenderInfo *r_render_info) { GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); GLES3::Config *config = GLES3::Config::get_singleton(); RENDER_TIMESTAMP("Setup 3D Scene"); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index ed59aba266fb..49324ecff015 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -737,7 +737,7 @@ class RasterizerSceneGLES3 : public RendererSceneRender { void voxel_gi_set_quality(RS::VoxelGIQuality) override; - void render_scene(const Ref &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, 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, const PagedArray &p_fog_volumes, RID p_environment, RID p_camera_attributes, 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_mesh_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, RenderingMethod::RenderInfo *r_render_info = nullptr) override; + void render_scene(const Ref &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, 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, const PagedArray &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_compositor, 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_mesh_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, RenderingMethod::RenderInfo *r_render_info = nullptr) override; void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, 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; diff --git a/misc/extension_api_validation/4.2-stable.expected b/misc/extension_api_validation/4.2-stable.expected index b8010662044b..1bb1bdcd709b 100644 --- a/misc/extension_api_validation/4.2-stable.expected +++ b/misc/extension_api_validation/4.2-stable.expected @@ -147,3 +147,16 @@ GH-84792 Validate extension JSON: Error: Field 'classes/RenderingServer/methods/environment_set_fog/arguments': size changed value in new API, from 10 to 11. Added fog mode argument. Compatibility method registered. + + +GH-80214 +-------- + +Validate extension JSON: Error: Field 'classes/RenderSceneBuffersRD/methods/get_color_layer/arguments': size changed value in new API, from 1 to 2. +Validate extension JSON: Error: Field 'classes/RenderSceneBuffersRD/methods/get_depth_layer/arguments': size changed value in new API, from 1 to 2. +Validate extension JSON: Error: Field 'classes/RenderSceneBuffersRD/methods/get_velocity_layer/arguments': size changed value in new API, from 1 to 2. +Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/RenderSceneBuffersRD/methods/get_color_texture': arguments +Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/RenderSceneBuffersRD/methods/get_depth_texture': arguments +Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/RenderSceneBuffersRD/methods/get_velocity_texture': arguments + +MSAA flag was added, compatibility functions exist for these. diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index d27233289af0..a44aa54c17fa 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -465,6 +465,20 @@ void Camera3D::_attributes_changed() { _update_camera_mode(); } +void Camera3D::set_compositor(const Ref &p_compositor) { + compositor = p_compositor; + if (compositor.is_valid()) { + RS::get_singleton()->camera_set_compositor(camera, compositor->get_rid()); + } else { + RS::get_singleton()->camera_set_compositor(camera, RID()); + } + _update_camera_mode(); +} + +Ref Camera3D::get_compositor() const { + return compositor; +} + void Camera3D::set_keep_aspect_mode(KeepAspect p_aspect) { keep_aspect = p_aspect; RenderingServer::get_singleton()->camera_set_use_vertical_aspect(camera, p_aspect == KEEP_WIDTH); @@ -533,6 +547,8 @@ void Camera3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_environment"), &Camera3D::get_environment); ClassDB::bind_method(D_METHOD("set_attributes", "env"), &Camera3D::set_attributes); ClassDB::bind_method(D_METHOD("get_attributes"), &Camera3D::get_attributes); + ClassDB::bind_method(D_METHOD("set_compositor", "compositor"), &Camera3D::set_compositor); + ClassDB::bind_method(D_METHOD("get_compositor"), &Camera3D::get_compositor); ClassDB::bind_method(D_METHOD("set_keep_aspect_mode", "mode"), &Camera3D::set_keep_aspect_mode); ClassDB::bind_method(D_METHOD("get_keep_aspect_mode"), &Camera3D::get_keep_aspect_mode); ClassDB::bind_method(D_METHOD("set_doppler_tracking", "mode"), &Camera3D::set_doppler_tracking); @@ -551,6 +567,7 @@ void Camera3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_environment", "get_environment"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "attributes", PROPERTY_HINT_RESOURCE_TYPE, "CameraAttributesPractical,CameraAttributesPhysical"), "set_attributes", "get_attributes"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "compositor", PROPERTY_HINT_RESOURCE_TYPE, "Compositor"), "set_compositor", "get_compositor"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "h_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_h_offset", "get_h_offset"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "v_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_v_offset", "get_v_offset"); ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Physics"), "set_doppler_tracking", "get_doppler_tracking"); diff --git a/scene/3d/camera_3d.h b/scene/3d/camera_3d.h index b32eb147c106..dbf2ffc1dd06 100644 --- a/scene/3d/camera_3d.h +++ b/scene/3d/camera_3d.h @@ -34,6 +34,7 @@ #include "scene/3d/node_3d.h" #include "scene/3d/velocity_tracker_3d.h" #include "scene/resources/camera_attributes.h" +#include "scene/resources/compositor.h" #include "scene/resources/environment.h" class Camera3D : public Node3D { @@ -83,6 +84,7 @@ class Camera3D : public Node3D { Ref environment; Ref attributes; + Ref compositor; void _attributes_changed(); // void _camera_make_current(Node *p_camera); @@ -167,6 +169,9 @@ class Camera3D : public Node3D { void set_attributes(const Ref &p_effects); Ref get_attributes() const; + void set_compositor(const Ref &p_compositor); + Ref get_compositor() const; + void set_keep_aspect_mode(KeepAspect p_aspect); KeepAspect get_keep_aspect_mode() const; diff --git a/scene/3d/world_environment.cpp b/scene/3d/world_environment.cpp index 4687c8473483..82b7c160a4cc 100644 --- a/scene/3d/world_environment.cpp +++ b/scene/3d/world_environment.cpp @@ -46,6 +46,11 @@ void WorldEnvironment::_notification(int p_what) { add_to_group("_world_camera_attributes_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); _update_current_camera_attributes(); } + + if (compositor.is_valid()) { + add_to_group("_world_compositor_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); + _update_current_compositor(); + } } break; case Node3D::NOTIFICATION_EXIT_WORLD: @@ -59,6 +64,11 @@ void WorldEnvironment::_notification(int p_what) { remove_from_group("_world_camera_attributes_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); _update_current_camera_attributes(); } + + if (compositor.is_valid()) { + remove_from_group("_world_compositor_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); + _update_current_compositor(); + } } break; } } @@ -85,6 +95,17 @@ void WorldEnvironment::_update_current_camera_attributes() { get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, "_world_camera_attributes_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warnings"); } +void WorldEnvironment::_update_current_compositor() { + WorldEnvironment *first = Object::cast_to(get_tree()->get_first_node_in_group("_world_compositor_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()))); + if (first) { + get_viewport()->find_world_3d()->set_compositor(first->compositor); + } else { + get_viewport()->find_world_3d()->set_compositor(Ref()); + } + + get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, "_world_compositor_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warnings"); +} + void WorldEnvironment::set_environment(const Ref &p_environment) { if (environment == p_environment) { return; @@ -135,6 +156,31 @@ Ref WorldEnvironment::get_camera_attributes() const { return camera_attributes; } +void WorldEnvironment::set_compositor(const Ref &p_compositor) { + if (compositor == p_compositor) { + return; + } + if (is_inside_tree() && compositor.is_valid()) { + remove_from_group("_world_compositor_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); + } + + compositor = p_compositor; + + if (is_inside_tree() && compositor.is_valid()) { + add_to_group("_world_compositor_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); + } + + if (is_inside_tree()) { + _update_current_compositor(); + } else { + update_configuration_warnings(); + } +} + +Ref WorldEnvironment::get_compositor() const { + return compositor; +} + PackedStringArray WorldEnvironment::get_configuration_warnings() const { PackedStringArray warnings = Node::get_configuration_warnings(); @@ -154,6 +200,10 @@ PackedStringArray WorldEnvironment::get_configuration_warnings() const { warnings.push_back(RTR("Only one WorldEnvironment is allowed per scene (or set of instantiated scenes).")); } + if (compositor.is_valid() && get_viewport()->find_world_3d()->get_compositor() != compositor) { + warnings.push_back(("Only the first Compositor has an effect in a scene (or set of instantiated scenes).")); + } + return warnings; } @@ -165,6 +215,10 @@ void WorldEnvironment::_bind_methods() { ClassDB::bind_method(D_METHOD("set_camera_attributes", "camera_attributes"), &WorldEnvironment::set_camera_attributes); ClassDB::bind_method(D_METHOD("get_camera_attributes"), &WorldEnvironment::get_camera_attributes); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_attributes", PROPERTY_HINT_RESOURCE_TYPE, "CameraAttributesPractical,CameraAttributesPhysical"), "set_camera_attributes", "get_camera_attributes"); + + ClassDB::bind_method(D_METHOD("set_compositor", "compositor"), &WorldEnvironment::set_compositor); + ClassDB::bind_method(D_METHOD("get_compositor"), &WorldEnvironment::get_compositor); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "compositor", PROPERTY_HINT_RESOURCE_TYPE, "Compositor"), "set_compositor", "get_compositor"); } WorldEnvironment::WorldEnvironment() { diff --git a/scene/3d/world_environment.h b/scene/3d/world_environment.h index 2809d2550aeb..53a695d7de4f 100644 --- a/scene/3d/world_environment.h +++ b/scene/3d/world_environment.h @@ -33,6 +33,7 @@ #include "scene/main/node.h" #include "scene/resources/camera_attributes.h" +#include "scene/resources/compositor.h" #include "scene/resources/environment.h" class WorldEnvironment : public Node { @@ -40,9 +41,11 @@ class WorldEnvironment : public Node { Ref environment; Ref camera_attributes; + Ref compositor; void _update_current_environment(); void _update_current_camera_attributes(); + void _update_current_compositor(); protected: void _notification(int p_what); @@ -55,6 +58,9 @@ class WorldEnvironment : public Node { void set_camera_attributes(const Ref &p_camera_attributes); Ref get_camera_attributes() const; + void set_compositor(const Ref &p_compositor); + Ref get_compositor() const; + PackedStringArray get_configuration_warnings() const override; WorldEnvironment(); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index d7e5eb469884..4aa1bebb9c71 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -153,6 +153,7 @@ #include "scene/resources/capsule_shape_2d.h" #include "scene/resources/capsule_shape_3d.h" #include "scene/resources/circle_shape_2d.h" +#include "scene/resources/compositor.h" #include "scene/resources/compressed_texture.h" #include "scene/resources/concave_polygon_shape_2d.h" #include "scene/resources/concave_polygon_shape_3d.h" @@ -341,6 +342,8 @@ void register_scene_types() { GDREGISTER_CLASS(SubViewport); GDREGISTER_CLASS(ViewportTexture); + GDREGISTER_VIRTUAL_CLASS(CompositorEffect); + GDREGISTER_ABSTRACT_CLASS(MultiplayerPeer); GDREGISTER_CLASS(MultiplayerPeerExtension); GDREGISTER_ABSTRACT_CLASS(MultiplayerAPI); @@ -865,6 +868,7 @@ void register_scene_types() { GDREGISTER_CLASS(PhysicsMaterial); GDREGISTER_CLASS(World3D); + GDREGISTER_CLASS(Compositor); GDREGISTER_CLASS(Environment); GDREGISTER_VIRTUAL_CLASS(CameraAttributes); GDREGISTER_CLASS(CameraAttributesPhysical); diff --git a/scene/resources/compositor.cpp b/scene/resources/compositor.cpp new file mode 100644 index 000000000000..60b7ed0563fa --- /dev/null +++ b/scene/resources/compositor.cpp @@ -0,0 +1,250 @@ +/**************************************************************************/ +/* compositor.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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 "compositor.h" + +#include "servers/rendering_server.h" + +/* Compositor Effect */ + +void CompositorEffect::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &CompositorEffect::set_enabled); + ClassDB::bind_method(D_METHOD("get_enabled"), &CompositorEffect::get_enabled); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "get_enabled"); + + ClassDB::bind_method(D_METHOD("set_effect_callback_type", "effect_callback_type"), &CompositorEffect::set_effect_callback_type); + ClassDB::bind_method(D_METHOD("get_effect_callback_type"), &CompositorEffect::get_effect_callback_type); + ADD_PROPERTY(PropertyInfo(Variant::INT, "effect_callback_type", PROPERTY_HINT_ENUM, "Pre Opaque,Post Opaque,Post Sky,Pre Transparent,Post Transparent"), "set_effect_callback_type", "get_effect_callback_type"); + + ClassDB::bind_method(D_METHOD("set_access_resolved_color", "enable"), &CompositorEffect::set_access_resolved_color); + ClassDB::bind_method(D_METHOD("get_access_resolved_color"), &CompositorEffect::get_access_resolved_color); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "access_resolved_color"), "set_access_resolved_color", "get_access_resolved_color"); + + ClassDB::bind_method(D_METHOD("set_access_resolved_depth", "enable"), &CompositorEffect::set_access_resolved_depth); + ClassDB::bind_method(D_METHOD("get_access_resolved_depth"), &CompositorEffect::get_access_resolved_depth); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "access_resolved_depth"), "set_access_resolved_depth", "get_access_resolved_depth"); + + ClassDB::bind_method(D_METHOD("set_needs_motion_vectors", "enable"), &CompositorEffect::set_needs_motion_vectors); + ClassDB::bind_method(D_METHOD("get_needs_motion_vectors"), &CompositorEffect::get_needs_motion_vectors); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "needs_motion_vectors"), "set_needs_motion_vectors", "get_needs_motion_vectors"); + + ClassDB::bind_method(D_METHOD("set_needs_normal_roughness", "enable"), &CompositorEffect::set_needs_normal_roughness); + ClassDB::bind_method(D_METHOD("get_needs_normal_roughness"), &CompositorEffect::get_needs_normal_roughness); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "needs_normal_roughness"), "set_needs_normal_roughness", "get_needs_normal_roughness"); + + ClassDB::bind_method(D_METHOD("set_needs_separate_specular", "enable"), &CompositorEffect::set_needs_separate_specular); + ClassDB::bind_method(D_METHOD("get_needs_separate_specular"), &CompositorEffect::get_needs_separate_specular); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "needs_separate_specular"), "set_needs_separate_specular", "get_needs_separate_specular"); + + BIND_ENUM_CONSTANT(EFFECT_CALLBACK_TYPE_PRE_OPAQUE) + BIND_ENUM_CONSTANT(EFFECT_CALLBACK_TYPE_POST_OPAQUE) + BIND_ENUM_CONSTANT(EFFECT_CALLBACK_TYPE_POST_SKY) + BIND_ENUM_CONSTANT(EFFECT_CALLBACK_TYPE_PRE_TRANSPARENT) + BIND_ENUM_CONSTANT(EFFECT_CALLBACK_TYPE_POST_TRANSPARENT) + BIND_ENUM_CONSTANT(EFFECT_CALLBACK_TYPE_MAX) + + GDVIRTUAL_BIND(_render_callback, "effect_callback_type", "render_data"); +} + +void CompositorEffect::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "access_resolved_color" && effect_callback_type == EFFECT_CALLBACK_TYPE_POST_TRANSPARENT) { + p_property.usage = PROPERTY_USAGE_NONE; + } + if (p_property.name == "access_resolved_depth" && effect_callback_type == EFFECT_CALLBACK_TYPE_POST_TRANSPARENT) { + p_property.usage = PROPERTY_USAGE_NONE; + } + if (p_property.name == "needs_separate_specular" && effect_callback_type != EFFECT_CALLBACK_TYPE_POST_SKY) { + p_property.usage = PROPERTY_USAGE_NONE; + } +} + +void CompositorEffect::set_enabled(bool p_enabled) { + enabled = p_enabled; + if (rid.is_valid()) { + RenderingServer *rs = RenderingServer::get_singleton(); + ERR_FAIL_NULL(rs); + rs->compositor_effect_set_enabled(rid, enabled); + } +} + +bool CompositorEffect::get_enabled() const { + return enabled; +} + +void CompositorEffect::set_effect_callback_type(EffectCallbackType p_callback_type) { + effect_callback_type = p_callback_type; + notify_property_list_changed(); + + if (rid.is_valid()) { + RenderingServer *rs = RenderingServer::get_singleton(); + ERR_FAIL_NULL(rs); + rs->compositor_effect_set_callback(rid, RenderingServer::CompositorEffectCallbackType(effect_callback_type), Callable(this, "_render_callback")); + } +} + +CompositorEffect::EffectCallbackType CompositorEffect::get_effect_callback_type() const { + return effect_callback_type; +} + +void CompositorEffect::set_access_resolved_color(bool p_enabled) { + access_resolved_color = p_enabled; + if (rid.is_valid()) { + RenderingServer *rs = RenderingServer::get_singleton(); + ERR_FAIL_NULL(rs); + rs->compositor_effect_set_flag(rid, RS::CompositorEffectFlags::COMPOSITOR_EFFECT_FLAG_ACCESS_RESOLVED_COLOR, access_resolved_color); + } +} + +bool CompositorEffect::get_access_resolved_color() const { + return access_resolved_color; +} + +void CompositorEffect::set_access_resolved_depth(bool p_enabled) { + access_resolved_depth = p_enabled; + if (rid.is_valid()) { + RenderingServer *rs = RenderingServer::get_singleton(); + ERR_FAIL_NULL(rs); + rs->compositor_effect_set_flag(rid, RS::CompositorEffectFlags::COMPOSITOR_EFFECT_FLAG_ACCESS_RESOLVED_DEPTH, access_resolved_depth); + } +} + +bool CompositorEffect::get_access_resolved_depth() const { + return access_resolved_depth; +} + +void CompositorEffect::set_needs_motion_vectors(bool p_enabled) { + needs_motion_vectors = p_enabled; + if (rid.is_valid()) { + RenderingServer *rs = RenderingServer::get_singleton(); + ERR_FAIL_NULL(rs); + rs->compositor_effect_set_flag(rid, RS::CompositorEffectFlags::COMPOSITOR_EFFECT_FLAG_NEEDS_MOTION_VECTORS, needs_motion_vectors); + } +} + +bool CompositorEffect::get_needs_motion_vectors() const { + return needs_motion_vectors; +} + +void CompositorEffect::set_needs_normal_roughness(bool p_enabled) { + needs_normal_roughness = p_enabled; + if (rid.is_valid()) { + RenderingServer *rs = RenderingServer::get_singleton(); + ERR_FAIL_NULL(rs); + rs->compositor_effect_set_flag(rid, RS::CompositorEffectFlags::COMPOSITOR_EFFECT_FLAG_NEEDS_ROUGHNESS, needs_normal_roughness); + } +} + +bool CompositorEffect::get_needs_normal_roughness() const { + return needs_normal_roughness; +} + +void CompositorEffect::set_needs_separate_specular(bool p_enabled) { + needs_separate_specular = p_enabled; + if (rid.is_valid()) { + RenderingServer *rs = RenderingServer::get_singleton(); + ERR_FAIL_NULL(rs); + rs->compositor_effect_set_flag(rid, RS::CompositorEffectFlags::COMPOSITOR_EFFECT_FLAG_NEEDS_SEPARATE_SPECULAR, needs_separate_specular); + } +} + +bool CompositorEffect::get_needs_separate_specular() const { + return needs_separate_specular; +} + +CompositorEffect::CompositorEffect() { + RenderingServer *rs = RenderingServer::get_singleton(); + if (rs != nullptr) { + rid = rs->compositor_effect_create(); + rs->compositor_effect_set_callback(rid, RenderingServer::CompositorEffectCallbackType(effect_callback_type), Callable(this, "_render_callback")); + } +} + +CompositorEffect::~CompositorEffect() { + RenderingServer *rs = RenderingServer::get_singleton(); + if (rs != nullptr && rid.is_valid()) { + rs->free(rid); + } +} + +/* Compositor */ + +void Compositor::_bind_methods() { + // compositor effects + ClassDB::bind_method(D_METHOD("set_compositor_effects", "compositor_effects"), &Compositor::set_compositor_effects); + ClassDB::bind_method(D_METHOD("get_compositor_effects"), &Compositor::get_compositor_effects); + + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "compositor_effects", PROPERTY_HINT_ARRAY_TYPE, MAKE_RESOURCE_TYPE_HINT("CompositorEffect")), "set_compositor_effects", "get_compositor_effects"); +} + +Compositor::Compositor() { + RenderingServer *rs = RenderingServer::get_singleton(); + if (rs != nullptr) { + compositor = rs->compositor_create(); + } +} + +Compositor::~Compositor() { + RenderingServer *rs = RenderingServer::get_singleton(); + if (rs != nullptr && compositor.is_valid()) { + rs->free(compositor); + } +} + +// Compositor effects +void Compositor::set_compositor_effects(const TypedArray &p_compositor_effects) { + Array effect_rids; + effects.clear(); + + for (int i = 0; i < p_compositor_effects.size(); i++) { + // Cast to proper ref, if our object isn't a CompositorEffect resource this will be an empty Ref. + Ref compositor_effect = p_compositor_effects[i]; + + // We add the effect even if this is an empty Ref, this allows the UI to add new entries. + effects.push_back(compositor_effect); + + // But we only add a rid for valid Refs + if (compositor_effect.is_valid()) { + RID rid = compositor_effect->get_rid(); + effect_rids.push_back(rid); + } + } + + RenderingServer::get_singleton()->compositor_set_compositor_effects(compositor, effect_rids); +} + +TypedArray Compositor::get_compositor_effects() const { + TypedArray arr; + + for (uint32_t i = 0; i < effects.size(); i++) { + arr.push_back(effects[i]); + } + + return arr; +} diff --git a/scene/resources/compositor.h b/scene/resources/compositor.h new file mode 100644 index 000000000000..ff840c88789f --- /dev/null +++ b/scene/resources/compositor.h @@ -0,0 +1,125 @@ +/**************************************************************************/ +/* compositor.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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 COMPOSITOR_H +#define COMPOSITOR_H + +#include "core/io/resource.h" +#include "core/object/gdvirtual.gen.inc" +#include "servers/rendering/storage/render_data.h" + +/* Compositor Effect */ + +class CompositorEffect : public Resource { + GDCLASS(CompositorEffect, Resource); + +public: + enum EffectCallbackType { + EFFECT_CALLBACK_TYPE_PRE_OPAQUE, + EFFECT_CALLBACK_TYPE_POST_OPAQUE, + EFFECT_CALLBACK_TYPE_POST_SKY, + EFFECT_CALLBACK_TYPE_PRE_TRANSPARENT, + EFFECT_CALLBACK_TYPE_POST_TRANSPARENT, + EFFECT_CALLBACK_TYPE_MAX + }; + +private: + RID rid; + bool enabled = true; + EffectCallbackType effect_callback_type = EFFECT_CALLBACK_TYPE_POST_TRANSPARENT; + + bool access_resolved_color = false; + bool access_resolved_depth = false; + bool needs_motion_vectors = false; + bool needs_normal_roughness = false; + bool needs_separate_specular = false; + +protected: + static void _bind_methods(); + void _validate_property(PropertyInfo &p_property) const; + + GDVIRTUAL2(_render_callback, int, const RenderData *) + +public: + virtual RID get_rid() const override { return rid; } + + void set_enabled(bool p_enabled); + bool get_enabled() const; + + void set_effect_callback_type(EffectCallbackType p_callback_type); + EffectCallbackType get_effect_callback_type() const; + + void set_access_resolved_color(bool p_enabled); + bool get_access_resolved_color() const; + + void set_access_resolved_depth(bool p_enabled); + bool get_access_resolved_depth() const; + + void set_needs_motion_vectors(bool p_enabled); + bool get_needs_motion_vectors() const; + + void set_needs_normal_roughness(bool p_enabled); + bool get_needs_normal_roughness() const; + + void set_needs_separate_specular(bool p_enabled); + bool get_needs_separate_specular() const; + + CompositorEffect(); + ~CompositorEffect(); +}; + +VARIANT_ENUM_CAST(CompositorEffect::EffectCallbackType) + +/* Compositor */ + +class Compositor : public Resource { + GDCLASS(Compositor, Resource); + +private: + RID compositor; + + // Compositor effects + LocalVector> effects; + +protected: + static void _bind_methods(); + +public: + virtual RID get_rid() const override { return compositor; } + + Compositor(); + ~Compositor(); + + // Compositor effects + void set_compositor_effects(const TypedArray &p_compositor_effects); + TypedArray get_compositor_effects() const; +}; + +#endif // COMPOSITOR_H diff --git a/scene/resources/world_3d.cpp b/scene/resources/world_3d.cpp index 81e261d6b794..bf91b1eb3387 100644 --- a/scene/resources/world_3d.cpp +++ b/scene/resources/world_3d.cpp @@ -132,6 +132,19 @@ Ref World3D::get_camera_attributes() const { return camera_attributes; } +void World3D::set_compositor(const Ref &p_compositor) { + compositor = p_compositor; + if (compositor.is_valid()) { + RS::get_singleton()->scenario_set_compositor(scenario, compositor->get_rid()); + } else { + RS::get_singleton()->scenario_set_compositor(scenario, RID()); + } +} + +Ref World3D::get_compositor() const { + return compositor; +} + PhysicsDirectSpaceState3D *World3D::get_direct_space_state() { return PhysicsServer3D::get_singleton()->space_get_direct_state(get_space()); } diff --git a/scene/resources/world_3d.h b/scene/resources/world_3d.h index 518fff64e20a..06b06aea98d8 100644 --- a/scene/resources/world_3d.h +++ b/scene/resources/world_3d.h @@ -32,6 +32,7 @@ #define WORLD_3D_H #include "core/io/resource.h" +#include "scene/resources/compositor.h" #include "scene/resources/environment.h" #include "servers/physics_server_3d.h" #include "servers/rendering_server.h" @@ -52,6 +53,7 @@ class World3D : public Resource { Ref environment; Ref fallback_environment; Ref camera_attributes; + Ref compositor; HashSet cameras; @@ -77,6 +79,9 @@ class World3D : public Resource { void set_camera_attributes(const Ref &p_camera_attributes); Ref get_camera_attributes() const; + void set_compositor(const Ref &p_compositor); + Ref get_compositor() const; + _FORCE_INLINE_ const HashSet &get_cameras() const { return cameras; } PhysicsDirectSpaceState3D *get_direct_space_state(); diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index 0ee2984a8cae..c4f93d27c157 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -69,10 +69,16 @@ #include "physics_server_3d.h" #include "physics_server_3d_wrap_mt.h" #include "rendering/renderer_compositor.h" +#include "rendering/renderer_rd/framebuffer_cache_rd.h" +#include "rendering/renderer_rd/storage_rd/render_data_rd.h" #include "rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h" +#include "rendering/renderer_rd/storage_rd/render_scene_data_rd.h" +#include "rendering/renderer_rd/uniform_set_cache_rd.h" #include "rendering/rendering_device.h" #include "rendering/rendering_device_binds.h" +#include "rendering/storage/render_data.h" #include "rendering/storage/render_scene_buffers.h" +#include "rendering/storage/render_scene_data.h" #include "rendering_server.h" #include "servers/extensions/physics_server_2d_extension.h" #include "servers/extensions/physics_server_3d_extension.h" @@ -259,10 +265,21 @@ void register_server_types() { GDREGISTER_CLASS(RDShaderFile); GDREGISTER_CLASS(RDPipelineSpecializationConstant); + GDREGISTER_ABSTRACT_CLASS(RenderData); + GDREGISTER_CLASS(RenderDataExtension); + GDREGISTER_CLASS(RenderDataRD); + + GDREGISTER_ABSTRACT_CLASS(RenderSceneData); + GDREGISTER_CLASS(RenderSceneDataExtension); + GDREGISTER_CLASS(RenderSceneDataRD); + GDREGISTER_CLASS(RenderSceneBuffersConfiguration); GDREGISTER_ABSTRACT_CLASS(RenderSceneBuffers); GDREGISTER_CLASS(RenderSceneBuffersExtension); - GDREGISTER_ABSTRACT_CLASS(RenderSceneBuffersRD); + GDREGISTER_CLASS(RenderSceneBuffersRD); + + GDREGISTER_CLASS(FramebufferCacheRD); + GDREGISTER_CLASS(UniformSetCacheRD); GDREGISTER_CLASS(CameraFeed); diff --git a/servers/rendering/dummy/rasterizer_scene_dummy.h b/servers/rendering/dummy/rasterizer_scene_dummy.h index fdf8df7587ba..083493003f0b 100644 --- a/servers/rendering/dummy/rasterizer_scene_dummy.h +++ b/servers/rendering/dummy/rasterizer_scene_dummy.h @@ -145,7 +145,7 @@ class RasterizerSceneDummy : public RendererSceneRender { void voxel_gi_set_quality(RS::VoxelGIQuality) override {} - void render_scene(const Ref &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, 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, const PagedArray &p_fog_volumes, RID p_environment, RID p_camera_attributes, 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_mesh_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, RenderingMethod::RenderInfo *r_info = nullptr) override {} + void render_scene(const Ref &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, 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, const PagedArray &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_compositor, 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_mesh_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, RenderingMethod::RenderInfo *r_info = nullptr) override {} void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, 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 {} @@ -168,6 +168,12 @@ class RasterizerSceneDummy : public RendererSceneRender { if (is_environment(p_rid)) { environment_free(p_rid); return true; + } else if (is_compositor(p_rid)) { + compositor_free(p_rid); + return true; + } else if (is_compositor_effect(p_rid)) { + compositor_effect_free(p_rid); + return true; } else if (RSG::camera_attributes->owns_camera_attributes(p_rid)) { RSG::camera_attributes->camera_attributes_free(p_rid); return true; diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h index 011493f1f6e6..6169d386b53e 100644 --- a/servers/rendering/renderer_rd/environment/gi.h +++ b/servers/rendering/renderer_rd/environment/gi.h @@ -56,7 +56,7 @@ #define RB_TEX_REFLECTION SNAME("reflection") // Forward declare RenderDataRD and RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound -struct RenderDataRD; +class RenderDataRD; class RendererSceneRenderRD; namespace RendererRD { 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 c454d35d2858..fa6e78750bc7 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -67,7 +67,7 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular() void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_normal_roughness_texture() { ERR_FAIL_NULL(render_buffers); - if (!render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS)) { + if (!render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_NORMAL_ROUGHNESS)) { RD::DataFormat format = RD::DATA_FORMAT_R8G8B8A8_UNORM; uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; @@ -77,11 +77,11 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_normal_rou usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; } - render_buffers->create_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS, format, usage_bits); + render_buffers->create_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_NORMAL_ROUGHNESS, format, usage_bits); if (render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; - render_buffers->create_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS_MSAA, format, usage_bits, render_buffers->get_texture_samples()); + render_buffers->create_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_NORMAL_ROUGHNESS_MSAA, format, usage_bits, render_buffers->get_texture_samples()); } } } @@ -214,7 +214,7 @@ RID RenderForwardClustered::RenderBufferDataForwardClustered::get_depth_fb(Depth case DEPTH_FB_ROUGHNESS: { ensure_normal_roughness_texture(); - RID normal_roughness_buffer = render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, use_msaa ? RB_TEX_ROUGHNESS_MSAA : RB_TEX_ROUGHNESS); + RID normal_roughness_buffer = render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, use_msaa ? RB_TEX_NORMAL_ROUGHNESS_MSAA : RB_TEX_NORMAL_ROUGHNESS); return FramebufferCacheRD::get_singleton()->get_cache_multiview(render_buffers->get_view_count(), depth, normal_roughness_buffer); } break; @@ -222,7 +222,7 @@ RID RenderForwardClustered::RenderBufferDataForwardClustered::get_depth_fb(Depth ensure_normal_roughness_texture(); ensure_voxelgi(); - RID normal_roughness_buffer = render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, use_msaa ? RB_TEX_ROUGHNESS_MSAA : RB_TEX_ROUGHNESS); + RID normal_roughness_buffer = render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, use_msaa ? RB_TEX_NORMAL_ROUGHNESS_MSAA : RB_TEX_NORMAL_ROUGHNESS); RID voxelgi_buffer = render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, use_msaa ? RB_TEX_VOXEL_GI_MSAA : RB_TEX_VOXEL_GI); return FramebufferCacheRD::get_singleton()->get_cache_multiview(render_buffers->get_view_count(), depth, normal_roughness_buffer, voxelgi_buffer); @@ -1578,6 +1578,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RENDER_TIMESTAMP("Prepare 3D Scene"); + // get info about our rendering effects + bool ce_needs_motion_vectors = _compositor_effects_has_flag(p_render_data, RS::COMPOSITOR_EFFECT_FLAG_NEEDS_MOTION_VECTORS); + bool ce_needs_normal_roughness = _compositor_effects_has_flag(p_render_data, RS::COMPOSITOR_EFFECT_FLAG_NEEDS_ROUGHNESS); + bool ce_needs_separate_specular = _compositor_effects_has_flag(p_render_data, RS::COMPOSITOR_EFFECT_FLAG_NEEDS_SEPARATE_SPECULAR); + // sdfgi first _update_sdfgi(p_render_data); @@ -1632,6 +1637,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool motion_vectors_required; if (using_debug_mvs) { motion_vectors_required = true; + } else if (ce_needs_motion_vectors) { + motion_vectors_required = true; } else if (!is_reflection_probe && using_taa) { motion_vectors_required = true; } else if (!is_reflection_probe && using_fsr2) { @@ -1738,10 +1745,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co if (using_voxelgi) { depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI; } else if (p_render_data->environment.is_valid()) { - if (environment_get_ssr_enabled(p_render_data->environment) || - environment_get_sdfgi_enabled(p_render_data->environment) || + if (using_ssr || + using_sdfgi || environment_get_ssao_enabled(p_render_data->environment) || using_ssil || + ce_needs_normal_roughness || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER || scene_state.used_normal_texture) { depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS; @@ -1770,7 +1778,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool using_sss = rb_data.is_valid() && !is_reflection_probe && scene_state.used_sss && ss_effects->sss_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED; - if (using_sss && !using_separate_specular) { + if ((using_sss || ce_needs_separate_specular) && !using_separate_specular) { using_separate_specular = true; color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR; color_framebuffer = rb_data->get_color_pass_fb(color_pass_flags); @@ -1880,6 +1888,17 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co clear_color = p_default_bg_color; } + RS::ViewportMSAA msaa = rb->get_msaa_3d(); + bool use_msaa = msaa != RS::VIEWPORT_MSAA_DISABLED; + + bool ce_pre_opaque_resolved_color = use_msaa && _compositor_effects_has_flag(p_render_data, RS::COMPOSITOR_EFFECT_FLAG_ACCESS_RESOLVED_COLOR, RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_PRE_OPAQUE); + bool ce_post_opaque_resolved_color = use_msaa && _compositor_effects_has_flag(p_render_data, RS::COMPOSITOR_EFFECT_FLAG_ACCESS_RESOLVED_COLOR, RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_POST_OPAQUE); + bool ce_pre_transparent_resolved_color = use_msaa && _compositor_effects_has_flag(p_render_data, RS::COMPOSITOR_EFFECT_FLAG_ACCESS_RESOLVED_COLOR, RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_PRE_TRANSPARENT); + + bool ce_pre_opaque_resolved_depth = use_msaa && _compositor_effects_has_flag(p_render_data, RS::COMPOSITOR_EFFECT_FLAG_ACCESS_RESOLVED_DEPTH, RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_PRE_OPAQUE); + bool ce_post_opaque_resolved_depth = use_msaa && _compositor_effects_has_flag(p_render_data, RS::COMPOSITOR_EFFECT_FLAG_ACCESS_RESOLVED_DEPTH, RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_POST_OPAQUE); + bool ce_pre_transparent_resolved_depth = use_msaa && _compositor_effects_has_flag(p_render_data, RS::COMPOSITOR_EFFECT_FLAG_ACCESS_RESOLVED_DEPTH, RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_PRE_TRANSPARENT); + 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 = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable")) && depth_framebuffer.is_valid(); @@ -1892,8 +1911,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } bool using_ssao = depth_pre_pass && !is_reflection_probe && p_render_data->environment.is_valid() && environment_get_ssao_enabled(p_render_data->environment); - if (depth_pre_pass) { //depth pre pass + if (depth_pre_pass) { //depth pre pass 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)"); @@ -1912,28 +1931,42 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID(), samplers); - bool finish_depth = using_ssao || using_ssil || using_sdfgi || using_voxelgi; + bool finish_depth = using_ssao || using_ssil || using_sdfgi || using_voxelgi || ce_pre_opaque_resolved_depth || ce_post_opaque_resolved_depth; 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, 0, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count, 0, spec_constant_base_flags); _render_list_with_draw_list(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, needs_pre_resolve ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, needs_pre_resolve ? Vector() : depth_pass_clear); RD::get_singleton()->draw_command_end_label(); - if (rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { + if (use_msaa) { RENDER_TIMESTAMP("Resolve Depth Pre-Pass (MSAA)"); RD::get_singleton()->draw_command_begin_label("Resolve Depth Pre-Pass (MSAA)"); if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI) { for (uint32_t v = 0; v < rb->get_view_count(); v++) { - resolve_effects->resolve_gi(rb->get_depth_msaa(v), rb_data->get_normal_roughness_msaa(v), using_voxelgi ? rb_data->get_voxelgi_msaa(v) : RID(), rb->get_depth_texture(v), rb_data->get_normal_roughness(v), using_voxelgi ? rb_data->get_voxelgi(v) : RID(), rb->get_internal_size(), texture_multisamples[rb->get_msaa_3d()]); + resolve_effects->resolve_gi(rb->get_depth_msaa(v), rb_data->get_normal_roughness_msaa(v), using_voxelgi ? rb_data->get_voxelgi_msaa(v) : RID(), rb->get_depth_texture(v), rb_data->get_normal_roughness(v), using_voxelgi ? rb_data->get_voxelgi(v) : RID(), rb->get_internal_size(), texture_multisamples[msaa]); } } else if (finish_depth) { for (uint32_t v = 0; v < rb->get_view_count(); v++) { - resolve_effects->resolve_depth(rb->get_depth_msaa(v), rb->get_depth_texture(v), rb->get_internal_size(), texture_multisamples[rb->get_msaa_3d()]); + resolve_effects->resolve_depth(rb->get_depth_msaa(v), rb->get_depth_texture(v), rb->get_internal_size(), texture_multisamples[msaa]); } } RD::get_singleton()->draw_command_end_label(); } } + { + if (ce_pre_opaque_resolved_color) { + // We haven't rendered color data yet so... + WARN_PRINT_ONCE("Pre opaque rendering effects can't access resolved color buffers."); + } + + if (ce_pre_opaque_resolved_depth && !depth_pre_pass) { + // We haven't rendered depth data yet so... + WARN_PRINT_ONCE("Pre opaque rendering effects can't access resolved depth buffers."); + } + + _process_compositor_effects(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_PRE_OPAQUE, p_render_data); + } + RID normal_roughness_views[RendererSceneRender::MAX_RENDER_VIEWS]; if (rb_data.is_valid() && rb_data->has_normal_roughness()) { for (uint32_t v = 0; v < rb->get_view_count(); v++) { @@ -1955,8 +1988,6 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RENDER_TIMESTAMP("Render Opaque Pass"); RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, p_render_data, radiance_texture, samplers, true); - bool can_continue_color = !scene_state.used_screen_texture && !using_ssr && !using_sss; - bool can_continue_depth = !(scene_state.used_depth_texture || scene_state.used_normal_texture) && !using_ssr && !using_sss; { bool render_motion_pass = !render_list[RENDER_LIST_MOTION].elements.is_empty(); @@ -2006,6 +2037,22 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } } + { + if (ce_post_opaque_resolved_color) { + for (uint32_t v = 0; v < rb->get_view_count(); v++) { + RD::get_singleton()->texture_resolve_multisample(rb->get_color_msaa(v), rb->get_internal_texture(v)); + } + } + + if (ce_post_opaque_resolved_depth) { + for (uint32_t v = 0; v < rb->get_view_count(); v++) { + resolve_effects->resolve_depth(rb->get_depth_msaa(v), rb->get_depth_texture(v), rb->get_internal_size(), texture_multisamples[msaa]); + } + } + + _process_compositor_effects(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_POST_OPAQUE, p_render_data); + } + if (debug_voxelgis) { Projection dc; dc.set_depth_correction(true); @@ -2040,11 +2087,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_list_end(); RD::get_singleton()->draw_command_end_label(); } - if (rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { + + if (use_msaa) { RENDER_TIMESTAMP("Resolve MSAA"); - if (!can_continue_color) { - // Handle views individual, might want to look at rewriting our resolve to do both layers in one pass. + if (scene_state.used_screen_texture || using_separate_specular || ce_pre_transparent_resolved_color) { for (uint32_t v = 0; v < rb->get_view_count(); v++) { RD::get_singleton()->texture_resolve_multisample(rb->get_color_msaa(v), rb->get_internal_texture(v)); } @@ -2055,13 +2102,18 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } } - if (!can_continue_depth) { + if (scene_state.used_depth_texture || scene_state.used_normal_texture || using_separate_specular || ce_needs_normal_roughness || ce_pre_transparent_resolved_depth) { for (uint32_t v = 0; v < rb->get_view_count(); v++) { - resolve_effects->resolve_depth(rb->get_depth_msaa(v), rb->get_depth_texture(v), rb->get_internal_size(), texture_multisamples[rb->get_msaa_3d()]); + resolve_effects->resolve_depth(rb->get_depth_msaa(v), rb->get_depth_texture(v), rb->get_internal_size(), texture_multisamples[msaa]); } } } + { + // Don't need to check for depth or color resolve here, we've already triggered it. + _process_compositor_effects(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_POST_SKY, p_render_data); + } + if (using_separate_specular) { if (using_sss) { RENDER_TIMESTAMP("Sub-Surface Scattering"); @@ -2077,12 +2129,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co for (uint32_t v = 0; v < p_render_data->scene_data->view_count; v++) { specular_views[v] = rb_data->get_specular(v); } - _process_ssr(rb, color_only_framebuffer, normal_roughness_views, rb_data->get_specular(), specular_views, p_render_data->environment, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, rb->get_msaa_3d() == RS::VIEWPORT_MSAA_DISABLED); + _process_ssr(rb, color_only_framebuffer, normal_roughness_views, rb_data->get_specular(), specular_views, p_render_data->environment, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, !use_msaa); RD::get_singleton()->draw_command_end_label(); } else { //just mix specular back RENDER_TIMESTAMP("Merge Specular"); - copy_effects->merge_specular(color_only_framebuffer, rb_data->get_specular(), rb->get_msaa_3d() == RS::VIEWPORT_MSAA_DISABLED ? RID() : rb->get_internal_texture(), RID(), p_render_data->scene_data->view_count); + copy_effects->merge_specular(color_only_framebuffer, rb_data->get_specular(), !use_msaa ? RID() : rb->get_internal_texture(), RID(), p_render_data->scene_data->view_count); } } @@ -2116,6 +2168,28 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co _render_buffers_copy_depth_texture(p_render_data); } + { + if (using_separate_specular) { + // Our specular will be combined back in (and effects, subsurface scattering and/or ssr applied), + // so if we've requested this, we need another copy. + // Fairly unlikely scenario though. + + if (ce_pre_transparent_resolved_color) { + for (uint32_t v = 0; v < rb->get_view_count(); v++) { + RD::get_singleton()->texture_resolve_multisample(rb->get_color_msaa(v), rb->get_internal_texture(v)); + } + } + + if (ce_pre_transparent_resolved_depth) { + for (uint32_t v = 0; v < rb->get_view_count(); v++) { + resolve_effects->resolve_depth(rb->get_depth_msaa(v), rb->get_depth_texture(v), rb->get_internal_size(), texture_multisamples[msaa]); + } + } + } + + _process_compositor_effects(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_PRE_TRANSPARENT, p_render_data); + } + RENDER_TIMESTAMP("Render 3D Transparent Pass"); RD::get_singleton()->draw_command_begin_label("Render 3D Transparent Pass"); @@ -2142,11 +2216,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_begin_label("Resolve"); - if (rb_data.is_valid() && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { - bool resolve_velocity_buffer = (using_taa || using_fsr2) && rb->has_velocity_buffer(true); + if (rb_data.is_valid() && use_msaa) { + bool resolve_velocity_buffer = (using_taa || using_fsr2 || ce_needs_motion_vectors) && rb->has_velocity_buffer(true); for (uint32_t v = 0; v < rb->get_view_count(); v++) { RD::get_singleton()->texture_resolve_multisample(rb->get_color_msaa(v), rb->get_internal_texture(v)); - resolve_effects->resolve_depth(rb->get_depth_msaa(v), rb->get_depth_texture(v), rb->get_internal_size(), texture_multisamples[rb->get_msaa_3d()]); + resolve_effects->resolve_depth(rb->get_depth_msaa(v), rb->get_depth_texture(v), rb->get_internal_size(), texture_multisamples[msaa]); if (resolve_velocity_buffer) { RD::get_singleton()->texture_resolve_multisample(rb->get_velocity_buffer(true, v), rb->get_velocity_buffer(false, v)); @@ -2156,6 +2230,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_end_label(); + { + _process_compositor_effects(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_POST_TRANSPARENT, p_render_data); + } + RD::get_singleton()->draw_command_begin_label("Copy framebuffer for SSIL"); if (using_ssil) { RENDER_TIMESTAMP("Copy Final Framebuffer (SSIL)"); 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 51fd0aaffb9e..12af8822b495 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -48,8 +48,8 @@ #define RB_TEX_SPECULAR SNAME("specular") #define RB_TEX_SPECULAR_MSAA SNAME("specular_msaa") -#define RB_TEX_ROUGHNESS SNAME("normal_roughnesss") -#define RB_TEX_ROUGHNESS_MSAA SNAME("normal_roughnesss_msaa") +#define RB_TEX_NORMAL_ROUGHNESS SNAME("normal_roughness") +#define RB_TEX_NORMAL_ROUGHNESS_MSAA SNAME("normal_roughness_msaa") #define RB_TEX_VOXEL_GI SNAME("voxel_gi") #define RB_TEX_VOXEL_GI_MSAA SNAME("voxel_gi_msaa") @@ -131,11 +131,11 @@ class RenderForwardClustered : public RendererSceneRenderRD { RID get_specular_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR_MSAA, p_layer, 0); } void ensure_normal_roughness_texture(); - bool has_normal_roughness() const { return render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS); } - RID get_normal_roughness() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS); } - RID get_normal_roughness(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS, p_layer, 0); } - RID get_normal_roughness_msaa() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS_MSAA); } - RID get_normal_roughness_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS_MSAA, p_layer, 0); } + bool has_normal_roughness() const { return render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_NORMAL_ROUGHNESS); } + RID get_normal_roughness() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_NORMAL_ROUGHNESS); } + RID get_normal_roughness(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_NORMAL_ROUGHNESS, p_layer, 0); } + RID get_normal_roughness_msaa() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_NORMAL_ROUGHNESS_MSAA); } + RID get_normal_roughness_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_NORMAL_ROUGHNESS_MSAA, p_layer, 0); } void ensure_voxelgi(); bool has_voxelgi() const { return render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI); } 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 fd81430983c9..ac93aca6bb02 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -669,6 +669,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color // check if we need motion vectors if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) { p_render_data->scene_data->calculate_motion_vectors = true; + } else if (_compositor_effects_has_flag(p_render_data, RS::COMPOSITOR_EFFECT_FLAG_NEEDS_MOTION_VECTORS)) { + p_render_data->scene_data->calculate_motion_vectors = true; } else if (render target has velocity override) { // TODO p_render_data->scene_data->calculate_motion_vectors = true; } else { @@ -694,6 +696,34 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color bool using_subpass_post_process = true; // If true: we can do our post processing in a subpass RendererRD::MaterialStorage::Samplers samplers; + RS::ViewportMSAA msaa = rb->get_msaa_3d(); + bool use_msaa = msaa != RS::VIEWPORT_MSAA_DISABLED; + + bool ce_has_post_opaque = _has_compositor_effect(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_POST_OPAQUE, p_render_data); + bool ce_has_pre_transparent = _has_compositor_effect(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_PRE_TRANSPARENT, p_render_data); + bool ce_has_post_transparent = _has_compositor_effect(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_POST_TRANSPARENT, p_render_data); + + if (ce_has_post_opaque) { + // As we're doing opaque and sky in subpasses we don't support this *yet* + WARN_PRINT_ONCE("Post opaque rendering effect callback is not supported in the mobile renderer"); + } + + // Using RenderingEffects limits our ability to do subpasses.. + if (ce_has_pre_transparent) { + merge_transparent_pass = false; + using_subpass_post_process = false; + } + if (ce_has_post_transparent) { + using_subpass_post_process = false; + } + + if (use_msaa && _compositor_effects_has_flag(p_render_data, RS::COMPOSITOR_EFFECT_FLAG_ACCESS_RESOLVED_DEPTH, RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_ANY)) { + // We'll be able to do this when we finish PR #78598 + WARN_PRINT_ONCE("Depth buffer resolve for rendering effect callback is not supported in the mobile renderer"); + } + + // We don't need to check resolve color flag, it will be resolved for transparent passes regardless. + bool using_shadows = true; if (p_render_data->reflection_probe.is_valid()) { @@ -881,6 +911,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color clear_color = p_default_bg_color; } + // We don't have access to any rendered buffers but we may be able to effect mesh data... + _process_compositor_effects(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_PRE_OPAQUE, p_render_data); + _pre_opaque_render(p_render_data); uint32_t spec_constant_base_flags = 0; @@ -942,7 +975,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color c.push_back(cc); // Our render buffer. if (rb_data.is_valid()) { - if (p_render_data->render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { + if (use_msaa) { c.push_back(clear_color.srgb_to_linear() * inverse_luminance_multiplier); // Our resolve buffer. } if (using_subpass_post_process) { @@ -985,6 +1018,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RD::get_singleton()->draw_command_end_label(); // Draw Sky } + // rendering effects + if (ce_has_pre_transparent) { + _process_compositor_effects(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_PRE_TRANSPARENT, p_render_data); + } + if (merge_transparent_pass) { if (render_list[RENDER_LIST_ALPHA].element_info.size() > 0) { // transparent pass @@ -1055,6 +1093,10 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (rb_data.is_valid() && !using_subpass_post_process) { RD::get_singleton()->draw_command_begin_label("Post process pass"); + if (ce_has_post_transparent) { + _process_compositor_effects(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_POST_TRANSPARENT, p_render_data); + } + // If we need extra effects we do this in its own pass RENDER_TIMESTAMP("Tonemap"); diff --git a/servers/rendering/renderer_rd/framebuffer_cache_rd.cpp b/servers/rendering/renderer_rd/framebuffer_cache_rd.cpp index 71b813624526..ec037b71faf8 100644 --- a/servers/rendering/renderer_rd/framebuffer_cache_rd.cpp +++ b/servers/rendering/renderer_rd/framebuffer_cache_rd.cpp @@ -32,6 +32,10 @@ FramebufferCacheRD *FramebufferCacheRD::singleton = nullptr; +void FramebufferCacheRD::_bind_methods() { + ClassDB::bind_static_method("FramebufferCacheRD", D_METHOD("get_cache_multipass", "textures", "passes", "views"), &FramebufferCacheRD::get_cache_multipass_array); +} + void FramebufferCacheRD::_invalidate(Cache *p_cache) { if (p_cache->prev) { p_cache->prev->next = p_cache->next; @@ -52,6 +56,25 @@ void FramebufferCacheRD::_framebuffer_invalidation_callback(void *p_userdata) { singleton->_invalidate(reinterpret_cast(p_userdata)); } +RID FramebufferCacheRD::get_cache_multipass_array(const TypedArray &p_textures, const TypedArray &p_passes, uint32_t p_views) { + Vector textures; + Vector passes; + + for (int i = 0; i < p_textures.size(); i++) { + RID texture = p_textures[i]; + textures.push_back(texture); // store even if NULL + } + + for (int i = 0; i < p_passes.size(); i++) { + Ref pass = p_passes[i]; + if (pass.is_valid()) { + passes.push_back(pass->base); + } + } + + return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, p_views); +} + FramebufferCacheRD::FramebufferCacheRD() { ERR_FAIL_COND(singleton != nullptr); singleton = this; diff --git a/servers/rendering/renderer_rd/framebuffer_cache_rd.h b/servers/rendering/renderer_rd/framebuffer_cache_rd.h index cae95ccce025..abb2a5808ded 100644 --- a/servers/rendering/renderer_rd/framebuffer_cache_rd.h +++ b/servers/rendering/renderer_rd/framebuffer_cache_rd.h @@ -34,6 +34,7 @@ #include "core/templates/local_vector.h" #include "core/templates/paged_allocator.h" #include "servers/rendering/rendering_device.h" +#include "servers/rendering/rendering_device_binds.h" class FramebufferCacheRD : public Object { GDCLASS(FramebufferCacheRD, Object) @@ -195,6 +196,9 @@ class FramebufferCacheRD : public Object { return rid; } +private: + static void _bind_methods(); + public: template RID get_cache(Args... args) { @@ -301,6 +305,8 @@ class FramebufferCacheRD : public Object { return _allocate_from_data(p_views, h, table_idx, p_textures, p_passes); } + static RID get_cache_multipass_array(const TypedArray &p_textures, const TypedArray &p_passes, uint32_t p_views = 1); + static FramebufferCacheRD *get_singleton() { return singleton; } FramebufferCacheRD(); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 35c0bdd5954e..62ecec39919e 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -249,6 +249,73 @@ Ref RendererSceneRenderRD::render_buffers_create() { return rb; } +bool RendererSceneRenderRD::_compositor_effects_has_flag(const RenderDataRD *p_render_data, RS::CompositorEffectFlags p_flag, RS::CompositorEffectCallbackType p_callback_type) { + RendererCompositorStorage *comp_storage = RendererCompositorStorage::get_singleton(); + + if (p_render_data->compositor.is_null()) { + return false; + } + + if (p_render_data->reflection_probe.is_valid()) { + return false; + } + + ERR_FAIL_COND_V(!comp_storage->is_compositor(p_render_data->compositor), false); + Vector re_rids = comp_storage->compositor_get_compositor_effects(p_render_data->compositor, p_callback_type, true); + + for (RID rid : re_rids) { + if (comp_storage->compositor_effect_get_flag(rid, p_flag)) { + return true; + } + } + + return false; +} + +bool RendererSceneRenderRD::_has_compositor_effect(RS::CompositorEffectCallbackType p_callback_type, const RenderDataRD *p_render_data) { + RendererCompositorStorage *comp_storage = RendererCompositorStorage::get_singleton(); + + if (p_render_data->compositor.is_null()) { + return false; + } + + if (p_render_data->reflection_probe.is_valid()) { + return false; + } + + ERR_FAIL_COND_V(!comp_storage->is_compositor(p_render_data->compositor), false); + + Vector effects = comp_storage->compositor_get_compositor_effects(p_render_data->compositor, p_callback_type, true); + + return effects.size() > 0; +} + +void RendererSceneRenderRD::_process_compositor_effects(RS::CompositorEffectCallbackType p_callback_type, const RenderDataRD *p_render_data) { + RendererCompositorStorage *comp_storage = RendererCompositorStorage::get_singleton(); + + if (p_render_data->compositor.is_null()) { + return; + } + + if (p_render_data->reflection_probe.is_valid()) { + return; + } + + ERR_FAIL_COND(!comp_storage->is_compositor(p_render_data->compositor)); + + Vector re_rids = comp_storage->compositor_get_compositor_effects(p_render_data->compositor, p_callback_type, true); + + for (RID rid : re_rids) { + Array arr; + Callable callback = comp_storage->compositor_effect_get_callback(rid); + + arr.push_back(p_callback_type); + arr.push_back(p_render_data); + + callback.callv(arr); + } +} + void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderDataRD *p_render_data) { Ref rb = p_render_data->render_buffers; ERR_FAIL_COND(rb.is_null()); @@ -987,7 +1054,7 @@ void RendererSceneRenderRD::_post_prepass_render(RenderDataRD *p_render_data, bo } } -void RendererSceneRenderRD::render_scene(const Ref &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, 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, const PagedArray &p_fog_volumes, RID p_environment, RID p_camera_attributes, 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_mesh_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, RenderingMethod::RenderInfo *r_render_info) { +void RendererSceneRenderRD::render_scene(const Ref &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, 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, const PagedArray &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_compositor, 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_mesh_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, RenderingMethod::RenderInfo *r_render_info) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); @@ -1067,6 +1134,7 @@ void RendererSceneRenderRD::render_scene(const Ref &p_render render_data.lightmaps = &p_lightmaps; render_data.fog_volumes = &p_fog_volumes; render_data.environment = p_environment; + render_data.compositor = p_compositor; render_data.camera_attributes = p_camera_attributes; render_data.shadow_atlas = p_shadow_atlas; render_data.occluder_debug_tex = p_occluder_debug_tex; @@ -1128,6 +1196,10 @@ void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, bool RendererSceneRenderRD::free(RID p_rid) { if (is_environment(p_rid)) { environment_free(p_rid); + } else if (is_compositor(p_rid)) { + compositor_free(p_rid); + } else if (is_compositor_effect(p_rid)) { + compositor_effect_free(p_rid); } else if (RSG::camera_attributes->owns_camera_attributes(p_rid)) { RSG::camera_attributes->camera_attributes_free(p_rid); } else if (gi.voxel_gi_instance_owns(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 4811ae3b44e5..5c5f11aba675 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -47,58 +47,13 @@ #include "servers/rendering/renderer_rd/environment/sky.h" #include "servers/rendering/renderer_rd/framebuffer_cache_rd.h" #include "servers/rendering/renderer_rd/storage_rd/light_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/render_data_rd.h" #include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h" #include "servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/rendering_method.h" -// For RenderDataRD, possibly inherited from RefCounted and add proper getters for our implementation classes - -struct RenderDataRD { - Ref render_buffers; - RenderSceneDataRD *scene_data; - - const PagedArray *instances = nullptr; - const PagedArray *lights = nullptr; - const PagedArray *reflection_probes = nullptr; - const PagedArray *voxel_gi_instances = nullptr; - const PagedArray *decals = nullptr; - const PagedArray *lightmaps = nullptr; - const PagedArray *fog_volumes = nullptr; - RID environment; - RID camera_attributes; - RID shadow_atlas; - RID occluder_debug_tex; - RID reflection_atlas; - RID reflection_probe; - int reflection_probe_pass = 0; - - RID cluster_buffer; - uint32_t cluster_size = 0; - uint32_t cluster_max_elements = 0; - - uint32_t directional_light_count = 0; - bool directional_light_soft_shadows = false; - - RenderingMethod::RenderInfo *render_info = nullptr; - - /* Shadow data */ - const RendererSceneRender::RenderShadowData *render_shadows = nullptr; - int render_shadow_count = 0; - - LocalVector cube_shadows; - LocalVector shadows; - LocalVector directional_shadows; - - /* GI info */ - const RendererSceneRender::RenderSDFGIData *render_sdfgi_regions = nullptr; - int render_sdfgi_region_count = 0; - const RendererSceneRender::RenderSDFGIUpdateData *sdfgi_update_data = nullptr; - - uint32_t voxel_gi_count = 0; -}; - class RendererSceneRenderRD : public RendererSceneRender { friend RendererRD::SkyRD; friend RendererRD::GI; @@ -145,6 +100,9 @@ class RendererSceneRenderRD : public RendererSceneRender { bool _needs_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi); void _post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi); + bool _compositor_effects_has_flag(const RenderDataRD *p_render_data, RS::CompositorEffectFlags p_flag, RS::CompositorEffectCallbackType p_callback_type = RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_ANY); + bool _has_compositor_effect(RS::CompositorEffectCallbackType p_callback_type, const RenderDataRD *p_render_data); + void _process_compositor_effects(RS::CompositorEffectCallbackType p_callback_type, const RenderDataRD *p_render_data); void _render_buffers_copy_screen_texture(const RenderDataRD *p_render_data); void _render_buffers_copy_depth_texture(const RenderDataRD *p_render_data); void _render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data); @@ -280,7 +238,7 @@ class RendererSceneRenderRD : public RendererSceneRender { virtual void base_uniforms_changed() = 0; - virtual void render_scene(const Ref &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, 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, const PagedArray &p_fog_volumes, RID p_environment, RID p_camera_attributes, 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_mesh_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, RenderingMethod::RenderInfo *r_render_info = nullptr) override; + virtual void render_scene(const Ref &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, 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, const PagedArray &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_compositor, 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_mesh_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, RenderingMethod::RenderInfo *r_render_info = nullptr) override; virtual void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray &p_instances, RID p_framebuffer, const Rect2i &p_region) override; diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h index 45226ec47cae..b3d27cc6ede7 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h @@ -43,7 +43,7 @@ #include "servers/rendering/storage/light_storage.h" #include "servers/rendering/storage/utilities.h" -struct RenderDataRD; +class RenderDataRD; namespace RendererRD { diff --git a/servers/rendering/renderer_rd/storage_rd/render_data_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_data_rd.cpp new file mode 100644 index 000000000000..ac4fbba75b0e --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/render_data_rd.cpp @@ -0,0 +1,50 @@ +/**************************************************************************/ +/* render_data_rd.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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 "render_data_rd.h" + +void RenderDataRD::_bind_methods() { +} + +Ref RenderDataRD::get_render_scene_buffers() const { + return render_buffers; +} + +RenderSceneData *RenderDataRD::get_render_scene_data() const { + return scene_data; +} + +RID RenderDataRD::get_environment() const { + return environment; +} + +RID RenderDataRD::get_camera_attributes() const { + return camera_attributes; +} diff --git a/servers/rendering/renderer_rd/storage_rd/render_data_rd.h b/servers/rendering/renderer_rd/storage_rd/render_data_rd.h new file mode 100644 index 000000000000..2f61899a1837 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/render_data_rd.h @@ -0,0 +1,97 @@ +/**************************************************************************/ +/* render_data_rd.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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 RENDER_DATA_RD_H +#define RENDER_DATA_RD_H + +#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h" +#include "servers/rendering/storage/render_data.h" + +class RenderDataRD : public RenderData { + GDCLASS(RenderDataRD, RenderData); + +protected: + static void _bind_methods(); + +public: + // Access methods to expose data externally + virtual Ref get_render_scene_buffers() const override; + virtual RenderSceneData *get_render_scene_data() const override; + + virtual RID get_environment() const override; + virtual RID get_camera_attributes() const override; + + // Members are publicly accessible within the render engine. + Ref render_buffers; + RenderSceneDataRD *scene_data = nullptr; + + const PagedArray *instances = nullptr; + const PagedArray *lights = nullptr; + const PagedArray *reflection_probes = nullptr; + const PagedArray *voxel_gi_instances = nullptr; + const PagedArray *decals = nullptr; + const PagedArray *lightmaps = nullptr; + const PagedArray *fog_volumes = nullptr; + RID environment; + RID camera_attributes; + RID compositor; + RID shadow_atlas; + RID occluder_debug_tex; + RID reflection_atlas; + RID reflection_probe; + int reflection_probe_pass = 0; + + RID cluster_buffer; + uint32_t cluster_size = 0; + uint32_t cluster_max_elements = 0; + + uint32_t directional_light_count = 0; + bool directional_light_soft_shadows = false; + + RenderingMethod::RenderInfo *render_info = nullptr; + + /* Shadow data */ + const RendererSceneRender::RenderShadowData *render_shadows = nullptr; + int render_shadow_count = 0; + + LocalVector cube_shadows; + LocalVector shadows; + LocalVector directional_shadows; + + /* GI info */ + const RendererSceneRender::RenderSDFGIData *render_sdfgi_regions = nullptr; + int render_sdfgi_region_count = 0; + const RendererSceneRender::RenderSDFGIUpdateData *sdfgi_update_data = nullptr; + + uint32_t voxel_gi_count = 0; +}; + +#endif // RENDER_DATA_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.compat.inc b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.compat.inc new file mode 100644 index 000000000000..75b9ee2da74e --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.compat.inc @@ -0,0 +1,66 @@ +/**************************************************************************/ +/* render_scene_buffers_rd.compat.inc */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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 DISABLE_DEPRECATED + +RID RenderSceneBuffersRD::_get_color_texture_compat_80214() { + return _get_color_texture(msaa_3d != RS::VIEWPORT_MSAA_DISABLED); +} + +RID RenderSceneBuffersRD::_get_color_layer_compat_80214(const uint32_t p_layer) { + return _get_color_layer(p_layer, msaa_3d != RS::VIEWPORT_MSAA_DISABLED); +} + +RID RenderSceneBuffersRD::_get_depth_texture_compat_80214() { + return _get_depth_texture(msaa_3d != RS::VIEWPORT_MSAA_DISABLED); +} + +RID RenderSceneBuffersRD::_get_depth_layer_compat_80214(const uint32_t p_layer) { + return _get_depth_layer(p_layer, msaa_3d != RS::VIEWPORT_MSAA_DISABLED); +} + +RID RenderSceneBuffersRD::_get_velocity_texture_compat_80214() { + return _get_velocity_texture(msaa_3d != RS::VIEWPORT_MSAA_DISABLED); +} + +RID RenderSceneBuffersRD::_get_velocity_layer_compat_80214(const uint32_t p_layer) { + return _get_velocity_layer(p_layer, msaa_3d != RS::VIEWPORT_MSAA_DISABLED); +} + +void RenderSceneBuffersRD::_bind_compatibility_methods() { + ClassDB::bind_compatibility_method(D_METHOD("get_color_texture"), &RenderSceneBuffersRD::_get_color_texture_compat_80214); + ClassDB::bind_compatibility_method(D_METHOD("get_color_layer", "layer"), &RenderSceneBuffersRD::_get_color_layer_compat_80214); + ClassDB::bind_compatibility_method(D_METHOD("get_depth_texture"), &RenderSceneBuffersRD::_get_depth_texture_compat_80214); + ClassDB::bind_compatibility_method(D_METHOD("get_depth_layer", "layer"), &RenderSceneBuffersRD::_get_depth_layer_compat_80214); + ClassDB::bind_compatibility_method(D_METHOD("get_velocity_texture"), &RenderSceneBuffersRD::_get_velocity_texture_compat_80214); + ClassDB::bind_compatibility_method(D_METHOD("get_velocity_layer", "layer"), &RenderSceneBuffersRD::_get_velocity_layer_compat_80214); +} + +#endif // DISABLE_DEPRECATED diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp index c338dd0377ac..8dc74820e228 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp @@ -29,6 +29,8 @@ /**************************************************************************/ #include "render_scene_buffers_rd.h" +#include "render_scene_buffers_rd.compat.inc" + #include "core/config/project_settings.h" #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" @@ -57,17 +59,18 @@ void RenderSceneBuffersRD::_bind_methods() { ClassDB::bind_method(D_METHOD("clear_context", "context"), &RenderSceneBuffersRD::clear_context); // Access to some core buffers so users don't need to know their names. - ClassDB::bind_method(D_METHOD("get_color_texture"), &RenderSceneBuffersRD::_get_color_texture); - ClassDB::bind_method(D_METHOD("get_color_layer", "layer"), &RenderSceneBuffersRD::_get_color_layer); - ClassDB::bind_method(D_METHOD("get_depth_texture"), &RenderSceneBuffersRD::_get_depth_texture); - ClassDB::bind_method(D_METHOD("get_depth_layer", "layer"), &RenderSceneBuffersRD::_get_depth_layer); - ClassDB::bind_method(D_METHOD("get_velocity_texture"), &RenderSceneBuffersRD::_get_velocity_texture); - ClassDB::bind_method(D_METHOD("get_velocity_layer", "layer"), &RenderSceneBuffersRD::_get_velocity_layer); + ClassDB::bind_method(D_METHOD("get_color_texture", "msaa"), &RenderSceneBuffersRD::_get_color_texture, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("get_color_layer", "layer", "msaa"), &RenderSceneBuffersRD::_get_color_layer, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("get_depth_texture", "msaa"), &RenderSceneBuffersRD::_get_depth_texture, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("get_depth_layer", "layer", "msaa"), &RenderSceneBuffersRD::_get_depth_layer, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("get_velocity_texture", "msaa"), &RenderSceneBuffersRD::_get_velocity_texture, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("get_velocity_layer", "layer", "msaa"), &RenderSceneBuffersRD::_get_velocity_layer, DEFVAL(false)); // Expose a few properties we're likely to use externally ClassDB::bind_method(D_METHOD("get_render_target"), &RenderSceneBuffersRD::get_render_target); ClassDB::bind_method(D_METHOD("get_view_count"), &RenderSceneBuffersRD::get_view_count); ClassDB::bind_method(D_METHOD("get_internal_size"), &RenderSceneBuffersRD::get_internal_size); + ClassDB::bind_method(D_METHOD("get_msaa_3d"), &RenderSceneBuffersRD::get_msaa_3d); ClassDB::bind_method(D_METHOD("get_use_taa"), &RenderSceneBuffersRD::get_use_taa); } diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h index 5b8a74de833b..c885ad52d170 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h @@ -305,20 +305,25 @@ class RenderSceneBuffersRD : public RenderSceneBuffers { return samplers; } +private: //////////////////////////////////////////////////////////////////////////////////////////////////////////// // Our classDB doesn't support calling our normal exposed functions -private: RID _create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const Ref &p_texture_format, const Ref &p_view = Ref(), bool p_unique = true); RID _create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName &p_view_name, const Ref p_view = Ref()); Ref _get_texture_format(const StringName &p_context, const StringName &p_texture_name) const; RID _get_texture_slice_view(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers = 1, const uint32_t p_mipmaps = 1, const Ref p_view = Ref()); - // For color and depth as exposed to extensions, we return the buffer that we're rendering into. - // Resolving happens after effects etc. are run. - RID _get_color_texture() { - if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED && has_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA)) { - return get_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA); + // For color and depth as exposed to extensions: + // - we need separately named functions to access the layer, + // - we don't output an error for missing buffers but just return an empty RID. + RID _get_color_texture(bool p_msaa = false) { + if (p_msaa) { + if (has_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA)) { + return get_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA); + } else { + return RID(); + } } else if (has_internal_texture()) { return get_internal_texture(); } else { @@ -326,9 +331,13 @@ class RenderSceneBuffersRD : public RenderSceneBuffers { } } - RID _get_color_layer(const uint32_t p_layer) { - if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED && has_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA)) { - return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA, p_layer, 0); + RID _get_color_layer(const uint32_t p_layer, bool p_msaa = false) { + if (p_msaa) { + if (has_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA)) { + return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA, p_layer, 0); + } else { + return RID(); + } } else if (has_internal_texture()) { return get_internal_texture(p_layer); } else { @@ -336,9 +345,13 @@ class RenderSceneBuffersRD : public RenderSceneBuffers { } } - RID _get_depth_texture() { - if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED && has_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA)) { - return get_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA); + RID _get_depth_texture(bool p_msaa = false) { + if (p_msaa) { + if (has_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA)) { + return get_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA); + } else { + return RID(); + } } else if (has_depth_texture()) { return get_depth_texture(); } else { @@ -346,9 +359,13 @@ class RenderSceneBuffersRD : public RenderSceneBuffers { } } - RID _get_depth_layer(const uint32_t p_layer) { - if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED && has_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA)) { - return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA, p_layer, 0); + RID _get_depth_layer(const uint32_t p_layer, bool p_msaa = false) { + if (p_msaa) { + if (has_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA)) { + return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA, p_layer, 0); + } else { + return RID(); + } } else if (has_depth_texture()) { return get_depth_texture(p_layer); } else { @@ -356,26 +373,35 @@ class RenderSceneBuffersRD : public RenderSceneBuffers { } } - RID _get_velocity_texture() { - if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED && has_velocity_buffer(true)) { - return get_velocity_buffer(true); - } else if (has_velocity_buffer(false)) { - return get_velocity_buffer(false); + RID _get_velocity_texture(bool p_msaa = false) { + if (has_velocity_buffer(p_msaa)) { + return get_velocity_buffer(p_msaa); } else { return RID(); } } - RID _get_velocity_layer(const uint32_t p_layer) { - if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED && has_velocity_buffer(true)) { - return get_velocity_buffer(true, p_layer); - } else if (has_velocity_buffer(false)) { - return get_velocity_buffer(false, p_layer); + RID _get_velocity_layer(const uint32_t p_layer, bool p_msaa = false) { + if (has_velocity_buffer(p_msaa)) { + return get_velocity_buffer(p_msaa, p_layer); } else { return RID(); } } +#ifndef DISABLE_DEPRECATED + + RID _get_color_texture_compat_80214(); + RID _get_color_layer_compat_80214(const uint32_t p_layer); + RID _get_depth_texture_compat_80214(); + RID _get_depth_layer_compat_80214(const uint32_t p_layer); + RID _get_velocity_texture_compat_80214(); + RID _get_velocity_layer_compat_80214(const uint32_t p_layer); + + static void _bind_compatibility_methods(); + +#endif // DISABLE_DEPRECATED + //////////////////////////////////////////////////////////////////////////////////////////////////////////// // Everything after this needs to be re-evaluated, this is all old implementation public: diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp index 86f0f5acf2bc..dc1e64ddcc21 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp @@ -34,6 +34,33 @@ #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_default.h" +void RenderSceneDataRD::_bind_methods() { +} + +Transform3D RenderSceneDataRD::get_cam_transform() const { + return cam_transform; +} + +Projection RenderSceneDataRD::get_cam_projection() const { + return cam_projection; +} + +uint32_t RenderSceneDataRD::get_view_count() const { + return view_count; +} + +Vector3 RenderSceneDataRD::get_view_eye_offset(uint32_t p_view) const { + ERR_FAIL_UNSIGNED_INDEX_V(p_view, view_count, Vector3()); + + return view_eye_offset[p_view]; +} + +Projection RenderSceneDataRD::get_view_projection(uint32_t p_view) const { + ERR_FAIL_UNSIGNED_INDEX_V(p_view, view_count, Projection()); + + return view_projection[p_view]; +} + RID RenderSceneDataRD::create_uniform_buffer() { return RD::get_singleton()->uniform_buffer_create(sizeof(UBODATA)); } @@ -262,6 +289,6 @@ void RenderSceneDataRD::update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p RD::get_singleton()->buffer_update(uniform_buffer, 0, sizeof(UBODATA), &ubo); } -RID RenderSceneDataRD::get_uniform_buffer() { +RID RenderSceneDataRD::get_uniform_buffer() const { return uniform_buffer; } diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h index 9453966a86be..f6785942edb1 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h @@ -34,11 +34,14 @@ #include "render_scene_buffers_rd.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" +#include "servers/rendering/storage/render_scene_data.h" // This is a container for data related to rendering a single frame of a viewport where we load this data into a UBO // that can be used by the main scene shader but also by various effects. -class RenderSceneDataRD { +class RenderSceneDataRD : public RenderSceneData { + GDCLASS(RenderSceneDataRD, RenderSceneData); + public: bool calculate_motion_vectors = false; @@ -79,11 +82,20 @@ class RenderSceneDataRD { float time; float time_step; + virtual Transform3D get_cam_transform() const override; + virtual Projection get_cam_projection() const override; + + virtual uint32_t get_view_count() const override; + virtual Vector3 get_view_eye_offset(uint32_t p_view) const override; + virtual Projection get_view_projection(uint32_t p_view) const override; + RID create_uniform_buffer(); void update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p_debug_mode, RID p_env, RID p_reflection_probe_instance, RID p_camera_attributes, bool p_flip_y, bool p_pancake_shadows, const Size2i &p_screen_size, const Color &p_default_bg_color, float p_luminance_multiplier, bool p_opaque_render_buffers, bool p_apply_alpha_multiplier); - RID get_uniform_buffer(); + virtual RID get_uniform_buffer() const override; private: + static void _bind_methods(); + RID uniform_buffer; // loaded into this uniform buffer (supplied externally) // This struct is loaded into Set 1 - Binding 0, populated at start of rendering a frame, must match with shader code diff --git a/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp b/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp index 1f67d5e2582a..bcd8e78a710b 100644 --- a/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp +++ b/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp @@ -32,6 +32,23 @@ UniformSetCacheRD *UniformSetCacheRD::singleton = nullptr; +void UniformSetCacheRD::_bind_methods() { + ClassDB::bind_static_method("UniformSetCacheRD", D_METHOD("get_cache", "shader", "set", "uniforms"), &UniformSetCacheRD::get_cache_array); +} + +RID UniformSetCacheRD::get_cache_array(RID p_shader, uint32_t p_set, const TypedArray &p_uniforms) { + Vector uniforms; + + for (int i = 0; i < p_uniforms.size(); i++) { + Ref uniform = p_uniforms[i]; + if (uniform.is_valid()) { + uniforms.push_back(uniform->base); + } + } + + return UniformSetCacheRD::get_singleton()->get_cache_vec(p_shader, p_set, uniforms); +} + void UniformSetCacheRD::_invalidate(Cache *p_cache) { if (p_cache->prev) { p_cache->prev->next = p_cache->next; diff --git a/servers/rendering/renderer_rd/uniform_set_cache_rd.h b/servers/rendering/renderer_rd/uniform_set_cache_rd.h index 50243e715d64..c3b95f5f933d 100644 --- a/servers/rendering/renderer_rd/uniform_set_cache_rd.h +++ b/servers/rendering/renderer_rd/uniform_set_cache_rd.h @@ -34,6 +34,7 @@ #include "core/templates/local_vector.h" #include "core/templates/paged_allocator.h" #include "servers/rendering/rendering_device.h" +#include "servers/rendering/rendering_device_binds.h" class UniformSetCacheRD : public Object { GDCLASS(UniformSetCacheRD, Object) @@ -151,6 +152,9 @@ class UniformSetCacheRD : public Object { return rid; } +private: + static void _bind_methods(); + public: template RID get_cache(RID p_shader, uint32_t p_set, Args... args) { @@ -214,6 +218,8 @@ class UniformSetCacheRD : public Object { return _allocate_from_uniforms(p_shader, p_set, h, table_idx, p_uniforms); } + static RID get_cache_array(RID p_shader, uint32_t p_set, const TypedArray &p_uniforms); + static UniformSetCacheRD *get_singleton() { return singleton; } UniformSetCacheRD(); diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index b8f14bb6112c..59d70958f151 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -115,6 +115,12 @@ void RendererSceneCull::camera_set_camera_attributes(RID p_camera, RID p_attribu camera->attributes = p_attributes; } +void RendererSceneCull::camera_set_compositor(RID p_camera, RID p_compositor) { + Camera *camera = camera_owner.get_or_null(p_camera); + ERR_FAIL_NULL(camera); + camera->compositor = p_compositor; +} + void RendererSceneCull::camera_set_use_vertical_aspect(RID p_camera, bool p_enable) { Camera *camera = camera_owner.get_or_null(p_camera); ERR_FAIL_NULL(camera); @@ -401,6 +407,12 @@ void RendererSceneCull::scenario_set_camera_attributes(RID p_scenario, RID p_cam scenario->camera_attributes = p_camera_attributes; } +void RendererSceneCull::scenario_set_compositor(RID p_scenario, RID p_compositor) { + Scenario *scenario = scenario_owner.get_or_null(p_scenario); + ERR_FAIL_NULL(scenario); + scenario->compositor = p_compositor; +} + void RendererSceneCull::scenario_set_fallback_environment(RID p_scenario, RID p_environment) { Scenario *scenario = scenario_owner.get_or_null(p_scenario); ERR_FAIL_NULL(scenario); @@ -2623,12 +2635,13 @@ void RendererSceneCull::render_camera(const Ref &p_render_bu } RID environment = _render_get_environment(p_camera, p_scenario); + RID compositor = _render_get_compositor(p_camera, p_scenario); RENDER_TIMESTAMP("Update Occlusion Buffer") // For now just cull on the first camera RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_orthogonal); - _render_scene(&camera_data, p_render_buffers, environment, camera->attributes, camera->visible_layers, p_scenario, p_viewport, p_shadow_atlas, RID(), -1, p_screen_mesh_lod_threshold, true, r_render_info); + _render_scene(&camera_data, p_render_buffers, environment, camera->attributes, compositor, camera->visible_layers, p_scenario, p_viewport, p_shadow_atlas, RID(), -1, p_screen_mesh_lod_threshold, true, r_render_info); #endif } @@ -3008,7 +3021,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul } } -void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_camera_data, const Ref &p_render_buffers, RID p_environment, RID p_force_camera_attributes, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows, RenderingMethod::RenderInfo *r_render_info) { +void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_camera_data, const Ref &p_render_buffers, RID p_environment, RID p_force_camera_attributes, RID p_compositor, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows, RenderingMethod::RenderInfo *r_render_info) { Instance *render_reflection_probe = instance_owner.get_or_null(p_reflection_probe); //if null, not rendering to it // Prepare the light - camera volume culling system. @@ -3378,6 +3391,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c } else { camera_attributes = scenario->camera_attributes; } + /* PROCESS GEOMETRY AND DRAW SCENE */ RID occluders_tex; @@ -3388,7 +3402,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c } RENDER_TIMESTAMP("Render 3D Scene"); - scene_render->render_scene(p_render_buffers, p_camera_data, prev_camera_data, scene_cull_result.geometry_instances, scene_cull_result.light_instances, scene_cull_result.reflections, scene_cull_result.voxel_gi_instances, scene_cull_result.decals, scene_cull_result.lightmaps, scene_cull_result.fog_volumes, p_environment, camera_attributes, p_shadow_atlas, occluders_tex, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_mesh_lod_threshold, render_shadow_data, max_shadows_used, render_sdfgi_data, cull.sdfgi.region_count, &sdfgi_update_data, r_render_info); + scene_render->render_scene(p_render_buffers, p_camera_data, prev_camera_data, scene_cull_result.geometry_instances, scene_cull_result.light_instances, scene_cull_result.reflections, scene_cull_result.voxel_gi_instances, scene_cull_result.decals, scene_cull_result.lightmaps, scene_cull_result.fog_volumes, p_environment, camera_attributes, p_compositor, p_shadow_atlas, occluders_tex, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_mesh_lod_threshold, render_shadow_data, max_shadows_used, render_sdfgi_data, cull.sdfgi.region_count, &sdfgi_update_data, r_render_info); if (p_viewport.is_valid()) { RSG::viewport->viewport_set_prev_camera_data(p_viewport, p_camera_data); @@ -3425,6 +3439,20 @@ RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) { return RID(); } +RID RendererSceneCull::_render_get_compositor(RID p_camera, RID p_scenario) { + Camera *camera = camera_owner.get_or_null(p_camera); + if (camera && scene_render->is_compositor(camera->compositor)) { + return camera->compositor; + } + + Scenario *scenario = scenario_owner.get_or_null(p_scenario); + if (scenario && scene_render->is_compositor(scenario->compositor)) { + return scenario->compositor; + } + + return RID(); +} + void RendererSceneCull::render_empty_scene(const Ref &p_render_buffers, RID p_scenario, RID p_shadow_atlas) { #ifndef _3D_DISABLED Scenario *scenario = scenario_owner.get_or_null(p_scenario); @@ -3435,12 +3463,13 @@ void RendererSceneCull::render_empty_scene(const Ref &p_rend } else { environment = scenario->fallback_environment; } + RID compositor = scenario->compositor; RENDER_TIMESTAMP("Render Empty 3D Scene"); RendererSceneRender::CameraData camera_data; camera_data.set_camera(Transform3D(), Projection(), true, false); - scene_render->render_scene(p_render_buffers, &camera_data, &camera_data, PagedArray(), PagedArray(), PagedArray(), PagedArray(), PagedArray(), PagedArray(), PagedArray(), environment, RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr); + scene_render->render_scene(p_render_buffers, &camera_data, &camera_data, PagedArray(), PagedArray(), PagedArray(), PagedArray(), PagedArray(), PagedArray(), PagedArray(), environment, RID(), compositor, p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr); #endif } @@ -3514,7 +3543,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int camera_data.set_camera(xform, cm, false, false); Ref render_buffers = RSG::light_storage->reflection_probe_atlas_get_render_buffers(scenario->reflection_atlas); - _render_scene(&camera_data, render_buffers, environment, RID(), RSG::light_storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows); + _render_scene(&camera_data, render_buffers, environment, RID(), RID(), RSG::light_storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows); } else { //do roughness postprocess step until it believes it's done diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index f48902a4efaf..86090aa416ee 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -80,6 +80,7 @@ class RendererSceneCull : public RenderingMethod { bool vaspect; RID env; RID attributes; + RID compositor; Transform3D transform; @@ -107,6 +108,7 @@ class RendererSceneCull : public RenderingMethod { virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers); virtual void camera_set_environment(RID p_camera, RID p_env); virtual void camera_set_camera_attributes(RID p_camera, RID p_attributes); + virtual void camera_set_compositor(RID p_camera, RID p_compositor); virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable); virtual bool is_camera(RID p_camera) const; @@ -324,6 +326,7 @@ class RendererSceneCull : public RenderingMethod { RID environment; RID fallback_environment; RID camera_attributes; + RID compositor; RID reflection_probe_shadow_atlas; RID reflection_atlas; uint64_t used_viewport_visibility_bits; @@ -359,6 +362,7 @@ class RendererSceneCull : public RenderingMethod { virtual void scenario_set_environment(RID p_scenario, RID p_environment); virtual void scenario_set_camera_attributes(RID p_scenario, RID p_attributes); virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment); + virtual void scenario_set_compositor(RID p_scenario, RID p_compositor); virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count); virtual bool is_scenario(RID p_scenario) const; virtual RID scenario_get_environment(RID p_scenario); @@ -1065,6 +1069,7 @@ class RendererSceneCull : public RenderingMethod { _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_scren_mesh_lod_threshold, uint32_t p_visible_layers = 0xFFFFFF); RID _render_get_environment(RID p_camera, RID p_scenario); + RID _render_get_compositor(RID p_camera, RID p_scenario); struct Cull { struct Shadow { @@ -1134,7 +1139,7 @@ class RendererSceneCull : public RenderingMethod { _FORCE_INLINE_ bool _visibility_parent_check(const CullData &p_cull_data, const InstanceData &p_instance_data); bool _render_reflection_probe_step(Instance *p_instance, int p_step); - void _render_scene(const RendererSceneRender::CameraData *p_camera_data, const Ref &p_render_buffers, RID p_environment, RID p_force_camera_attributes, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows = true, RenderInfo *r_render_info = nullptr); + void _render_scene(const RendererSceneRender::CameraData *p_camera_data, const Ref &p_render_buffers, RID p_environment, RID p_force_camera_attributes, RID p_compositor, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows = true, RenderInfo *r_render_info = nullptr); void render_empty_scene(const Ref &p_render_buffers, RID p_scenario, RID p_shadow_atlas); void render_camera(const Ref &p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, uint32_t p_jitter_phase_count, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref &p_xr_interface, RenderingMethod::RenderInfo *r_render_info = nullptr); @@ -1167,6 +1172,28 @@ class RendererSceneCull : public RenderingMethod { PASS2(sky_set_material, RID, RID) PASS4R(Ref, sky_bake_panorama, RID, float, bool, const Size2i &) + // Compositor effect + + PASS0R(RID, compositor_effect_allocate) + PASS1(compositor_effect_initialize, RID) + + PASS1RC(bool, is_compositor_effect, RID) + + PASS2(compositor_effect_set_enabled, RID, bool) + PASS3(compositor_effect_set_callback, RID, RS::CompositorEffectCallbackType, const Callable &) + PASS3(compositor_effect_set_flag, RID, RS::CompositorEffectFlags, bool) + + // Compositor + + PASS0R(RID, compositor_allocate) + PASS1(compositor_initialize, RID) + + PASS1RC(bool, is_compositor, RID) + + PASS2(compositor_set_compositor_effects, RID, const TypedArray &) + + // Environment + PASS0R(RID, environment_allocate) PASS1(environment_initialize, RID) diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp index 95eb29a8915d..76c779900fba 100644 --- a/servers/rendering/renderer_scene_render.cpp +++ b/servers/rendering/renderer_scene_render.cpp @@ -186,6 +186,64 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count } } +/* Compositor effect API */ + +RID RendererSceneRender::compositor_effect_allocate() { + return compositor_storage.compositor_effect_allocate(); +} + +void RendererSceneRender::compositor_effect_initialize(RID p_rid) { + compositor_storage.compositor_effect_initialize(p_rid); +} + +void RendererSceneRender::compositor_effect_free(RID p_rid) { + compositor_storage.compositor_effect_free(p_rid); +} + +bool RendererSceneRender::is_compositor_effect(RID p_effect) const { + return compositor_storage.is_compositor_effect(p_effect); +} + +void RendererSceneRender::compositor_effect_set_enabled(RID p_effect, bool p_enabled) { + compositor_storage.compositor_effect_set_enabled(p_effect, p_enabled); +} + +void RendererSceneRender::compositor_effect_set_callback(RID p_effect, RS::CompositorEffectCallbackType p_callback_type, const Callable &p_callback) { + compositor_storage.compositor_effect_set_callback(p_effect, p_callback_type, p_callback); +} + +void RendererSceneRender::compositor_effect_set_flag(RID p_effect, RS::CompositorEffectFlags p_flag, bool p_set) { + compositor_storage.compositor_effect_set_flag(p_effect, p_flag, p_set); +} + +/* Compositor API */ + +RID RendererSceneRender::compositor_allocate() { + return compositor_storage.compositor_allocate(); +} + +void RendererSceneRender::compositor_initialize(RID p_rid) { + compositor_storage.compositor_initialize(p_rid); +} + +void RendererSceneRender::compositor_free(RID p_rid) { + compositor_storage.compositor_free(p_rid); +} + +bool RendererSceneRender::is_compositor(RID p_rid) const { + return compositor_storage.is_compositor(p_rid); +} + +void RendererSceneRender::compositor_set_compositor_effects(RID p_compositor, const TypedArray &p_effects) { + Vector rids; + for (int i = 0; i < p_effects.size(); i++) { + RID rid = p_effects[i]; + rids.push_back(rid); + } + + compositor_storage.compositor_set_compositor_effects(p_compositor, rids); +} + /* Environment API */ RID RendererSceneRender::environment_allocate() { diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h index c6e2c23e9118..719efa4df228 100644 --- a/servers/rendering/renderer_scene_render.h +++ b/servers/rendering/renderer_scene_render.h @@ -35,6 +35,7 @@ #include "core/templates/paged_array.h" #include "servers/rendering/renderer_geometry_instance.h" #include "servers/rendering/rendering_method.h" +#include "servers/rendering/storage/compositor_storage.h" #include "servers/rendering/storage/environment_storage.h" #include "storage/render_scene_buffers.h" #include "storage/utilities.h" @@ -42,6 +43,7 @@ class RendererSceneRender { private: RendererEnvironmentStorage environment_storage; + RendererCompositorStorage compositor_storage; public: enum { @@ -73,6 +75,27 @@ class RendererSceneRender { virtual void sky_set_material(RID p_sky, RID p_material) = 0; virtual Ref sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) = 0; + /* COMPOSITOR EFFECT API */ + + RID compositor_effect_allocate(); + void compositor_effect_initialize(RID p_rid); + void compositor_effect_free(RID p_rid); + + bool is_compositor_effect(RID p_compositor) const; + void compositor_effect_set_enabled(RID p_compositor, bool p_enabled); + void compositor_effect_set_callback(RID p_compositor, RS::CompositorEffectCallbackType p_callback_type, const Callable &p_callback); + void compositor_effect_set_flag(RID p_compositor, RS::CompositorEffectFlags p_flag, bool p_set); + + /* COMPOSITOR API */ + + RID compositor_allocate(); + void compositor_initialize(RID p_rid); + void compositor_free(RID p_rid); + + bool is_compositor(RID p_compositor) const; + + void compositor_set_compositor_effects(RID p_compositor, const TypedArray &p_effects); + /* ENVIRONMENT API */ RID environment_allocate(); @@ -289,7 +312,7 @@ class RendererSceneRender { void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect); }; - virtual void render_scene(const Ref &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, 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, const PagedArray &p_fog_volumes, RID p_environment, RID p_camera_attributes, 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_mesh_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, RenderingMethod::RenderInfo *r_render_info = nullptr) = 0; + virtual void render_scene(const Ref &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, 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, const PagedArray &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_compositor, 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_mesh_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, RenderingMethod::RenderInfo *r_render_info = nullptr) = 0; virtual void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, 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/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h index 5f21207579df..4d9b56508000 100644 --- a/servers/rendering/rendering_device_binds.h +++ b/servers/rendering/rendering_device_binds.h @@ -134,6 +134,7 @@ class RDAttachmentFormat : public RefCounted { class RDFramebufferPass : public RefCounted { GDCLASS(RDFramebufferPass, RefCounted) friend class RenderingDevice; + friend class FramebufferCacheRD; RD::FramebufferPass base; @@ -443,6 +444,7 @@ class RDShaderFile : public Resource { class RDUniform : public RefCounted { GDCLASS(RDUniform, RefCounted) friend class RenderingDevice; + friend class UniformSetCacheRD; RD::Uniform base; public: diff --git a/servers/rendering/rendering_method.h b/servers/rendering/rendering_method.h index be14a50eec22..456984675279 100644 --- a/servers/rendering/rendering_method.h +++ b/servers/rendering/rendering_method.h @@ -47,6 +47,7 @@ class RenderingMethod { virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers) = 0; virtual void camera_set_environment(RID p_camera, RID p_env) = 0; virtual void camera_set_camera_attributes(RID p_camera, RID p_attributes) = 0; + virtual void camera_set_compositor(RID p_camera, RID p_compositor) = 0; virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable) = 0; virtual bool is_camera(RID p_camera) const = 0; @@ -60,6 +61,7 @@ class RenderingMethod { virtual void scenario_set_environment(RID p_scenario, RID p_environment) = 0; virtual void scenario_set_camera_attributes(RID p_scenario, RID p_attributes) = 0; virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment) = 0; + virtual void scenario_set_compositor(RID p_scenario, RID p_compositor) = 0; virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count) = 0; virtual bool is_scenario(RID p_scenario) const = 0; virtual RID scenario_get_environment(RID p_scenario) = 0; @@ -117,6 +119,27 @@ class RenderingMethod { virtual void sky_set_material(RID p_sky, RID p_material) = 0; virtual Ref sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) = 0; + /* COMPOSITOR EFFECT API */ + + virtual RID compositor_effect_allocate() = 0; + virtual void compositor_effect_initialize(RID p_rid) = 0; + + virtual bool is_compositor_effect(RID p_compositor) const = 0; + + virtual void compositor_effect_set_enabled(RID p_compositor, bool p_enabled) = 0; + + virtual void compositor_effect_set_callback(RID p_compositor, RS::CompositorEffectCallbackType p_callback_type, const Callable &p_callback) = 0; + virtual void compositor_effect_set_flag(RID p_compositor, RS::CompositorEffectFlags p_flag, bool p_set) = 0; + + /* COMPOSITOR API */ + + virtual RID compositor_allocate() = 0; + virtual void compositor_initialize(RID p_rid) = 0; + + virtual bool is_compositor(RID p_compositor) const = 0; + + virtual void compositor_set_compositor_effects(RID p_env, const TypedArray &p_effects) = 0; + /* ENVIRONMENT API */ virtual RID environment_allocate() = 0; diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index c218007a789f..17622ba3111f 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -591,6 +591,7 @@ class RenderingServerDefault : public RenderingServer { FUNC2(camera_set_cull_mask, RID, uint32_t) FUNC2(camera_set_environment, RID, RID) FUNC2(camera_set_camera_attributes, RID, RID) + FUNC2(camera_set_compositor, RID, RID) FUNC2(camera_set_use_vertical_aspect, RID, bool) /* OCCLUDER */ @@ -676,7 +677,7 @@ class RenderingServerDefault : public RenderingServer { FUNC2(viewport_set_vrs_mode, RID, ViewportVRSMode) FUNC2(viewport_set_vrs_texture, RID, RID) - /* ENVIRONMENT API */ + /* COMPOSITOR EFFECT */ #undef server_name #undef ServerName @@ -684,6 +685,19 @@ class RenderingServerDefault : public RenderingServer { #define ServerName RenderingMethod #define server_name RSG::scene + FUNCRIDSPLIT(compositor_effect) + FUNC2(compositor_effect_set_enabled, RID, bool) + FUNC3(compositor_effect_set_callback, RID, CompositorEffectCallbackType, const Callable &) + FUNC3(compositor_effect_set_flag, RID, CompositorEffectFlags, bool) + + /* COMPOSITOR */ + + FUNC2(compositor_set_compositor_effects, RID, const TypedArray &) + + FUNCRIDSPLIT(compositor) + + /* ENVIRONMENT API */ + FUNC1(voxel_gi_set_quality, VoxelGIQuality) /* SKY API */ @@ -694,6 +708,8 @@ class RenderingServerDefault : public RenderingServer { FUNC2(sky_set_material, RID, RID) FUNC4R(Ref, sky_bake_panorama, RID, float, bool, const Size2i &) + /* ENVIRONMENT */ + FUNCRIDSPLIT(environment) FUNC2(environment_set_background, RID, EnvironmentBG) @@ -779,6 +795,7 @@ class RenderingServerDefault : public RenderingServer { FUNC2(scenario_set_environment, RID, RID) FUNC2(scenario_set_camera_attributes, RID, RID) FUNC2(scenario_set_fallback_environment, RID, RID) + FUNC2(scenario_set_compositor, RID, RID) /* INSTANCING API */ FUNCRIDSPLIT(instance) diff --git a/servers/rendering/storage/compositor_storage.cpp b/servers/rendering/storage/compositor_storage.cpp new file mode 100644 index 000000000000..d9a70a093d3e --- /dev/null +++ b/servers/rendering/storage/compositor_storage.cpp @@ -0,0 +1,160 @@ +/**************************************************************************/ +/* compositor_storage.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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 "compositor_storage.h" + +// Storage + +RendererCompositorStorage *RendererCompositorStorage::singleton = nullptr; + +RendererCompositorStorage::RendererCompositorStorage() { + singleton = this; +} + +RendererCompositorStorage::~RendererCompositorStorage() { + singleton = nullptr; +} + +// Compositor effect + +RID RendererCompositorStorage::compositor_effect_allocate() { + return compositor_effects_owner.allocate_rid(); +} + +void RendererCompositorStorage::compositor_effect_initialize(RID p_rid) { + compositor_effects_owner.initialize_rid(p_rid, CompositorEffect()); +} + +void RendererCompositorStorage::compositor_effect_free(RID p_rid) { + // TODO remove this RID from any compositor that uses it. + + compositor_effects_owner.free(p_rid); +} + +void RendererCompositorStorage::compositor_effect_set_callback(RID p_effect, RS::CompositorEffectCallbackType p_callback_type, const Callable &p_callback) { + CompositorEffect *effect = compositor_effects_owner.get_or_null(p_effect); + ERR_FAIL_NULL(effect); + + effect->callback_type = p_callback_type; + effect->callback = p_callback; +} + +void RendererCompositorStorage::compositor_effect_set_enabled(RID p_effect, bool p_enabled) { + CompositorEffect *effect = compositor_effects_owner.get_or_null(p_effect); + ERR_FAIL_NULL(effect); + + effect->is_enabled = p_enabled; +} + +bool RendererCompositorStorage::compositor_effect_get_enabled(RID p_effect) const { + CompositorEffect *effect = compositor_effects_owner.get_or_null(p_effect); + ERR_FAIL_NULL_V(effect, false); + + return effect->is_enabled; +} + +RS::CompositorEffectCallbackType RendererCompositorStorage::compositor_effect_get_callback_type(RID p_effect) const { + CompositorEffect *effect = compositor_effects_owner.get_or_null(p_effect); + ERR_FAIL_NULL_V(effect, RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_MAX); + + return effect->callback_type; +} + +Callable RendererCompositorStorage::compositor_effect_get_callback(RID p_effect) const { + CompositorEffect *effect = compositor_effects_owner.get_or_null(p_effect); + ERR_FAIL_NULL_V(effect, Callable()); + + return effect->callback; +} + +void RendererCompositorStorage::compositor_effect_set_flag(RID p_effect, RS::CompositorEffectFlags p_flag, bool p_set) { + CompositorEffect *effect = compositor_effects_owner.get_or_null(p_effect); + ERR_FAIL_NULL(effect); + + if (p_set) { + effect->flags.set_flag(p_flag); + } else { + effect->flags.clear_flag(p_flag); + } +} + +bool RendererCompositorStorage::compositor_effect_get_flag(RID p_effect, RS::CompositorEffectFlags p_flag) const { + CompositorEffect *effect = compositor_effects_owner.get_or_null(p_effect); + ERR_FAIL_NULL_V(effect, false); + + return effect->flags.has_flag(p_flag); +} + +// Compositor + +RID RendererCompositorStorage::compositor_allocate() { + return compositor_owner.allocate_rid(); +} + +void RendererCompositorStorage::compositor_initialize(RID p_rid) { + compositor_owner.initialize_rid(p_rid, Compositor()); +} + +void RendererCompositorStorage::compositor_free(RID p_rid) { + compositor_owner.free(p_rid); +} + +// compositor effects + +void RendererCompositorStorage::compositor_set_compositor_effects(RID p_compositor, const Vector &p_effects) { + Compositor *compositor = compositor_owner.get_or_null(p_compositor); + ERR_FAIL_NULL(compositor); + + compositor->compositor_effects.clear(); + for (const RID &effect : p_effects) { + if (is_compositor_effect(effect)) { + compositor->compositor_effects.push_back(effect); + } + } +} + +Vector RendererCompositorStorage::compositor_get_compositor_effects(RID p_compositor, RS::CompositorEffectCallbackType p_callback_type, bool p_enabled_only) const { + Compositor *compositor = compositor_owner.get_or_null(p_compositor); + ERR_FAIL_NULL_V(compositor, Vector()); + + if (p_enabled_only || p_callback_type != RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_ANY) { + Vector effects; + + for (RID rid : compositor->compositor_effects) { + if ((!p_enabled_only || compositor_effect_get_enabled(rid)) && (p_callback_type == RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_ANY || compositor_effect_get_callback_type(rid) == p_callback_type)) { + effects.push_back(rid); + } + } + + return effects; + } else { + return compositor->compositor_effects; + } +} diff --git a/servers/rendering/storage/compositor_storage.h b/servers/rendering/storage/compositor_storage.h new file mode 100644 index 000000000000..0d6942e27f8b --- /dev/null +++ b/servers/rendering/storage/compositor_storage.h @@ -0,0 +1,98 @@ +/**************************************************************************/ +/* compositor_storage.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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 COMPOSITOR_STORAGE_H +#define COMPOSITOR_STORAGE_H + +#include "core/templates/rid_owner.h" +#include "servers/rendering_server.h" + +class RendererCompositorStorage { +private: + static RendererCompositorStorage *singleton; + + // Compositor effect + struct CompositorEffect { + bool is_enabled = true; + RS::CompositorEffectCallbackType callback_type; + Callable callback; + + BitField flags; + }; + + mutable RID_Owner compositor_effects_owner; + + // Compositor + struct Compositor { + // Compositor effects + Vector compositor_effects; + }; + + mutable RID_Owner compositor_owner; + +public: + static RendererCompositorStorage *get_singleton() { return singleton; } + + RendererCompositorStorage(); + virtual ~RendererCompositorStorage(); + + // Compositor effect + RID compositor_effect_allocate(); + void compositor_effect_initialize(RID p_rid); + void compositor_effect_free(RID p_rid); + + bool is_compositor_effect(RID p_effect) const { + return compositor_effects_owner.owns(p_effect); + } + + void compositor_effect_set_enabled(RID p_effect, bool p_enabled); + bool compositor_effect_get_enabled(RID p_effect) const; + + void compositor_effect_set_callback(RID p_effect, RS::CompositorEffectCallbackType p_callback_type, const Callable &p_callback); + RS::CompositorEffectCallbackType compositor_effect_get_callback_type(RID p_effect) const; + Callable compositor_effect_get_callback(RID p_effect) const; + + void compositor_effect_set_flag(RID p_effect, RS::CompositorEffectFlags p_flag, bool p_set); + bool compositor_effect_get_flag(RID p_effect, RS::CompositorEffectFlags p_flag) const; + + // Compositor + RID compositor_allocate(); + void compositor_initialize(RID p_rid); + void compositor_free(RID p_rid); + + bool is_compositor(RID p_compositor) const { + return compositor_owner.owns(p_compositor); + } + + void compositor_set_compositor_effects(RID p_compositor, const Vector &p_effects); + Vector compositor_get_compositor_effects(RID p_compositor, RS::CompositorEffectCallbackType p_callback_type = RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_ANY, bool p_enabled_only = true) const; +}; + +#endif // COMPOSITOR_STORAGE_H diff --git a/servers/rendering/storage/environment_storage.cpp b/servers/rendering/storage/environment_storage.cpp index ec26e3650943..fcd2a3d3b880 100644 --- a/servers/rendering/storage/environment_storage.cpp +++ b/servers/rendering/storage/environment_storage.cpp @@ -30,6 +30,20 @@ #include "environment_storage.h" +// Storage + +RendererEnvironmentStorage *RendererEnvironmentStorage::singleton = nullptr; + +RendererEnvironmentStorage::RendererEnvironmentStorage() { + singleton = this; +} + +RendererEnvironmentStorage::~RendererEnvironmentStorage() { + singleton = nullptr; +} + +// Environment + RID RendererEnvironmentStorage::environment_allocate() { return environment_owner.allocate_rid(); } diff --git a/servers/rendering/storage/environment_storage.h b/servers/rendering/storage/environment_storage.h index c077e093daa7..9f78808ff757 100644 --- a/servers/rendering/storage/environment_storage.h +++ b/servers/rendering/storage/environment_storage.h @@ -36,6 +36,9 @@ class RendererEnvironmentStorage { private: + static RendererEnvironmentStorage *singleton; + + // Environment struct Environment { // Note, we capture and store all environment parameters received from Godot here. // Not all renderers support all effects and should just ignore the bits they don't support. @@ -155,6 +158,12 @@ class RendererEnvironmentStorage { mutable RID_Owner environment_owner; public: + static RendererEnvironmentStorage *get_singleton() { return singleton; } + + RendererEnvironmentStorage(); + virtual ~RendererEnvironmentStorage(); + + // Environment RID environment_allocate(); void environment_initialize(RID p_rid); void environment_free(RID p_rid); diff --git a/servers/rendering/storage/render_data.cpp b/servers/rendering/storage/render_data.cpp new file mode 100644 index 000000000000..fa00a5c672b4 --- /dev/null +++ b/servers/rendering/storage/render_data.cpp @@ -0,0 +1,69 @@ +/**************************************************************************/ +/* render_data.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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 "render_data.h" + +void RenderData::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_render_scene_buffers"), &RenderData::get_render_scene_buffers); + ClassDB::bind_method(D_METHOD("get_render_scene_data"), &RenderData::get_render_scene_data); + ClassDB::bind_method(D_METHOD("get_environment"), &RenderData::get_environment); + ClassDB::bind_method(D_METHOD("get_camera_attributes"), &RenderData::get_camera_attributes); +} + +void RenderDataExtension::_bind_methods() { + GDVIRTUAL_BIND(_get_render_scene_buffers); + GDVIRTUAL_BIND(_get_render_scene_data) + GDVIRTUAL_BIND(_get_environment) + GDVIRTUAL_BIND(_get_camera_attributes) +} + +Ref RenderDataExtension::get_render_scene_buffers() const { + Ref ret; + GDVIRTUAL_CALL(_get_render_scene_buffers, ret); + return ret; +} + +RenderSceneData *RenderDataExtension::get_render_scene_data() const { + RenderSceneData *ret = nullptr; + GDVIRTUAL_CALL(_get_render_scene_data, ret); + return ret; +} + +RID RenderDataExtension::get_environment() const { + RID ret; + GDVIRTUAL_CALL(_get_environment, ret); + return ret; +} + +RID RenderDataExtension::get_camera_attributes() const { + RID ret; + GDVIRTUAL_CALL(_get_camera_attributes, ret); + return ret; +} diff --git a/servers/rendering/storage/render_data.h b/servers/rendering/storage/render_data.h new file mode 100644 index 000000000000..36aa6db784c4 --- /dev/null +++ b/servers/rendering/storage/render_data.h @@ -0,0 +1,70 @@ +/**************************************************************************/ +/* render_data.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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 RENDER_DATA_H +#define RENDER_DATA_H + +#include "core/object/object.h" +#include "render_scene_buffers.h" +#include "render_scene_data.h" + +class RenderData : public Object { + GDCLASS(RenderData, Object); + +protected: + static void _bind_methods(); + +public: + virtual Ref get_render_scene_buffers() const = 0; + virtual RenderSceneData *get_render_scene_data() const = 0; + + virtual RID get_environment() const = 0; + virtual RID get_camera_attributes() const = 0; +}; + +class RenderDataExtension : public RenderData { + GDCLASS(RenderDataExtension, RenderData); + +protected: + static void _bind_methods(); + + virtual Ref get_render_scene_buffers() const override; + virtual RenderSceneData *get_render_scene_data() const override; + + virtual RID get_environment() const override; + virtual RID get_camera_attributes() const override; + + GDVIRTUAL0RC(Ref, _get_render_scene_buffers) + GDVIRTUAL0RC(RenderSceneData *, _get_render_scene_data) + GDVIRTUAL0RC(RID, _get_environment) + GDVIRTUAL0RC(RID, _get_camera_attributes) +}; + +#endif // RENDER_DATA_H diff --git a/servers/rendering/storage/render_scene_data.cpp b/servers/rendering/storage/render_scene_data.cpp new file mode 100644 index 000000000000..a1d8f524b431 --- /dev/null +++ b/servers/rendering/storage/render_scene_data.cpp @@ -0,0 +1,88 @@ +/**************************************************************************/ +/* render_scene_data.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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 "render_scene_data.h" + +void RenderSceneData::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_cam_transform"), &RenderSceneData::get_cam_transform); + ClassDB::bind_method(D_METHOD("get_cam_projection"), &RenderSceneData::get_cam_projection); + + ClassDB::bind_method(D_METHOD("get_view_count"), &RenderSceneData::get_view_count); + ClassDB::bind_method(D_METHOD("get_view_eye_offset", "view"), &RenderSceneData::get_view_eye_offset); + ClassDB::bind_method(D_METHOD("get_view_projection", "view"), &RenderSceneData::get_view_projection); + + ClassDB::bind_method(D_METHOD("get_uniform_buffer"), &RenderSceneData::get_uniform_buffer); +} + +void RenderSceneDataExtension::_bind_methods() { + GDVIRTUAL_BIND(_get_cam_transform); + GDVIRTUAL_BIND(_get_cam_projection); + GDVIRTUAL_BIND(_get_view_count); + GDVIRTUAL_BIND(_get_view_eye_offset, "view"); + GDVIRTUAL_BIND(_get_view_projection, "view"); + + GDVIRTUAL_BIND(_get_uniform_buffer); +} + +Transform3D RenderSceneDataExtension::get_cam_transform() const { + Transform3D ret; + GDVIRTUAL_CALL(_get_cam_transform, ret); + return ret; +} + +Projection RenderSceneDataExtension::get_cam_projection() const { + Projection ret; + GDVIRTUAL_CALL(_get_cam_projection, ret); + return ret; +} + +uint32_t RenderSceneDataExtension::get_view_count() const { + uint32_t ret = 0; + GDVIRTUAL_CALL(_get_view_count, ret); + return ret; +} + +Vector3 RenderSceneDataExtension::get_view_eye_offset(uint32_t p_view) const { + Vector3 ret; + GDVIRTUAL_CALL(_get_view_eye_offset, p_view, ret); + return ret; +} + +Projection RenderSceneDataExtension::get_view_projection(uint32_t p_view) const { + Projection ret; + GDVIRTUAL_CALL(_get_view_projection, p_view, ret); + return ret; +} + +RID RenderSceneDataExtension::get_uniform_buffer() const { + RID ret; + GDVIRTUAL_CALL(_get_uniform_buffer, ret); + return ret; +} diff --git a/servers/rendering/storage/render_scene_data.h b/servers/rendering/storage/render_scene_data.h new file mode 100644 index 000000000000..6a00cecc9677 --- /dev/null +++ b/servers/rendering/storage/render_scene_data.h @@ -0,0 +1,82 @@ +/**************************************************************************/ +/* render_scene_data.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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 RENDER_SCENE_DATA_H +#define RENDER_SCENE_DATA_H + +#include "core/object/class_db.h" +#include "core/object/gdvirtual.gen.inc" +#include "core/object/object.h" +#include "core/object/script_language.h" + +class RenderSceneData : public Object { + GDCLASS(RenderSceneData, Object); + +protected: + static void _bind_methods(); + +public: + virtual Transform3D get_cam_transform() const = 0; + virtual Projection get_cam_projection() const = 0; + + virtual uint32_t get_view_count() const = 0; + virtual Vector3 get_view_eye_offset(uint32_t p_view) const = 0; + virtual Projection get_view_projection(uint32_t p_view) const = 0; + + virtual RID get_uniform_buffer() const = 0; +}; + +class RenderSceneDataExtension : public RenderSceneData { + GDCLASS(RenderSceneDataExtension, RenderSceneData); + +protected: + static void _bind_methods(); + +public: + virtual Transform3D get_cam_transform() const override; + virtual Projection get_cam_projection() const override; + + virtual uint32_t get_view_count() const override; + virtual Vector3 get_view_eye_offset(uint32_t p_view) const override; + virtual Projection get_view_projection(uint32_t p_view) const override; + + virtual RID get_uniform_buffer() const override; + + GDVIRTUAL0RC(Transform3D, _get_cam_transform) + GDVIRTUAL0RC(Projection, _get_cam_projection) + + GDVIRTUAL0RC(uint32_t, _get_view_count) + GDVIRTUAL1RC(Vector3, _get_view_eye_offset, uint32_t) + GDVIRTUAL1RC(Projection, _get_view_projection, uint32_t) + + GDVIRTUAL0RC(RID, _get_uniform_buffer) +}; + +#endif // RENDER_SCENE_DATA_H diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 655b748d3f7b..6e9b525f31cf 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2762,6 +2762,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("camera_set_cull_mask", "camera", "layers"), &RenderingServer::camera_set_cull_mask); ClassDB::bind_method(D_METHOD("camera_set_environment", "camera", "env"), &RenderingServer::camera_set_environment); ClassDB::bind_method(D_METHOD("camera_set_camera_attributes", "camera", "effects"), &RenderingServer::camera_set_camera_attributes); + ClassDB::bind_method(D_METHOD("camera_set_compositor", "camera", "compositor"), &RenderingServer::camera_set_compositor); ClassDB::bind_method(D_METHOD("camera_set_use_vertical_aspect", "camera", "enable"), &RenderingServer::camera_set_use_vertical_aspect); /* VIEWPORT */ @@ -2928,6 +2929,32 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(SKY_MODE_INCREMENTAL); BIND_ENUM_CONSTANT(SKY_MODE_REALTIME); + /* COMPOSITOR EFFECT API */ + + ClassDB::bind_method(D_METHOD("compositor_effect_create"), &RenderingServer::compositor_effect_create); + ClassDB::bind_method(D_METHOD("compositor_effect_set_enabled", "effect", "enabled"), &RenderingServer::compositor_effect_set_enabled); + ClassDB::bind_method(D_METHOD("compositor_effect_set_callback", "effect", "callback_type", "callback"), &RenderingServer::compositor_effect_set_callback); + ClassDB::bind_method(D_METHOD("compositor_effect_set_flag", "effect", "flag", "set"), &RenderingServer::compositor_effect_set_flag); + + BIND_ENUM_CONSTANT(COMPOSITOR_EFFECT_FLAG_ACCESS_RESOLVED_COLOR); + BIND_ENUM_CONSTANT(COMPOSITOR_EFFECT_FLAG_ACCESS_RESOLVED_DEPTH); + BIND_ENUM_CONSTANT(COMPOSITOR_EFFECT_FLAG_NEEDS_MOTION_VECTORS); + BIND_ENUM_CONSTANT(COMPOSITOR_EFFECT_FLAG_NEEDS_ROUGHNESS); + BIND_ENUM_CONSTANT(COMPOSITOR_EFFECT_FLAG_NEEDS_SEPARATE_SPECULAR); + + BIND_ENUM_CONSTANT(COMPOSITOR_EFFECT_CALLBACK_TYPE_PRE_OPAQUE); + BIND_ENUM_CONSTANT(COMPOSITOR_EFFECT_CALLBACK_TYPE_POST_OPAQUE); + BIND_ENUM_CONSTANT(COMPOSITOR_EFFECT_CALLBACK_TYPE_POST_SKY); + BIND_ENUM_CONSTANT(COMPOSITOR_EFFECT_CALLBACK_TYPE_PRE_TRANSPARENT); + BIND_ENUM_CONSTANT(COMPOSITOR_EFFECT_CALLBACK_TYPE_POST_TRANSPARENT); + BIND_ENUM_CONSTANT(COMPOSITOR_EFFECT_CALLBACK_TYPE_ANY); + + /* COMPOSITOR */ + + ClassDB::bind_method(D_METHOD("compositor_create"), &RenderingServer::compositor_create); + + ClassDB::bind_method(D_METHOD("compositor_set_compositor_effects", "compositor", "effects"), &RenderingServer::compositor_set_compositor_effects); + /* ENVIRONMENT */ ClassDB::bind_method(D_METHOD("environment_create"), &RenderingServer::environment_create); @@ -3071,6 +3098,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("scenario_set_environment", "scenario", "environment"), &RenderingServer::scenario_set_environment); ClassDB::bind_method(D_METHOD("scenario_set_fallback_environment", "scenario", "environment"), &RenderingServer::scenario_set_fallback_environment); ClassDB::bind_method(D_METHOD("scenario_set_camera_attributes", "scenario", "effects"), &RenderingServer::scenario_set_camera_attributes); + ClassDB::bind_method(D_METHOD("scenario_set_compositor", "scenario", "compositor"), &RenderingServer::scenario_set_compositor); /* INSTANCE */ diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 6b00213440d6..02a90dad3b1c 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -816,6 +816,7 @@ class RenderingServer : public Object { virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers) = 0; virtual void camera_set_environment(RID p_camera, RID p_env) = 0; virtual void camera_set_camera_attributes(RID p_camera, RID p_camera_attributes) = 0; + virtual void camera_set_compositor(RID p_camera, RID p_compositor) = 0; virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable) = 0; /* VIEWPORT API */ @@ -1046,6 +1047,37 @@ class RenderingServer : public Object { virtual void sky_set_material(RID p_sky, RID p_material) = 0; virtual Ref sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) = 0; + /* COMPOSITOR EFFECTS API */ + + enum CompositorEffectFlags { + COMPOSITOR_EFFECT_FLAG_ACCESS_RESOLVED_COLOR = 1, + COMPOSITOR_EFFECT_FLAG_ACCESS_RESOLVED_DEPTH = 2, + COMPOSITOR_EFFECT_FLAG_NEEDS_MOTION_VECTORS = 4, + COMPOSITOR_EFFECT_FLAG_NEEDS_ROUGHNESS = 8, + COMPOSITOR_EFFECT_FLAG_NEEDS_SEPARATE_SPECULAR = 16, + }; + + enum CompositorEffectCallbackType { + COMPOSITOR_EFFECT_CALLBACK_TYPE_PRE_OPAQUE, + COMPOSITOR_EFFECT_CALLBACK_TYPE_POST_OPAQUE, + COMPOSITOR_EFFECT_CALLBACK_TYPE_POST_SKY, + COMPOSITOR_EFFECT_CALLBACK_TYPE_PRE_TRANSPARENT, + COMPOSITOR_EFFECT_CALLBACK_TYPE_POST_TRANSPARENT, + COMPOSITOR_EFFECT_CALLBACK_TYPE_MAX, + COMPOSITOR_EFFECT_CALLBACK_TYPE_ANY = -1, + }; + + virtual RID compositor_effect_create() = 0; + virtual void compositor_effect_set_enabled(RID p_effect, bool p_enabled) = 0; + virtual void compositor_effect_set_callback(RID p_effect, CompositorEffectCallbackType p_callback_type, const Callable &p_callback) = 0; + virtual void compositor_effect_set_flag(RID p_effect, CompositorEffectFlags p_flag, bool p_set) = 0; + + /* COMPOSITOR API */ + + virtual RID compositor_create() = 0; + + virtual void compositor_set_compositor_effects(RID p_compositor, const TypedArray &p_effects) = 0; + /* ENVIRONMENT API */ virtual RID environment_create() = 0; @@ -1241,6 +1273,7 @@ class RenderingServer : public Object { virtual void scenario_set_environment(RID p_scenario, RID p_environment) = 0; virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment) = 0; virtual void scenario_set_camera_attributes(RID p_scenario, RID p_camera_attributes) = 0; + virtual void scenario_set_compositor(RID p_scenario, RID p_compositor) = 0; /* INSTANCING API */ @@ -1737,6 +1770,8 @@ VARIANT_ENUM_CAST(RenderingServer::ViewportSDFOversize); VARIANT_ENUM_CAST(RenderingServer::ViewportSDFScale); VARIANT_ENUM_CAST(RenderingServer::ViewportVRSMode); VARIANT_ENUM_CAST(RenderingServer::SkyMode); +VARIANT_ENUM_CAST(RenderingServer::CompositorEffectCallbackType); +VARIANT_ENUM_CAST(RenderingServer::CompositorEffectFlags); VARIANT_ENUM_CAST(RenderingServer::EnvironmentBG); VARIANT_ENUM_CAST(RenderingServer::EnvironmentAmbientSource); VARIANT_ENUM_CAST(RenderingServer::EnvironmentReflectionSource);