diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 6cc6b8224c3f..eb9ca49c5d4e 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1994,6 +1994,28 @@ void RasterizerSceneGLES3::render_scene(const Ref &p_render_ _draw_sky(render_data.environment, render_data.cam_projection, render_data.cam_transform, sky_energy_multiplier, p_camera_data->view_count > 1, flip_y); } + if (scene_state.used_screen_texture || scene_state.used_depth_texture) { + texture_storage->copy_scene_to_backbuffer(rt, scene_state.used_screen_texture, scene_state.used_depth_texture); + glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->fbo); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, rt->backbuffer_fbo); + if (scene_state.used_screen_texture) { + glBlitFramebuffer(0, 0, rt->size.x, rt->size.y, + 0, 0, rt->size.x, rt->size.y, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 5); + glBindTexture(GL_TEXTURE_2D, rt->backbuffer); + } + if (scene_state.used_depth_texture) { + glBlitFramebuffer(0, 0, rt->size.x, rt->size.y, + 0, 0, rt->size.x, rt->size.y, + GL_DEPTH_BUFFER_BIT, GL_NEAREST); + glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 6); + glBindTexture(GL_TEXTURE_2D, rt->backbuffer_depth); + } + glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo); + } + RENDER_TIMESTAMP("Render 3D Transparent Pass"); glEnable(GL_BLEND); diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index ce6694332824..e4a3e8788832 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -1780,7 +1780,64 @@ void TextureStorage::_create_render_target_backbuffer(RenderTarget *rt) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } } +void GLES3::TextureStorage::copy_scene_to_backbuffer(RenderTarget *rt, const bool uses_screen_texture, const bool uses_depth_texture) { + if (rt->backbuffer != 0 && rt->backbuffer_depth != 0) { + return; + } + Config *config = Config::get_singleton(); + bool use_multiview = rt->view_count > 1 && config->multiview_supported; + GLenum texture_target = use_multiview ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D; + if (rt->backbuffer_fbo == 0) { + glGenFramebuffers(1, &rt->backbuffer_fbo); + } + glBindFramebuffer(GL_FRAMEBUFFER, rt->backbuffer_fbo); + if (rt->backbuffer == 0 && uses_screen_texture) { + glGenTextures(1, &rt->backbuffer); + glBindTexture(texture_target, rt->backbuffer); + if (use_multiview) { + glTexImage3D(texture_target, 0, rt->color_internal_format, rt->size.x, rt->size.y, rt->view_count, 0, rt->color_format, rt->color_type, nullptr); + } else { + glTexImage2D(texture_target, 0, rt->color_internal_format, rt->size.x, rt->size.y, 0, rt->color_format, rt->color_type, nullptr); + } + + glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); +#ifndef IOS_ENABLED + if (use_multiview) { + glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, rt->backbuffer, 0, 0, rt->view_count); + } else { +#else + { +#endif + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->backbuffer, 0); + } + } + if (rt->backbuffer_depth == 0 && uses_depth_texture) { + glGenTextures(1, &rt->backbuffer_depth); + glBindTexture(texture_target, rt->backbuffer_depth); + if (use_multiview) { + glTexImage3D(texture_target, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, rt->view_count, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); + } else { + glTexImage2D(texture_target, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); + } + glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); +#ifndef IOS_ENABLED + if (use_multiview) { + glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, rt->backbuffer_depth, 0, 0, rt->view_count); + } else { +#else + { +#endif + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->backbuffer_depth, 0); + } + } +} void TextureStorage::_clear_render_target(RenderTarget *rt) { // there is nothing to clear when DIRECT_TO_SCREEN is used if (rt->direct_to_screen) { @@ -1846,6 +1903,10 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) { rt->backbuffer = 0; rt->backbuffer_fbo = 0; } + if (rt->backbuffer_depth != 0) { + glDeleteTextures(1, &rt->backbuffer_depth); + rt->backbuffer_depth = 0; + } _render_target_clear_sdf(rt); } diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h index fedda6b260ab..9803e9548a29 100644 --- a/drivers/gles3/storage/texture_storage.h +++ b/drivers/gles3/storage/texture_storage.h @@ -345,6 +345,7 @@ struct RenderTarget { GLuint depth = 0; GLuint backbuffer_fbo = 0; GLuint backbuffer = 0; + GLuint backbuffer_depth = 0; GLuint color_internal_format = GL_RGBA8; GLuint color_format = GL_RGBA; @@ -604,6 +605,8 @@ public: RenderTarget *get_render_target(RID p_rid) { return render_target_owner.get_or_null(p_rid); }; bool owns_render_target(RID p_rid) { return render_target_owner.owns(p_rid); }; + void copy_scene_to_backbuffer(RenderTarget *rt, const bool uses_screen_texture, const bool uses_depth_texture); + virtual RID render_target_create() override; virtual void render_target_free(RID p_rid) override;