diff options
Diffstat (limited to 'servers/rendering')
35 files changed, 1388 insertions, 133 deletions
diff --git a/servers/rendering/dummy/rasterizer_scene_dummy.h b/servers/rendering/dummy/rasterizer_scene_dummy.h index fdf8df7587..083493003f 100644 --- a/servers/rendering/dummy/rasterizer_scene_dummy.h +++ b/servers/rendering/dummy/rasterizer_scene_dummy.h @@ -145,7 +145,7 @@ public: void voxel_gi_set_quality(RS::VoxelGIQuality) override {} - void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &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<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &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<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {} void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) override {} @@ -168,6 +168,12 @@ public: 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_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index 94355f2c5f..65fcdb9751 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -311,12 +311,14 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 child_item_count = ci->ysort_children_count + 1; child_items = (Item **)alloca(child_item_count * sizeof(Item *)); + ci->ysort_xform = ci->xform.affine_inverse(); + ci->ysort_pos = Vector2(); + ci->ysort_modulate = Color(1, 1, 1, 1); + ci->ysort_index = 0; ci->ysort_parent_abs_z_index = parent_z; child_items[0] = ci; int i = 1; _collect_ysort_children(ci, Transform2D(), p_material_owner, Color(1, 1, 1, 1), child_items, i, p_z); - ci->ysort_xform = ci->xform.affine_inverse(); - ci->ysort_modulate = Color(1, 1, 1, 1); SortArray<Item *, ItemPtrSort> sorter; sorter.sort(child_items, child_item_count); diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h index 011493f1f6..6169d386b5 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 c454d35d28..fa6e78750b 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<Color>() : 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 51fd0aaffb..12af8822b4 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 fd81430983..ac93aca6bb 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 71b8136245..ec037b71fa 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<Cache *>(p_userdata)); } +RID FramebufferCacheRD::get_cache_multipass_array(const TypedArray<RID> &p_textures, const TypedArray<RDFramebufferPass> &p_passes, uint32_t p_views) { + Vector<RID> textures; + Vector<RD::FramebufferPass> 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<RDFramebufferPass> 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 cae95ccce0..abb2a5808d 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 <typename... Args> RID get_cache(Args... args) { @@ -301,6 +305,8 @@ public: return _allocate_from_data(p_views, h, table_idx, p_textures, p_passes); } + static RID get_cache_multipass_array(const TypedArray<RID> &p_textures, const TypedArray<RDFramebufferPass> &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 35c0bdd595..62ecec3991 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<RenderSceneBuffers> 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<RID> 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<RID> 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<RID> 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<RenderSceneBuffersRD> 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<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &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<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &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<RenderSceneBuffers> &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 4811ae3b44..5c5f11aba6 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<RenderSceneBuffersRD> render_buffers; - RenderSceneDataRD *scene_data; - - const PagedArray<RenderGeometryInstance *> *instances = nullptr; - const PagedArray<RID> *lights = nullptr; - const PagedArray<RID> *reflection_probes = nullptr; - const PagedArray<RID> *voxel_gi_instances = nullptr; - const PagedArray<RID> *decals = nullptr; - const PagedArray<RID> *lightmaps = nullptr; - const PagedArray<RID> *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<int> cube_shadows; - LocalVector<int> shadows; - LocalVector<int> 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 @@ protected: 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 @@ public: virtual void base_uniforms_changed() = 0; - virtual void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &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<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &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<RenderGeometryInstance *> &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 45226ec47c..b3d27cc6ed 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 0000000000..ac4fbba75b --- /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<RenderSceneBuffers> 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 0000000000..2f61899a18 --- /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<RenderSceneBuffers> 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<RenderSceneBuffersRD> render_buffers; + RenderSceneDataRD *scene_data = nullptr; + + const PagedArray<RenderGeometryInstance *> *instances = nullptr; + const PagedArray<RID> *lights = nullptr; + const PagedArray<RID> *reflection_probes = nullptr; + const PagedArray<RID> *voxel_gi_instances = nullptr; + const PagedArray<RID> *decals = nullptr; + const PagedArray<RID> *lightmaps = nullptr; + const PagedArray<RID> *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<int> cube_shadows; + LocalVector<int> shadows; + LocalVector<int> 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 0000000000..75b9ee2da7 --- /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 c338dd0377..8dc74820e2 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 5b8a74de83..c885ad52d1 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 @@ public: 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<RDTextureFormat> &p_texture_format, const Ref<RDTextureView> &p_view = Ref<RDTextureView>(), bool p_unique = true); RID _create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName &p_view_name, const Ref<RDTextureView> p_view = Ref<RDTextureView>()); Ref<RDTextureFormat> _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<RDTextureView> p_view = Ref<RDTextureView>()); - // 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 @@ private: } } - 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 @@ private: } } - 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 @@ private: } } - 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 @@ private: } } - 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 86f0f5acf2..dc1e64ddcc 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 9453966a86..f6785942ed 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 @@ public: 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 1f67d5e258..bcd8e78a71 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<RDUniform> &p_uniforms) { + Vector<RD::Uniform> uniforms; + + for (int i = 0; i < p_uniforms.size(); i++) { + Ref<RDUniform> 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 50243e715d..c3b95f5f93 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 <typename... Args> RID get_cache(RID p_shader, uint32_t p_set, Args... args) { @@ -214,6 +218,8 @@ public: 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<RDUniform> &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 b8f14bb611..59d70958f1 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<RenderSceneBuffers> &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<RenderSceneBuffers> &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<RenderSceneBuffers> &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<RenderSceneBuffers> &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<RenderSceneBuffers> &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<RenderGeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), 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<RenderGeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), 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<RenderSceneBuffers> 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 f48902a4ef..86090aa416 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -80,6 +80,7 @@ public: bool vaspect; RID env; RID attributes; + RID compositor; Transform3D transform; @@ -107,6 +108,7 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: _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 @@ public: _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<RenderSceneBuffers> &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<RenderSceneBuffers> &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<RenderSceneBuffers> &p_render_buffers, RID p_scenario, RID p_shadow_atlas); void render_camera(const Ref<RenderSceneBuffers> &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<XRInterface> &p_xr_interface, RenderingMethod::RenderInfo *r_render_info = nullptr); @@ -1167,6 +1172,28 @@ public: PASS2(sky_set_material, RID, RID) PASS4R(Ref<Image>, 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<RID> &) + + // 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 95eb29a891..76c779900f 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<RID> &p_effects) { + Vector<RID> 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 c6e2c23e91..719efa4df2 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 @@ public: virtual void sky_set_material(RID p_sky, RID p_material) = 0; virtual Ref<Image> 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<RID> &p_effects); + /* ENVIRONMENT API */ RID environment_allocate(); @@ -289,7 +312,7 @@ public: 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<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &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<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &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<RenderGeometryInstance *> &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<RenderGeometryInstance *> &p_instances) = 0; diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h index 5f21207579..4d9b565080 100644 --- a/servers/rendering/rendering_device_binds.h +++ b/servers/rendering/rendering_device_binds.h @@ -134,6 +134,7 @@ protected: class RDFramebufferPass : public RefCounted { GDCLASS(RDFramebufferPass, RefCounted) friend class RenderingDevice; + friend class FramebufferCacheRD; RD::FramebufferPass base; @@ -443,6 +444,7 @@ protected: 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 be14a50eec..4569846752 100644 --- a/servers/rendering/rendering_method.h +++ b/servers/rendering/rendering_method.h @@ -47,6 +47,7 @@ public: 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 @@ public: 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 @@ public: virtual void sky_set_material(RID p_sky, RID p_material) = 0; virtual Ref<Image> 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<RID> &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 c218007a78..17622ba311 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -591,6 +591,7 @@ public: 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 @@ public: 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 @@ public: #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<RID> &) + + FUNCRIDSPLIT(compositor) + + /* ENVIRONMENT API */ + FUNC1(voxel_gi_set_quality, VoxelGIQuality) /* SKY API */ @@ -694,6 +708,8 @@ public: FUNC2(sky_set_material, RID, RID) FUNC4R(Ref<Image>, sky_bake_panorama, RID, float, bool, const Size2i &) + /* ENVIRONMENT */ + FUNCRIDSPLIT(environment) FUNC2(environment_set_background, RID, EnvironmentBG) @@ -779,6 +795,7 @@ public: 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 0000000000..d9a70a093d --- /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<RID> &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<RID> 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<RID>()); + + if (p_enabled_only || p_callback_type != RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_ANY) { + Vector<RID> 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 0000000000..0d6942e27f --- /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<RS::CompositorEffectFlags> flags; + }; + + mutable RID_Owner<CompositorEffect, true> compositor_effects_owner; + + // Compositor + struct Compositor { + // Compositor effects + Vector<RID> compositor_effects; + }; + + mutable RID_Owner<Compositor, true> 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<RID> &p_effects); + Vector<RID> 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 ec26e36509..7b75a12a19 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(); } @@ -417,11 +431,6 @@ void RendererEnvironmentStorage::environment_set_glow(RID p_env, bool p_enable, Environment *env = environment_owner.get_or_null(p_env); ERR_FAIL_NULL(env); ERR_FAIL_COND_MSG(p_levels.size() != 7, "Size of array of glow levels must be 7"); -#ifdef DEBUG_ENABLED - if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility" && p_enable) { - WARN_PRINT_ONCE_ED("Glow is not supported when using the GL Compatibility backend yet. Support will be added in a future release."); - } -#endif env->glow_enabled = p_enable; env->glow_levels = p_levels; env->glow_intensity = p_intensity; diff --git a/servers/rendering/storage/environment_storage.h b/servers/rendering/storage/environment_storage.h index c077e093da..9f78808ff7 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 @@ private: mutable RID_Owner<Environment, true> 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 0000000000..fa00a5c672 --- /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<RenderSceneBuffers> RenderDataExtension::get_render_scene_buffers() const { + Ref<RenderSceneBuffers> 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 0000000000..36aa6db784 --- /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<RenderSceneBuffers> 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<RenderSceneBuffers> 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<RenderSceneBuffers>, _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 0000000000..a1d8f524b4 --- /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 0000000000..6a00cecc96 --- /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 |