diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp index 1568867663d..a363b03dd86 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.cpp +++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp @@ -533,7 +533,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, bool p_alpha_to_one, bool p_linear, bool p_normal) { +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, bool p_linear, bool p_normal, const Rect2 &p_src_rect) { UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); MaterialStorage *material_storage = MaterialStorage::get_singleton(); @@ -568,6 +568,14 @@ void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffe copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_NORMAL; } + if (p_src_rect != Rect2()) { + copy_to_fb.push_constant.section[0] = p_src_rect.position.x; + copy_to_fb.push_constant.section[1] = p_src_rect.position.y; + copy_to_fb.push_constant.section[2] = p_src_rect.size.x; + copy_to_fb.push_constant.section[3] = p_src_rect.size.y; + copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_USE_SRC_SECTION; + } + // setup our uniforms RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h index d18971a6767..014f78e2b9b 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.h +++ b/servers/rendering/renderer_rd/effects/copy_effects.h @@ -191,6 +191,7 @@ private: COPY_TO_FB_FLAG_ALPHA_TO_ONE = (1 << 5), COPY_TO_FB_FLAG_LINEAR = (1 << 6), COPY_TO_FB_FLAG_NORMAL = (1 << 7), + COPY_TO_FB_FLAG_USE_SRC_SECTION = (1 << 8), }; struct CopyToFbPushConstant { @@ -329,7 +330,7 @@ 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, bool alpha_to_one = false, bool p_linear = false, bool p_normal = 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, bool p_linear = false, bool p_normal = false, const Rect2 &p_src_rect = Rect2()); 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_to_drawlist(RD::DrawListID p_draw_list, RD::FramebufferFormatID p_fb_format, RID p_source_rd_texture, bool p_linear = false); void copy_raster(RID p_source_texture, RID p_dest_framebuffer); 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 7192e596eb5..3f9d1cce793 100644 --- a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl @@ -21,6 +21,7 @@ #define FLAG_ALPHA_TO_ONE (1 << 5) #define FLAG_LINEAR (1 << 6) #define FLAG_NORMAL (1 << 7) +#define FLAG_USE_SRC_SECTION (1 << 8) #ifdef USE_MULTIVIEW layout(location = 0) out vec3 uv_interp; @@ -54,6 +55,10 @@ void main() { if (bool(params.flags & FLAG_FLIP_Y)) { uv_interp.y = 1.0 - uv_interp.y; } + + if (bool(params.flags & FLAG_USE_SRC_SECTION)) { + uv_interp = params.section.xy + uv_interp * params.section.zw; + } } #[fragment] diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index da046bf6b17..af30a328666 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -3820,7 +3820,10 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) { copy_effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, !rt->use_hdr, true); } else { - copy_effects->copy_to_fb_rect(rt->color, rt->backbuffer_fb, region, false, false, false, false, RID(), false, true); + Rect2 src_rect = Rect2(region); + src_rect.position /= Size2(rt->size); + src_rect.size /= Size2(rt->size); + copy_effects->copy_to_fb_rect(rt->color, rt->backbuffer_fb, region, false, false, false, false, RID(), false, true, false, false, src_rect); } if (!p_gen_mipmaps) {