diff options
Diffstat (limited to 'servers/rendering/renderer_rd')
20 files changed, 228 insertions, 78 deletions
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp index 27f977a80b..0ab21bc4ef 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.cpp +++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp @@ -56,6 +56,7 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) { blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n"); // BLUR_MODE_GAUSSIAN_GLOW blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); // BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE blur_modes.push_back("\n#define MODE_COPY\n"); // BLUR_MODE_COPY + blur_modes.push_back("\n#define MODE_SET_COLOR\n"); // BLUR_MODE_SET_COLOR blur_raster.shader.initialize(blur_modes); memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); @@ -105,6 +106,7 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) { copy_modes.push_back("\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_COPY2 copy_modes.push_back("\n#define MULTIVIEW\n"); // COPY_TO_FB_MULTIVIEW copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_MULTIVIEW_WITH_DEPTH + copy_modes.push_back("\n#define MODE_SET_COLOR\n"); // COPY_TO_FB_SET_COLOR copy_to_fb.shader.initialize(copy_modes); @@ -535,7 +537,7 @@ void CopyEffects::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuff RD::get_singleton()->draw_list_draw(draw_list, true); } -void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview) { +void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview, bool p_alpha_to_one) { UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); MaterialStorage *material_storage = MaterialStorage::get_singleton(); @@ -555,6 +557,9 @@ void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffe if (p_srgb) { copy_to_fb.push_constant.srgb = true; } + if (p_alpha_to_one) { + copy_to_fb.push_constant.alpha_to_one = true; + } // setup our uniforms RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); @@ -608,8 +613,6 @@ void CopyEffects::copy_raster(RID p_source_texture, RID p_dest_framebuffer) { RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[BLUR_MODE_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_texture), 0); RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); - - memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); RD::get_singleton()->draw_list_draw(draw_list, true); @@ -641,7 +644,6 @@ void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Re RID shader = copy.shader.version_get_shader(copy.shader_version, mode); ERR_FAIL_COND(shader.is_null()); - //HORIZONTAL RD::DrawListID compute_list = RD::get_singleton()->compute_list_begin(); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); @@ -654,6 +656,43 @@ void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Re RD::get_singleton()->compute_list_end(); } +void CopyEffects::gaussian_blur_raster(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_region, const Size2i &p_size) { + ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian blur with the clustered renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture); + + memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); + + BlurRasterMode blur_mode = BLUR_MODE_GAUSSIAN_BLUR; + + blur_raster.push_constant.pixel_size[0] = 1.0 / float(p_size.x); + blur_raster.push_constant.pixel_size[1] = 1.0 / float(p_size.y); + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + + RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode); + ERR_FAIL_COND(shader.is_null()); + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + + RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) { ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer."); @@ -882,6 +921,36 @@ void CopyEffects::set_color(RID p_dest_texture, const Color &p_color, const Rect RD::get_singleton()->compute_list_end(); } +void CopyEffects::set_color_raster(RID p_dest_texture, const Color &p_color, const Rect2i &p_region) { + ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the set_color shader with the clustered renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(©_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant)); + + copy_to_fb.push_constant.set_color[0] = p_color.r; + copy_to_fb.push_constant.set_color[1] = p_color.g; + copy_to_fb.push_constant.set_color[2] = p_color.b; + copy_to_fb.push_constant.set_color[3] = p_color.a; + + RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture); + + CopyToFBMode mode = COPY_TO_FB_SET_COLOR; + + RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_region); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer))); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + RD::get_singleton()->draw_list_set_push_constant(draw_list, ©_to_fb.push_constant, sizeof(CopyToFbPushConstant)); + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + void CopyEffects::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip) { UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h index 0ddb60ebef..cda4f70730 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.h +++ b/servers/rendering/renderer_rd/effects/copy_effects.h @@ -63,6 +63,8 @@ private: BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE, BLUR_MODE_COPY, + BLUR_MODE_SET_COLOR, + BLUR_MODE_MAX }; @@ -174,6 +176,8 @@ private: COPY_TO_FB_MULTIVIEW, COPY_TO_FB_MULTIVIEW_WITH_DEPTH, + + COPY_TO_FB_SET_COLOR, COPY_TO_FB_MAX, }; @@ -186,7 +190,9 @@ private: uint32_t force_luminance; uint32_t alpha_to_zero; uint32_t srgb; - uint32_t pad; + uint32_t alpha_to_one; + + float set_color[4]; }; struct CopyToFb { @@ -316,11 +322,12 @@ public: void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array); void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false); void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far); - void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false); + void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false, bool alpha_to_one = false); void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false); void copy_raster(RID p_source_texture, RID p_dest_framebuffer); void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst = false); + void gaussian_blur_raster(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_region, const Size2i &p_size); void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0); void gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0); @@ -328,6 +335,7 @@ public: void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size); void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false); + void set_color_raster(RID p_dest_texture, const Color &p_color, const Rect2i &p_region); void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip); void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size); diff --git a/servers/rendering/renderer_rd/effects/ss_effects.h b/servers/rendering/renderer_rd/effects/ss_effects.h index dfaf3881bb..a04dfc4a74 100644 --- a/servers/rendering/renderer_rd/effects/ss_effects.h +++ b/servers/rendering/renderer_rd/effects/ss_effects.h @@ -100,7 +100,7 @@ public: float sharpness = 0.98; float normal_rejection = 1.0; - Size2i full_screen_size = Size2i(); + Size2i full_screen_size; }; void ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings, RID p_linear_depth); @@ -137,7 +137,7 @@ public: float horizon = 0.06; float sharpness = 0.98; - Size2i full_screen_size = Size2i(); + Size2i full_screen_size; }; void ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings, RID p_linear_depth); diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp index 74082906c4..eece195946 100644 --- a/servers/rendering/renderer_rd/environment/fog.cpp +++ b/servers/rendering/renderer_rd/environment/fog.cpp @@ -727,9 +727,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P any_uses_time |= shader_data->uses_time; - Vector3i min = Vector3i(); - Vector3i max = Vector3i(); - Vector3i kernel_size = Vector3i(); + Vector3i min; + Vector3i max; + Vector3i kernel_size; Vector3 position = fog_volume_instance->transform.get_origin(); RS::FogVolumeShape volume_type = RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume); 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 0e4a223f69..2d1d0e0951 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -2311,6 +2311,8 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page scene_data.lod_distance_multiplier = p_lod_distance_multiplier; scene_data.dual_paraboloid_side = p_use_dp_flip ? -1 : 1; scene_data.opaque_prepass_threshold = 0.1f; + scene_data.time = time; + scene_data.time_step = time_step; RenderDataRD render_data; render_data.scene_data = &scene_data; @@ -2401,6 +2403,8 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con scene_data.z_far = p_cam_projection.get_z_far(); scene_data.dual_paraboloid_side = 0; scene_data.opaque_prepass_threshold = 0.0; + scene_data.time = time; + scene_data.time_step = time_step; RenderDataRD render_data; render_data.scene_data = &scene_data; @@ -2443,6 +2447,8 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform scene_data.material_uv2_mode = false; scene_data.opaque_prepass_threshold = 0.0f; scene_data.emissive_exposure_normalization = p_exposure_normalization; + scene_data.time = time; + scene_data.time_step = time_step; RenderDataRD render_data; render_data.scene_data = &scene_data; @@ -3083,7 +3089,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 19; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID vfog = RID(); + RID vfog; if (rb_data.is_valid() && rb->has_custom_data(RB_SCOPE_FOG)) { Ref<RendererRD::Fog::VolumetricFog> fog = rb->get_custom_data(RB_SCOPE_FOG); vfog = fog->fog_map; diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index c1b23af82f..6c8ce5265e 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -115,6 +115,9 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { actions.usage_flag_pointers["ALPHA"] = &uses_alpha; actions.usage_flag_pointers["ALPHA_SCISSOR_THRESHOLD"] = &uses_alpha_clip; + // Use alpha clip pipeline for alpha hash/dither. + // This prevents sorting issues inherent to alpha blending and allows such materials to cast shadows. + actions.usage_flag_pointers["ALPHA_HASH_SCALE"] = &uses_alpha_clip; actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass; actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss; @@ -151,6 +154,8 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { depth_test = DepthTest(depth_testi); cull_mode = Cull(cull_modei); uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps; + uses_vertex_time = gen_code.uses_vertex_time; + uses_fragment_time = gen_code.uses_fragment_time; #if 0 print_line("**compiling shader:"); @@ -457,11 +462,15 @@ bool SceneShaderForwardClustered::ShaderData::is_parameter_texture(const StringN } bool SceneShaderForwardClustered::ShaderData::is_animated() const { - return false; + return (uses_fragment_time && uses_discard) || (uses_vertex_time && uses_vertex); } bool SceneShaderForwardClustered::ShaderData::casts_shadows() const { - return false; + bool has_read_screen_alpha = uses_screen_texture || uses_depth_texture || uses_normal_texture; + bool has_base_alpha = (uses_alpha && !uses_alpha_clip) || has_read_screen_alpha; + bool has_alpha = has_base_alpha || uses_blend_alpha; + + return !has_alpha || (uses_depth_pre_pass && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED)); } Variant SceneShaderForwardClustered::ShaderData::get_default_parameter(const StringName &p_parameter) const { diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index a9a9fa94de..194edf2dcb 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -150,8 +150,8 @@ public: String code; HashMap<StringName, HashMap<int, RID>> default_texture_params; - DepthDraw depth_draw; - DepthTest depth_test; + DepthDraw depth_draw = DEPTH_DRAW_OPAQUE; + DepthTest depth_test = DEPTH_TEST_ENABLED; bool uses_point_size = false; bool uses_alpha = false; @@ -172,6 +172,8 @@ public: bool uses_depth_texture = false; bool uses_normal_texture = false; bool uses_time = false; + bool uses_vertex_time = false; + bool uses_fragment_time = false; bool writes_modelview_or_projection = false; bool uses_world_coordinates = false; bool uses_screen_texture_mipmaps = false; 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 898521ca4d..558aba62e1 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -1269,6 +1269,8 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr scene_data.lod_distance_multiplier = p_lod_distance_multiplier; scene_data.dual_paraboloid_side = p_use_dp_flip ? -1 : 1; scene_data.opaque_prepass_threshold = 0.1; + scene_data.time = time; + scene_data.time_step = time_step; RenderDataRD render_data; render_data.scene_data = &scene_data; @@ -1361,6 +1363,8 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c scene_data.material_uv2_mode = false; scene_data.opaque_prepass_threshold = 0.0f; scene_data.emissive_exposure_normalization = p_exposure_normalization; + scene_data.time = time; + scene_data.time_step = time_step; RenderDataRD render_data; render_data.scene_data = &scene_data; @@ -1484,6 +1488,8 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const scene_data.z_far = p_cam_projection.get_z_far(); scene_data.dual_paraboloid_side = 0; scene_data.opaque_prepass_threshold = 0.0; + scene_data.time = time; + scene_data.time_step = time_step; RenderDataRD render_data; render_data.scene_data = &scene_data; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 02bd30d32d..ee82fa7c7d 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -116,6 +116,9 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { actions.usage_flag_pointers["ALPHA"] = &uses_alpha; actions.usage_flag_pointers["ALPHA_SCISSOR_THRESHOLD"] = &uses_alpha_clip; + // Use alpha clip pipeline for alpha hash/dither. + // This prevents sorting issues inherent to alpha blending and allows such materials to cast shadows. + actions.usage_flag_pointers["ALPHA_HASH_SCALE"] = &uses_alpha_clip; actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass; // actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss; @@ -150,6 +153,8 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { depth_draw = DepthDraw(depth_drawi); depth_test = DepthTest(depth_testi); + uses_vertex_time = gen_code.uses_vertex_time; + uses_fragment_time = gen_code.uses_fragment_time; #if 0 print_line("**compiling shader:"); @@ -412,11 +417,15 @@ bool SceneShaderForwardMobile::ShaderData::is_parameter_texture(const StringName } bool SceneShaderForwardMobile::ShaderData::is_animated() const { - return false; + return (uses_fragment_time && uses_discard) || (uses_vertex_time && uses_vertex); } bool SceneShaderForwardMobile::ShaderData::casts_shadows() const { - return false; + bool has_read_screen_alpha = uses_screen_texture || uses_depth_texture || uses_normal_texture; + bool has_base_alpha = (uses_alpha && !uses_alpha_clip) || has_read_screen_alpha; + bool has_alpha = has_base_alpha || uses_blend_alpha; + + return !has_alpha || (uses_depth_pre_pass && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED)); } Variant SceneShaderForwardMobile::ShaderData::get_default_parameter(const StringName &p_parameter) const { diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index f67665a02f..5b51cfc8c3 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -132,6 +132,8 @@ public: bool uses_depth_texture = false; bool uses_normal_texture = false; bool uses_time = false; + bool uses_vertex_time = false; + bool uses_fragment_time = false; bool writes_modelview_or_projection = false; bool uses_world_coordinates = false; diff --git a/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl index cb06250cf2..31aabbe9d2 100644 --- a/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl @@ -53,30 +53,31 @@ void main() { #ifdef MODE_GAUSSIAN_BLUR - // Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect - - // note, for blur blur.luminance_multiplier is irrelavant, we would be multiplying and then dividing by this amount. - - if (bool(blur.flags & FLAG_HORIZONTAL)) { - vec2 pix_size = blur.pixel_size; - pix_size *= 0.5; //reading from larger buffer, so use more samples - vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.214607; - color += texture(source_color, uv_interp + vec2(1.0, 0.0) * pix_size) * 0.189879; - color += texture(source_color, uv_interp + vec2(2.0, 0.0) * pix_size) * 0.131514; - color += texture(source_color, uv_interp + vec2(3.0, 0.0) * pix_size) * 0.071303; - color += texture(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size) * 0.189879; - color += texture(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size) * 0.131514; - color += texture(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size) * 0.071303; - frag_color = color; - } else { - vec2 pix_size = blur.pixel_size; - vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.38774; - color += texture(source_color, uv_interp + vec2(0.0, 1.0) * pix_size) * 0.24477; - color += texture(source_color, uv_interp + vec2(0.0, 2.0) * pix_size) * 0.06136; - color += texture(source_color, uv_interp + vec2(0.0, -1.0) * pix_size) * 0.24477; - color += texture(source_color, uv_interp + vec2(0.0, -2.0) * pix_size) * 0.06136; - frag_color = color; - } + // For Gaussian Blur we use 13 taps in a single pass instead of 12 taps over 2 passes. + // This minimizes the number of times we change framebuffers which is very important for mobile. + // Source: http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare + vec4 A = texture(source_color, uv_interp + blur.pixel_size * vec2(-1.0, -1.0)); + vec4 B = texture(source_color, uv_interp + blur.pixel_size * vec2(0.0, -1.0)); + vec4 C = texture(source_color, uv_interp + blur.pixel_size * vec2(1.0, -1.0)); + vec4 D = texture(source_color, uv_interp + blur.pixel_size * vec2(-0.5, -0.5)); + vec4 E = texture(source_color, uv_interp + blur.pixel_size * vec2(0.5, -0.5)); + vec4 F = texture(source_color, uv_interp + blur.pixel_size * vec2(-1.0, 0.0)); + vec4 G = texture(source_color, uv_interp); + vec4 H = texture(source_color, uv_interp + blur.pixel_size * vec2(1.0, 0.0)); + vec4 I = texture(source_color, uv_interp + blur.pixel_size * vec2(-0.5, 0.5)); + vec4 J = texture(source_color, uv_interp + blur.pixel_size * vec2(0.5, 0.5)); + vec4 K = texture(source_color, uv_interp + blur.pixel_size * vec2(-1.0, 1.0)); + vec4 L = texture(source_color, uv_interp + blur.pixel_size * vec2(0.0, 1.0)); + vec4 M = texture(source_color, uv_interp + blur.pixel_size * vec2(1.0, 1.0)); + + float base_weight = 0.5 / 4.0; + float lesser_weight = 0.125 / 4.0; + + frag_color = (D + E + I + J) * base_weight; + frag_color += (A + B + G + F) * lesser_weight; + frag_color += (B + C + H + G) * lesser_weight; + frag_color += (F + G + L + K) * lesser_weight; + frag_color += (G + H + M + L) * lesser_weight; #endif #ifdef MODE_GAUSSIAN_GLOW diff --git a/servers/rendering/renderer_rd/shaders/effects/copy.glsl b/servers/rendering/renderer_rd/shaders/effects/copy.glsl index bfe329b8ec..5cc2ed7622 100644 --- a/servers/rendering/renderer_rd/shaders/effects/copy.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/copy.glsl @@ -194,10 +194,10 @@ void main() { color = min(color * feedback, vec4(params.glow_luminance_cap)); } -#endif +#endif // MODE_GLOW imageStore(dest_buffer, pos + params.target, color); -#endif +#endif // MODE_GAUSSIAN_BLUR #ifdef MODE_SIMPLE_COPY @@ -227,7 +227,7 @@ void main() { imageStore(dest_buffer, pos + params.target, color); -#endif +#endif // MODE_SIMPLE_COPY #ifdef MODE_SIMPLE_COPY_DEPTH @@ -239,7 +239,7 @@ void main() { imageStore(dest_buffer, pos + params.target, vec4(color.r)); -#endif +#endif // MODE_SIMPLE_COPY_DEPTH #ifdef MODE_LINEARIZE_DEPTH_COPY @@ -253,7 +253,7 @@ void main() { } imageStore(dest_buffer, pos + params.target, color); -#endif +#endif // MODE_LINEARIZE_DEPTH_COPY #if defined(MODE_CUBEMAP_TO_PANORAMA) || defined(MODE_CUBEMAP_ARRAY_TO_PANORAMA) @@ -276,7 +276,7 @@ void main() { vec4 color = textureLod(source_color, vec4(normal, params.camera_z_far), 0.0); //the biggest the lod the least the acne #endif imageStore(dest_buffer, pos + params.target, color); -#endif +#endif // defined(MODE_CUBEMAP_TO_PANORAMA) || defined(MODE_CUBEMAP_ARRAY_TO_PANORAMA) #ifdef MODE_SET_COLOR imageStore(dest_buffer, pos + params.target, params.set_color); diff --git a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl index 1c17eabb56..4d4e983b7f 100644 --- a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl @@ -26,7 +26,11 @@ layout(push_constant, std430) uniform Params { bool use_section; bool force_luminance; - uint pad[3]; + bool alpha_to_zero; + bool srgb; + bool alpha_to_one; + + vec4 color; } params; @@ -72,7 +76,9 @@ layout(push_constant, std430) uniform Params { bool force_luminance; bool alpha_to_zero; bool srgb; - uint pad; + bool alpha_to_one; + + vec4 color; } params; @@ -105,6 +111,10 @@ vec3 linear_to_srgb(vec3 color) { } void main() { +#ifdef MODE_SET_COLOR + frag_color = params.color; +#else + #ifdef MULTIVIEW vec3 uv = uv_interp; #else @@ -164,6 +174,10 @@ void main() { if (params.srgb) { color.rgb = linear_to_srgb(color.rgb); } + if (params.alpha_to_one) { + color.a = 1.0; + } frag_color = color; +#endif // MODE_SET_COLOR } diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl index 0bdf0e50aa..7440c5748b 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl @@ -826,7 +826,8 @@ void fragment_shader(in SceneData scene_data) { // alpha hash can be used in unison with alpha antialiasing #ifdef ALPHA_HASH_USED - if (alpha < compute_alpha_hash_threshold(vertex, alpha_hash_scale)) { + vec3 object_pos = (inverse(read_model_matrix) * inv_view_matrix * vec4(vertex, 1.0)).xyz; + if (alpha < compute_alpha_hash_threshold(object_pos, alpha_hash_scale)) { discard; } #endif // ALPHA_HASH_USED diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl index 9aeaa6d978..cc44cff799 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl @@ -779,7 +779,8 @@ void main() { // alpha hash can be used in unison with alpha antialiasing #ifdef ALPHA_HASH_USED - if (alpha < compute_alpha_hash_threshold(vertex, alpha_hash_scale)) { + vec3 object_pos = (inverse(read_model_matrix) * inv_view_matrix * vec4(vertex, 1.0)).xyz; + if (alpha < compute_alpha_hash_threshold(object_pos, alpha_hash_scale)) { discard; } #endif // ALPHA_HASH_USED diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl index 97c913d489..71510ee06a 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl @@ -11,7 +11,8 @@ float hash_3d(vec3 p) { float compute_alpha_hash_threshold(vec3 pos, float hash_scale) { vec3 dx = dFdx(pos); - vec3 dy = dFdx(pos); + vec3 dy = dFdy(pos); + float delta_max_sqr = max(length(dx), length(dy)); float pix_scale = 1.0 / (hash_scale * delta_max_sqr); @@ -32,9 +33,9 @@ float compute_alpha_hash_threshold(vec3 pos, float hash_scale) { 1.0 - ((1.0 - a_interp) * (1.0 - a_interp) / (2.0 * min_lerp * (1.0 - min_lerp)))); float alpha_hash_threshold = - (lerp_factor < (1.0 - min_lerp)) ? ((lerp_factor < min_lerp) ? cases.x : cases.y) : cases.z; + (a_interp < (1.0 - min_lerp)) ? ((a_interp < min_lerp) ? cases.x : cases.y) : cases.z; - return clamp(alpha_hash_threshold, 0.0, 1.0); + return clamp(alpha_hash_threshold, 0.00001, 1.0); } #endif // ALPHA_HASH_USED diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp index c83473ef07..1dd95969e6 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp @@ -653,6 +653,14 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged if (light_data.shadow_opacity > 0.001) { RS::LightDirectionalShadowMode smode = light->directional_shadow_mode; + light_data.soft_shadow_scale = light->param[RS::LIGHT_PARAM_SHADOW_BLUR]; + light_data.softshadow_angle = angular_diameter; + light_data.bake_mode = light->bake_mode; + + if (angular_diameter <= 0.0) { + light_data.soft_shadow_scale *= RendererSceneRenderRD::get_singleton()->directional_shadow_quality_radius_get(); // Only use quality radius for PCF + } + int limit = smode == RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3); light_data.blend_splits = (smode != RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL) && light->directional_blend_splits; for (int j = 0; j < 4; j++) { @@ -669,7 +677,7 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged Projection shadow_mtx = rectm * bias * matrix * modelview; light_data.shadow_split_offsets[j] = split; - float bias_scale = light_instance->shadow_transform[j].bias_scale; + float bias_scale = light_instance->shadow_transform[j].bias_scale * light_data.soft_shadow_scale; light_data.shadow_bias[j] = light->param[RS::LIGHT_PARAM_SHADOW_BIAS] / 100.0 * bias_scale; light_data.shadow_normal_bias[j] = light->param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] * light_instance->shadow_transform[j].shadow_texel_size; light_data.shadow_transmittance_bias[j] = light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] * bias_scale; @@ -702,14 +710,6 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged float fade_start = light->param[RS::LIGHT_PARAM_SHADOW_FADE_START]; light_data.fade_from = -light_data.shadow_split_offsets[3] * MIN(fade_start, 0.999); //using 1.0 would break smoothstep light_data.fade_to = -light_data.shadow_split_offsets[3]; - - light_data.soft_shadow_scale = light->param[RS::LIGHT_PARAM_SHADOW_BLUR]; - light_data.softshadow_angle = angular_diameter; - light_data.bake_mode = light->bake_mode; - - if (angular_diameter <= 0.0) { - light_data.soft_shadow_scale *= RendererSceneRenderRD::get_singleton()->directional_shadow_quality_radius_get(); // Only use quality radius for PCF - } } r_directional_light_count++; @@ -978,6 +978,7 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged light_data.soft_shadow_size = 0.0; light_data.soft_shadow_scale *= RendererSceneRenderRD::get_singleton()->shadows_quality_radius_get(); // Only use quality radius for PCF } + light_data.shadow_bias *= light_data.soft_shadow_scale; } } else { light_data.shadow_opacity = 0.0; diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index 854976692e..51aa81745b 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -1027,6 +1027,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta uniforms.push_back(u); } p_particles->collision_textures_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 2); + p_particles->collision_heightmap_texture = collision_heightmap_texture; } } diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h index a9cc98abb9..49a8444e2f 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h @@ -54,8 +54,7 @@ private: float velocity[3]; uint32_t active; float color[4]; - float custom[3]; - float lifetime; + float custom[4]; }; struct ParticlesFrameParams { @@ -127,9 +126,6 @@ private: Collider colliders[MAX_COLLIDERS]; }; - struct ParticleEmissionBufferData { - }; - struct ParticleEmissionBuffer { struct Data { float xform[16]; @@ -412,7 +408,7 @@ public: bool owns_particles(RID p_rid) { return particles_owner.owns(p_rid); } virtual RID particles_allocate() override; - virtual void particles_initialize(RID p_particles_collision) override; + virtual void particles_initialize(RID p_rid) override; virtual void particles_free(RID p_rid) override; virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override; @@ -519,7 +515,7 @@ public: virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) override; virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) override; - virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override; + void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture); virtual void update_particles() override; @@ -546,7 +542,7 @@ public: virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override; Vector3 particles_collision_get_extents(RID p_particles_collision) const; virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override; - virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override; + RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const; Dependency *particles_collision_get_dependency(RID p_particles) const; diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index 077fde58b8..15c5687665 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -560,6 +560,7 @@ void TextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS: void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); ERR_FAIL_NULL(ct); + ct->texture_repeat = p_repeat; ct->clear_sets(); } @@ -3119,9 +3120,11 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons // TODO figure out stereo support here - //single texture copy for backbuffer - //RD::get_singleton()->texture_copy(rt->color, rt->backbuffer_mipmap0, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true); - copy_effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true); + if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) { + copy_effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true); + } else { + copy_effects->copy_to_fb_rect(rt->color, rt->backbuffer_fb, region, false, false, false, false, RID(), false, true); + } if (!p_gen_mipmaps) { return; @@ -3130,6 +3133,8 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons //then mipmap blur RID prev_texture = rt->color; //use color, not backbuffer, as bb has mipmaps. + Size2i texture_size = rt->size; + for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) { region.position.x >>= 1; region.position.y >>= 1; @@ -3137,7 +3142,13 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons region.size.y = MAX(1, region.size.y >> 1); RID mipmap = rt->backbuffer_mipmaps[i]; - copy_effects->gaussian_blur(prev_texture, mipmap, region, true); + if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) { + copy_effects->gaussian_blur(prev_texture, mipmap, region, true); + } else { + texture_size.x = MAX(1, texture_size.x >> 1); + texture_size.y = MAX(1, texture_size.y >> 1); + copy_effects->gaussian_blur_raster(prev_texture, mipmap, region, texture_size); + } prev_texture = mipmap; } RD::get_singleton()->draw_command_end_label(); @@ -3165,7 +3176,11 @@ void TextureStorage::render_target_clear_back_buffer(RID p_render_target, const } //single texture copy for backbuffer - copy_effects->set_color(rt->backbuffer_mipmap0, p_color, region, true); + if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) { + copy_effects->set_color(rt->backbuffer_mipmap0, p_color, region, true); + } else { + copy_effects->set_color(rt->backbuffer_mipmap0, p_color, region, true); + } } void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) { @@ -3191,6 +3206,7 @@ void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target, RD::get_singleton()->draw_command_begin_label("Gaussian Blur Mipmaps2"); //then mipmap blur RID prev_texture = rt->backbuffer_mipmap0; + Size2i texture_size = rt->size; for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) { region.position.x >>= 1; @@ -3199,7 +3215,14 @@ void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target, region.size.y = MAX(1, region.size.y >> 1); RID mipmap = rt->backbuffer_mipmaps[i]; - copy_effects->gaussian_blur(prev_texture, mipmap, region, true); + + if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) { + copy_effects->gaussian_blur(prev_texture, mipmap, region, true); + } else { + texture_size.x = MAX(1, texture_size.x >> 1); + texture_size.y = MAX(1, texture_size.y >> 1); + copy_effects->gaussian_blur_raster(prev_texture, mipmap, region, texture_size); + } prev_texture = mipmap; } RD::get_singleton()->draw_command_end_label(); |