summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp22
-rw-r--r--drivers/gles3/storage/texture_storage.cpp61
-rw-r--r--drivers/gles3/storage/texture_storage.h3
3 files changed, 86 insertions, 0 deletions
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 6cc6b8224c..eb9ca49c5d 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<RenderSceneBuffers> &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 dae722186c..4baffa93d5 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -1782,7 +1782,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) {
@@ -1848,6 +1905,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 fedda6b260..9803e9548a 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;