From 7fa41f17a608c75d164d313331105140b69cf494 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Thu, 24 Jan 2019 17:00:33 -0300 Subject: Makes screen texture work in GLES2 (2D for now), fixes #23604 --- drivers/gles2/rasterizer_canvas_gles2.cpp | 74 +++++++++++++++++++++++++++++- drivers/gles2/rasterizer_storage_gles2.cpp | 12 ++++- drivers/gles2/shader_gles2.h | 2 + drivers/gles2/shaders/copy.glsl | 2 +- 4 files changed, 85 insertions(+), 5 deletions(-) diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp index 047eaaf0ac..6f686690bf 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.cpp +++ b/drivers/gles2/rasterizer_canvas_gles2.cpp @@ -1162,7 +1162,65 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur void RasterizerCanvasGLES2::_copy_texscreen(const Rect2 &p_rect) { - // This isn't really working yet, so disabling for now. + if (storage->frame.current_rt->copy_screen_effect.color == 0) { + ERR_EXPLAIN("Can't use screen texture copying in a render target configured without copy buffers"); + ERR_FAIL(); + } + + glDisable(GL_BLEND); + + state.canvas_texscreen_used = true; + + Vector2 wh(storage->frame.current_rt->width, storage->frame.current_rt->height); + + Color copy_section(p_rect.position.x / wh.x, p_rect.position.y / wh.y, p_rect.size.x / wh.x, p_rect.size.y / wh.y); + + if (p_rect != Rect2()) { + storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, true); + } + + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->copy_screen_effect.fbo); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); + + glClearColor(1, 0, 1, 1); + glClear(GL_COLOR_BUFFER_BIT); + + storage->shaders.copy.bind(); + storage->shaders.copy.set_uniform(CopyShaderGLES2::COPY_SECTION, copy_section); + + const Vector2 vertpos[4] = { + Vector2(-1, -1), + Vector2(-1, 1), + Vector2(1, 1), + Vector2(1, -1), + }; + + const Vector2 uvpos[4] = { + Vector2(0, 0), + Vector2(0, 1), + Vector2(1, 1), + Vector2(1, 0) + }; + + const int indexpos[6] = { + 0, 1, 2, + 2, 3, 0 + }; + + _draw_polygon(indexpos, 6, 4, vertpos, uvpos, NULL, false); + + storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, false); + + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //back to front + + // back to canvas, force rebind + state.using_texture_rect = false; + state.canvas_shader.bind(); + _bind_canvas_texture(state.current_tex, state.current_normal); + _set_uniforms(); + + glEnable(GL_BLEND); } void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform) { @@ -1178,6 +1236,7 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons state.current_tex = RID(); state.current_tex_ptr = NULL; state.current_normal = RID(); + state.canvas_texscreen_used = false; glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); @@ -1265,7 +1324,18 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons if (shader_ptr) { if (shader_ptr->canvas_item.uses_screen_texture) { - _copy_texscreen(Rect2()); + if (!state.canvas_texscreen_used) { + //copy if not copied before + _copy_texscreen(Rect2()); + + // blend mode will have been enabled so make sure we disable it again later on + //last_blend_mode = last_blend_mode != RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_DISABLED ? last_blend_mode : -1; + } + + if (storage->frame.current_rt->copy_screen_effect.color) { + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->copy_screen_effect.color); + } } if (shader_ptr != shader_cache) { diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index 22c05d9d77..f0deff4791 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -4251,7 +4251,8 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // copy texscreen buffers - { + if (!(rt->flags[RasterizerStorage::RENDER_TARGET_NO_SAMPLING])) { + int w = rt->width; int h = rt->height; @@ -4259,10 +4260,17 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { glBindTexture(GL_TEXTURE_2D, rt->copy_screen_effect.color); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glGenFramebuffers(1, &rt->copy_screen_effect.fbo); glBindFramebuffer(GL_FRAMEBUFFER, rt->copy_screen_effect.fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->copy_screen_effect.color, 0); + + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { diff --git a/drivers/gles2/shader_gles2.h b/drivers/gles2/shader_gles2.h index 468971471c..5805432d09 100644 --- a/drivers/gles2/shader_gles2.h +++ b/drivers/gles2/shader_gles2.h @@ -465,6 +465,8 @@ public: void set_custom_shader(uint32_t p_code_id); void free_custom_shader(uint32_t p_code_id); + uint32_t get_version_key() const { return conditional_version.version; } + void set_uniform_default(int p_idx, const Variant &p_value) { if (p_value.get_type() == Variant::NIL) { diff --git a/drivers/gles2/shaders/copy.glsl b/drivers/gles2/shaders/copy.glsl index f3c2a7eec4..286ba6b8c0 100644 --- a/drivers/gles2/shaders/copy.glsl +++ b/drivers/gles2/shaders/copy.glsl @@ -29,7 +29,7 @@ varying vec2 uv_interp; varying vec2 uv2_interp; #ifdef USE_COPY_SECTION -uniform vec4 copy_section; +uniform highp vec4 copy_section; #endif void main() { -- cgit v1.2.3