diff options
author | clayjohn <claynjohn@gmail.com> | 2022-05-18 08:04:41 -0700 |
---|---|---|
committer | clayjohn <claynjohn@gmail.com> | 2022-05-24 11:00:34 -0700 |
commit | 3e20c1347db323438a76693bb9f7eea87f3a305d (patch) | |
tree | 98ed91197c8eaf8e4604089eea44c3c420ef5d22 | |
parent | d81c5eab8cfd1d91ef2cf1599a6b929ccbed0a3a (diff) |
Add clipping, backbuffer, and CanvasGroups to 2D GLES3 renderer
As well as significant consequent cleanup in the RenderTarget, Texture, and Canvas renderer code
27 files changed, 724 insertions, 1163 deletions
diff --git a/drivers/gles3/SCsub b/drivers/gles3/SCsub index fcb05a988d..5760fd714e 100644 --- a/drivers/gles3/SCsub +++ b/drivers/gles3/SCsub @@ -6,3 +6,4 @@ env.add_source_files(env.drivers_sources, "*.cpp") SConscript("shaders/SCsub") SConscript("storage/SCsub") +SConscript("effects/SCsub") diff --git a/drivers/gles3/effects/SCsub b/drivers/gles3/effects/SCsub new file mode 100644 index 0000000000..91e1140b75 --- /dev/null +++ b/drivers/gles3/effects/SCsub @@ -0,0 +1,5 @@ +#!/usr/bin/env python + +Import("env") + +env.add_source_files(env.drivers_sources, "*.cpp") diff --git a/drivers/gles3/effects/copy_effects.cpp b/drivers/gles3/effects/copy_effects.cpp new file mode 100644 index 0000000000..c8e6c2b476 --- /dev/null +++ b/drivers/gles3/effects/copy_effects.cpp @@ -0,0 +1,164 @@ +/*************************************************************************/ +/* copy_effects.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifdef GLES3_ENABLED + +#include "copy_effects.h" + +using namespace GLES3; + +CopyEffects *CopyEffects::singleton = nullptr; + +CopyEffects *CopyEffects::get_singleton() { + return singleton; +} + +CopyEffects::CopyEffects() { + singleton = this; + + copy.shader.initialize(); + copy.shader_version = copy.shader.version_create(); + copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_DEFAULT); + + { // Screen Triangle. + glGenBuffers(1, &screen_triangle); + glBindBuffer(GL_ARRAY_BUFFER, screen_triangle); + + const float qv[6] = { + -1.0f, + -1.0f, + 3.0f, + -1.0f, + -1.0f, + 3.0f, + }; + + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6, qv, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind + + glGenVertexArrays(1, &screen_triangle_array); + glBindVertexArray(screen_triangle_array); + glBindBuffer(GL_ARRAY_BUFFER, screen_triangle); + glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, nullptr); + glEnableVertexAttribArray(RS::ARRAY_VERTEX); + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind + } + + { // Screen Quad + + glGenBuffers(1, &quad); + glBindBuffer(GL_ARRAY_BUFFER, quad); + + const float qv[12] = { + -1.0f, + -1.0f, + 1.0f, + -1.0f, + 1.0f, + 1.0f, + -1.0f, + -1.0f, + 1.0f, + 1.0f, + -1.0f, + 1.0f, + }; + + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 12, qv, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind + + glGenVertexArrays(1, &quad_array); + glBindVertexArray(quad_array); + glBindBuffer(GL_ARRAY_BUFFER, quad); + glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, nullptr); + glEnableVertexAttribArray(RS::ARRAY_VERTEX); + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind + } +} + +CopyEffects::~CopyEffects() { + singleton = nullptr; + glDeleteBuffers(1, &screen_triangle); + glDeleteVertexArrays(1, &screen_triangle_array); + glDeleteBuffers(1, &quad); + glDeleteVertexArrays(1, &quad_array); +} + +void CopyEffects::copy_to_rect(const Rect2i &p_rect) { + copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_COPY_SECTION); + copy.shader.version_set_uniform(CopyShaderGLES3::COPY_SECTION, p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y, copy.shader_version, CopyShaderGLES3::MODE_COPY_SECTION); + glBindVertexArray(quad_array); + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); +} + +void CopyEffects::copy_screen() { + copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_DEFAULT); + glBindVertexArray(screen_triangle_array); + glDrawArrays(GL_TRIANGLES, 0, 3); + glBindVertexArray(0); +} + +void CopyEffects::bilinear_blur(GLuint p_source_texture, int p_mipmap_count, const Rect2i &p_region) { + GLuint framebuffers[2]; + glGenFramebuffers(2, framebuffers); + glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffers[0]); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_source_texture, 0); + + Rect2i source_region = p_region; + Rect2i dest_region = p_region; + for (int i = 1; i < p_mipmap_count; i++) { + dest_region.position.x >>= 1; + dest_region.position.y >>= 1; + dest_region.size.x = MAX(1, dest_region.size.x >> 1); + dest_region.size.y = MAX(1, dest_region.size.y >> 1); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffers[i % 2]); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_source_texture, i); + glBlitFramebuffer(source_region.position.x, source_region.position.y, source_region.size.x, source_region.size.y, + dest_region.position.x, dest_region.position.y, dest_region.size.x, dest_region.size.y, GL_COLOR_BUFFER_BIT, GL_LINEAR); + glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffers[i % 2]); + source_region = dest_region; + } + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glDeleteFramebuffers(2, framebuffers); +} + +void CopyEffects::set_color(const Color &p_color, const Rect2i &p_region) { + copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_SIMPLE_COLOR); + copy.shader.version_set_uniform(CopyShaderGLES3::COPY_SECTION, p_region.position.x, p_region.position.y, p_region.size.x, p_region.size.y, copy.shader_version, CopyShaderGLES3::MODE_SIMPLE_COLOR); + copy.shader.version_set_uniform(CopyShaderGLES3::COLOR_IN, p_color, copy.shader_version, CopyShaderGLES3::MODE_SIMPLE_COLOR); + glBindVertexArray(quad_array); + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); +} +#endif // GLES3_ENABLED diff --git a/drivers/gles3/texture_loader_gles3.h b/drivers/gles3/effects/copy_effects.h index 6873858b89..1cf1ac9404 100644 --- a/drivers/gles3/texture_loader_gles3.h +++ b/drivers/gles3/effects/copy_effects.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* texture_loader_gles3.h */ +/* copy_effects.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,24 +28,46 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef TEXTURE_LOADER_OPENGL_H -#define TEXTURE_LOADER_OPENGL_H +#ifndef COPY_GL_H +#define COPY_GL_H #ifdef GLES3_ENABLED -#include "core/io/resource_loader.h" -#include "scene/resources/texture.h" +#include "../shaders/copy.glsl.gen.h" + +namespace GLES3 { + +class CopyEffects { +private: + struct Copy { + CopyShaderGLES3 shader; + RID shader_version; + } copy; + + static CopyEffects *singleton; + + // Use for full-screen effects. Slightly more efficient than screen_quad as this eliminates pixel overdraw along the diagonal. + GLuint screen_triangle = 0; + GLuint screen_triangle_array = 0; + + // Use for rect-based effects. + GLuint quad = 0; + GLuint quad_array = 0; -class ResourceFormatGLES2Texture : public ResourceFormatLoader { public: - virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE); - virtual void get_recognized_extensions(List<String> *p_extensions) const; - virtual bool handles_type(const String &p_type) const; - virtual String get_resource_type(const String &p_path) const; + static CopyEffects *get_singleton(); + + CopyEffects(); + ~CopyEffects(); - virtual ~ResourceFormatGLES2Texture() {} + // These functions assume that a framebuffer and texture are bound already. They only manage the shader, uniforms, and vertex array. + void copy_to_rect(const Rect2i &p_rect); + void copy_screen(); + void bilinear_blur(GLuint p_source_texture, int p_mipmap_count, const Rect2i &p_region); + void set_color(const Color &p_color, const Rect2i &p_region); }; -#endif // GLES3_ENABLED +} //namespace GLES3 -#endif // TEXTURE_LOADER_OPENGL_H +#endif // GLES3_ENABLED +#endif // !COPY_GL_H diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index df54686574..5d06224bfd 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -119,12 +119,11 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); - texture_storage->frame.current_rt = nullptr; - - texture_storage->_set_current_render_target(p_to_render_target); - Transform2D canvas_transform_inverse = p_canvas_transform.affine_inverse(); + // Clear out any state that may have been left from the 3D pass. + reset_canvas(); + // TODO: Setup Directional Lights // TODO: Setup lights @@ -156,6 +155,9 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ state_buffer.screen_pixel_size[0] = 1.0 / render_target_size.x; state_buffer.screen_pixel_size[1] = 1.0 / render_target_size.y; + // TODO: temporary, this should be set at the top of this function + glViewport(0, 0, render_target_size.x, render_target_size.y); + state_buffer.time = state.time; state_buffer.use_pixel_snap = p_snap_2d_vertices_to_pixel; @@ -177,7 +179,6 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ state_buffer.sdf_to_tex[2] = -sdf_tex_rect.position.x / sdf_tex_rect.size.width; state_buffer.sdf_to_tex[3] = -sdf_tex_rect.position.y / sdf_tex_rect.size.height; - //print_line("w: " + itos(ssize.width) + " s: " + rtos(canvas_scale)); state_buffer.tex_to_sdf = 1.0 / ((canvas_scale.x + canvas_scale.y) * 0.5); glBindBufferBase(GL_UNIFORM_BUFFER, BASE_UNIFORM_LOCATION, state.canvas_state_buffer); glBufferData(GL_UNIFORM_BUFFER, sizeof(StateBuffer), &state_buffer, GL_STREAM_DRAW); @@ -193,17 +194,100 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ state.default_repeat = p_default_repeat; } - state.current_tex = RID(); - state.current_tex_ptr = nullptr; - state.current_normal = RID(); - state.current_specular = RID(); - state.canvas_texscreen_used = false; - r_sdf_used = false; int item_count = 0; + bool backbuffer_cleared = false; + bool time_used = false; + bool material_screen_texture_found = false; + Rect2 back_buffer_rect; + bool backbuffer_copy = false; Item *ci = p_item_list; + Item *canvas_group_owner = nullptr; + while (ci) { + if (ci->copy_back_buffer && canvas_group_owner == nullptr) { + backbuffer_copy = true; + + if (ci->copy_back_buffer->full) { + back_buffer_rect = Rect2(); + } else { + back_buffer_rect = ci->copy_back_buffer->rect; + } + } + + // Check material for something that may change flow of rendering, but do not bind for now. + RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material; + if (material.is_valid()) { + GLES3::CanvasMaterialData *md = static_cast<GLES3::CanvasMaterialData *>(material_storage->material_get_data(material, RS::SHADER_CANVAS_ITEM)); + if (md && md->shader_data->valid) { + if (md->shader_data->uses_screen_texture && canvas_group_owner == nullptr) { + if (!material_screen_texture_found) { + backbuffer_copy = true; + back_buffer_rect = Rect2(); + } + } + + if (md->shader_data->uses_sdf) { + r_sdf_used = true; + } + if (md->shader_data->uses_time) { + time_used = true; + } + } + } + + if (ci->canvas_group_owner != nullptr) { + if (canvas_group_owner == nullptr) { + // Canvas group begins here, render until before this item + + _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list); + item_count = 0; + + Rect2i group_rect = ci->canvas_group_owner->global_rect_cache; + + if (ci->canvas_group_owner->canvas_group->mode == RS::CANVAS_GROUP_MODE_OPAQUE) { + texture_storage->render_target_copy_to_back_buffer(p_to_render_target, group_rect, false); + } else if (!backbuffer_cleared) { + texture_storage->render_target_clear_back_buffer(p_to_render_target, Rect2i(), Color(0, 0, 0, 0)); + backbuffer_cleared = true; + } + + backbuffer_copy = false; + canvas_group_owner = ci->canvas_group_owner; //continue until owner found + } + + ci->canvas_group_owner = nullptr; //must be cleared + } + + if (!backbuffer_cleared && canvas_group_owner == nullptr && ci->canvas_group != nullptr && !backbuffer_copy) { + texture_storage->render_target_clear_back_buffer(p_to_render_target, Rect2i(), Color(0, 0, 0, 0)); + backbuffer_cleared = true; + } + + if (ci == canvas_group_owner) { + _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, true); + item_count = 0; + + if (ci->canvas_group->blur_mipmaps) { + texture_storage->render_target_gen_back_buffer_mipmaps(p_to_render_target, ci->global_rect_cache); + } + + canvas_group_owner = nullptr; + } + + if (backbuffer_copy) { + //render anything pending, including clearing if no items + + _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list); + item_count = 0; + + texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, true); + + backbuffer_copy = false; + material_screen_texture_found = true; //after a backbuffer copy, screen texture makes no further copies + } + // just add all items for now items[item_count++] = ci; @@ -215,27 +299,52 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ ci = ci->next; } + + if (time_used) { + RenderingServerDefault::redraw_request(); + } + + // Clear out state used in 2D pass + reset_canvas(); } void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer) { + GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); Item *current_clip = nullptr; Transform2D canvas_transform_inverse = p_canvas_transform_inverse; - RID framebuffer; - Vector<Color> clear_colors; - - canvas_begin(); + canvas_begin(p_to_render_target, p_to_backbuffer); RID prev_material; uint32_t index = 0; + GLES3::CanvasShaderData::BlendMode last_blend_mode = GLES3::CanvasShaderData::BLEND_MODE_MIX; + GLES3::CanvasShaderData *shader_data_cache = nullptr; + state.current_tex = texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE); + state.current_tex_ptr = nullptr; + state.current_normal = RID(); + state.current_specular = RID(); + state.canvas_texscreen_used = false; state.current_shader_version = state.canvas_shader_default_version; for (int i = 0; i < p_item_count; i++) { Item *ci = items[i]; + if (current_clip != ci->final_clip_owner) { + _render_batch(index); + + current_clip = ci->final_clip_owner; + //setup clip + if (current_clip) { + glEnable(GL_SCISSOR_TEST); + glScissor(current_clip->final_clip_rect.position.x, current_clip->final_clip_rect.position.y, current_clip->final_clip_rect.size.x, current_clip->final_clip_rect.size.y); + } else { + glDisable(GL_SCISSOR_TEST); + } + } + RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material; if (material.is_null() && ci->canvas_group != nullptr) { @@ -243,6 +352,7 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou } if (material != prev_material) { + _render_batch(index); GLES3::CanvasMaterialData *material_data = nullptr; if (material.is_valid()) { material_data = static_cast<GLES3::CanvasMaterialData *>(material_storage->material_get_data(material, RS::SHADER_CANVAS_ITEM)); @@ -252,22 +362,86 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou // Bind uniform buffer and textures material_data->bind_uniforms(); state.current_shader_version = material_data->shader_data->version; + shader_data_cache = material_data->shader_data; } else { state.current_shader_version = state.canvas_shader_default_version; + shader_data_cache = nullptr; } } else { state.current_shader_version = state.canvas_shader_default_version; + shader_data_cache = nullptr; } prev_material = material; } + GLES3::CanvasShaderData::BlendMode blend_mode = shader_data_cache ? shader_data_cache->blend_mode : GLES3::CanvasShaderData::BLEND_MODE_MIX; + + if (last_blend_mode != blend_mode) { + if (last_blend_mode == GLES3::CanvasShaderData::BLEND_MODE_DISABLED) { + // re-enable it + glEnable(GL_BLEND); + } else if (blend_mode == GLES3::CanvasShaderData::BLEND_MODE_DISABLED) { + // disable it + glDisable(GL_BLEND); + } + + switch (blend_mode) { + case GLES3::CanvasShaderData::BLEND_MODE_DISABLED: { + // Nothing to do here. + + } break; + case GLES3::CanvasShaderData::BLEND_MODE_MIX: { + glBlendEquation(GL_FUNC_ADD); + if (state.transparent_render_target) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } else { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); + } + + } break; + case GLES3::CanvasShaderData::BLEND_MODE_ADD: { + glBlendEquation(GL_FUNC_ADD); + if (state.transparent_render_target) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_SRC_ALPHA, GL_ONE); + } else { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE); + } + + } break; + case GLES3::CanvasShaderData::BLEND_MODE_SUB: { + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); + if (state.transparent_render_target) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_SRC_ALPHA, GL_ONE); + } else { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE); + } + } break; + case GLES3::CanvasShaderData::BLEND_MODE_MUL: { + glBlendEquation(GL_FUNC_ADD); + if (state.transparent_render_target) { + glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_DST_ALPHA, GL_ZERO); + } else { + glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ZERO, GL_ONE); + } + + } break; + case GLES3::CanvasShaderData::BLEND_MODE_PMALPHA: { + glBlendEquation(GL_FUNC_ADD); + if (state.transparent_render_target) { + glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } else { + glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); + } + + } break; + } + last_blend_mode = blend_mode; + } + _render_item(p_to_render_target, ci, canvas_transform_inverse, current_clip, p_lights, index); } // Render last command - state.end_batch = true; _render_batch(index); - - canvas_end(); } void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, uint32_t &r_index) { @@ -289,8 +463,7 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item uint32_t base_flags = 0; - RID last_texture; - Size2 texpixel_size; + bool reclip = false; bool skipping = false; @@ -326,21 +499,20 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item current_repeat = RenderingServer::CanvasItemTextureRepeat::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED; } - if (rect->texture != last_texture || state.current_primitive_points != 0 || state.current_command != Item::Command::TYPE_RECT) { - state.end_batch = true; + if (rect->texture != state.current_tex || state.current_primitive_points != 0 || state.current_command != Item::Command::TYPE_RECT) { _render_batch(r_index); state.current_primitive_points = 0; state.current_command = Item::Command::TYPE_RECT; } - _bind_canvas_texture(rect->texture, current_filter, current_repeat, r_index, last_texture, texpixel_size); + _bind_canvas_texture(rect->texture, current_filter, current_repeat, r_index); GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_QUAD); Rect2 src_rect; Rect2 dst_rect; if (rect->texture != RID()) { - src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * texpixel_size, rect->source.size * texpixel_size) : Rect2(0, 0, 1, 1); + src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * state.current_pixel_size, rect->source.size * state.current_pixel_size) : Rect2(0, 0, 1, 1); dst_rect = Rect2(rect->rect.position, rect->rect.size); if (dst_rect.size.width < 0) { @@ -408,8 +580,6 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item //_render_batch(r_index); r_index++; if (r_index >= state.max_instances_per_batch - 1) { - //r_index--; - state.end_batch = true; _render_batch(r_index); } } break; @@ -426,18 +596,18 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item //bind textures - _bind_canvas_texture(p_draw_list, np->texture, current_filter, current_repeat, index, last_texture, texpixel_size); + _bind_canvas_texture(p_draw_list, np->texture, current_filter, current_repeat, index); Rect2 src_rect; Rect2 dst_rect(np->rect.position.x, np->rect.position.y, np->rect.size.x, np->rect.size.y); if (np->texture == RID()) { - texpixel_size = Size2(1, 1); + state.current_pixel_size = Size2(1, 1); src_rect = Rect2(0, 0, 1, 1); } else { if (np->source != Rect2()) { - src_rect = Rect2(np->source.position.x * texpixel_size.width, np->source.position.y * texpixel_size.height, np->source.size.x * texpixel_size.width, np->source.size.y * texpixel_size.height); + src_rect = Rect2(np->source.position.x * state.current_pixel_size.width, np->source.position.y * state.current_pixel_size.height, np->source.size.x * state.current_pixel_size.width, np->source.size.y * state.current_pixel_size.height); state.instance_data_array[r_index].color_texture_pixel_size[0] = 1.0 / np->source.size.width; state.instance_data_array[r_index].color_texture_pixel_size[1] = 1.0 / np->source.size.height; @@ -478,8 +648,8 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item RD::get_singleton()->draw_list_draw(p_draw_list, true); // Restore if overridden. - state.instance_data_array[r_index].color_texture_pixel_size[0] = texpixel_size.x; - state.instance_data_array[r_index].color_texture_pixel_size[1] = texpixel_size.y; + state.instance_data_array[r_index].color_texture_pixel_size[0] = state.current_pixel_size.x; + state.instance_data_array[r_index].color_texture_pixel_size[1] = state.current_pixel_size.y; */ } break; @@ -489,14 +659,13 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item PolygonBuffers *pb = polygon_buffers.polygons.getptr(polygon->polygon.polygon_id); ERR_CONTINUE(!pb); - if (polygon->texture != last_texture || state.current_primitive_points != 0 || state.current_command != Item::Command::TYPE_POLYGON) { - state.end_batch = true; + if (polygon->texture != state.current_tex || state.current_primitive_points != 0 || state.current_command != Item::Command::TYPE_POLYGON) { _render_batch(r_index); state.current_primitive_points = 0; state.current_command = Item::Command::TYPE_POLYGON; } - _bind_canvas_texture(polygon->texture, current_filter, current_repeat, r_index, last_texture, texpixel_size); + _bind_canvas_texture(polygon->texture, current_filter, current_repeat, r_index); GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_ATTRIBUTES); state.current_primitive = polygon->primitive; @@ -549,13 +718,12 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item case Item::Command::TYPE_PRIMITIVE: { const Item::CommandPrimitive *primitive = static_cast<const Item::CommandPrimitive *>(c); - if (last_texture != default_canvas_texture || state.current_primitive_points != primitive->point_count || state.current_command != Item::Command::TYPE_PRIMITIVE) { - state.end_batch = true; + if (state.current_primitive_points != primitive->point_count || state.current_command != Item::Command::TYPE_PRIMITIVE) { _render_batch(r_index); state.current_primitive_points = primitive->point_count; state.current_command = Item::Command::TYPE_PRIMITIVE; } - _bind_canvas_texture(RID(), current_filter, current_repeat, r_index, last_texture, texpixel_size); + _bind_canvas_texture(RID(), current_filter, current_repeat, r_index); GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_PRIMITIVE); for (uint32_t j = 0; j < MIN(3u, primitive->point_count); j++) { @@ -589,8 +757,6 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item r_index++; } if (r_index >= state.max_instances_per_batch - 1) { - //r_index--; - state.end_batch = true; _render_batch(r_index); } } break; @@ -643,14 +809,13 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item break; } - if (texture != last_texture || state.current_primitive_points != 0 || state.current_command != Item::Command::TYPE_PRIMITIVE) { - state.end_batch = true; + if (texture != state.current_tex || state.current_primitive_points != 0 || state.current_command != Item::Command::TYPE_PRIMITIVE) { _render_batch(r_index); state.current_primitive_points = 0; state.current_command = c->type; } - _bind_canvas_texture(texture, current_filter, current_repeat, r_index, last_texture, texpixel_size); + _bind_canvas_texture(texture, current_filter, current_repeat, r_index); uint32_t surf_count = storage->mesh_get_surface_count(mesh); @@ -684,20 +849,19 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item } break; case Item::Command::TYPE_CLIP_IGNORE: { - /* const Item::CommandClipIgnore *ci = static_cast<const Item::CommandClipIgnore *>(c); if (current_clip) { if (ci->ignore != reclip) { if (ci->ignore) { - RD::get_singleton()->draw_list_disable_scissor(p_draw_list); + glDisable(GL_SCISSOR_TEST); reclip = true; } else { - RD::get_singleton()->draw_list_enable_scissor(p_draw_list, current_clip->final_clip_rect); + // Scissor area is already set + glEnable(GL_SCISSOR_TEST); reclip = false; } } } - */ } break; case Item::Command::TYPE_ANIMATION_SLICE: { /* @@ -713,10 +877,15 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item c = c->next; } + + if (current_clip && reclip) { + //will make it re-enable clipping if needed afterwards + current_clip = nullptr; + } } void RasterizerCanvasGLES3::_render_batch(uint32_t &r_index) { - if (state.end_batch && r_index > 0) { + if (r_index > 0) { // If the previous operation is not done yet, allocate a new buffer if (state.fences[state.current_buffer] != GLsync()) { GLint syncStatus; @@ -748,7 +917,6 @@ void RasterizerCanvasGLES3::_render_batch(uint32_t &r_index) { state.fences[state.current_buffer] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); state.current_buffer = (state.current_buffer + 1) % state.canvas_instance_data_buffers.size(); - state.end_batch = false; //copy the new data into the base of the batch for (int i = 0; i < 4; i++) { state.instance_data_array[0].modulation[i] = state.instance_data_array[r_index].modulation[i]; @@ -771,27 +939,6 @@ void RasterizerCanvasGLES3::_render_batch(uint32_t &r_index) { } } -// TODO maybe dont use -void RasterizerCanvasGLES3::_end_batch(const uint32_t p_index) { - for (int i = 0; i < 4; i++) { - state.instance_data_array[p_index].modulation[i] = 0.0; - state.instance_data_array[p_index].ninepatch_margins[i] = 0.0; - state.instance_data_array[p_index].src_rect[i] = 0.0; - state.instance_data_array[p_index].dst_rect[i] = 0.0; - } - state.instance_data_array[p_index].flags = uint32_t(0); - state.instance_data_array[p_index].color_texture_pixel_size[0] = 0.0; - state.instance_data_array[p_index].color_texture_pixel_size[1] = 0.0; - - state.instance_data_array[p_index].pad[0] = 0.0; - state.instance_data_array[p_index].pad[1] = 0.0; - - state.instance_data_array[p_index].lights[0] = uint32_t(0); - state.instance_data_array[p_index].lights[1] = uint32_t(0); - state.instance_data_array[p_index].lights[2] = uint32_t(0); - state.instance_data_array[p_index].lights[3] = uint32_t(0); -} - RID RasterizerCanvasGLES3::light_create() { return RID(); } @@ -831,49 +978,56 @@ bool RasterizerCanvasGLES3::free(RID p_rid) { void RasterizerCanvasGLES3::update() { } -void RasterizerCanvasGLES3::canvas_begin() { +void RasterizerCanvasGLES3::canvas_begin(RID p_to_render_target, bool p_to_backbuffer) { GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); + GLES3::Config *config = GLES3::Config::get_singleton(); - state.using_transparent_rt = false; + GLES3::RenderTarget *render_target = texture_storage->get_render_target(p_to_render_target); - if (texture_storage->frame.current_rt) { - glBindFramebuffer(GL_FRAMEBUFFER, texture_storage->frame.current_rt->fbo); - state.using_transparent_rt = texture_storage->frame.current_rt->flags[GLES3::TextureStorage::RENDER_TARGET_TRANSPARENT]; + if (p_to_backbuffer) { + glBindFramebuffer(GL_FRAMEBUFFER, render_target->backbuffer_fbo); + glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 4); + GLES3::Texture *tex = texture_storage->get_texture(texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE)); + glBindTexture(GL_TEXTURE_2D, tex->tex_id); + } else { + glBindFramebuffer(GL_FRAMEBUFFER, render_target->fbo); + glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 4); + glBindTexture(GL_TEXTURE_2D, render_target->backbuffer); + } + + if (render_target->is_transparent) { + state.transparent_render_target = true; + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } else { + state.transparent_render_target = false; + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - if (texture_storage->frame.current_rt && texture_storage->frame.current_rt->clear_requested) { - const Color &col = texture_storage->frame.current_rt->clear_color; + if (render_target && render_target->clear_requested) { + const Color &col = render_target->clear_color; glClearColor(col.r, col.g, col.b, col.a); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - texture_storage->frame.current_rt->clear_requested = false; + render_target->clear_requested = false; } - reset_canvas(); - glActiveTexture(GL_TEXTURE0); GLES3::Texture *tex = texture_storage->get_texture(texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE)); glBindTexture(GL_TEXTURE_2D, tex->tex_id); } -void RasterizerCanvasGLES3::canvas_end() { - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_UNIFORM_BUFFER, 0); -} - -void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, uint32_t &r_index, RID &r_last_texture, Size2 &r_texpixel_size) { +void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, uint32_t &r_index) { GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); + GLES3::Config *config = GLES3::Config::get_singleton(); if (p_texture == RID()) { - p_texture = default_canvas_texture; + p_texture = texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE); } - if (r_last_texture == p_texture) { + if (state.current_tex == p_texture) { return; //nothing to do, its the same } - - state.end_batch = true; - _render_batch(r_index); + state.current_tex = p_texture; GLES3::CanvasTexture *ct = nullptr; @@ -888,12 +1042,12 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe ct = t->canvas_texture; } else { - ct = GLES3::TextureStorage::get_singleton()->get_canvas_texture(p_texture); + ct = texture_storage->get_canvas_texture(p_texture); } if (!ct) { // Invalid Texture RID. - _bind_canvas_texture(default_canvas_texture, p_base_filter, p_base_repeat, r_index, r_last_texture, r_texpixel_size); + _bind_canvas_texture(default_canvas_texture, p_base_filter, p_base_repeat, r_index); return; } @@ -906,18 +1060,17 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe GLES3::Texture *texture = texture_storage->get_texture(ct->diffuse); if (!texture) { - state.current_tex = RID(); - state.current_tex_ptr = nullptr; - ct->size_cache = Size2i(1, 1); - + state.current_tex = texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE); + GLES3::Texture *tex = texture_storage->get_texture(state.current_tex); + state.current_tex_ptr = tex; + ct->size_cache = Size2i(tex->width, tex->height); glActiveTexture(GL_TEXTURE0); - GLES3::Texture *tex = texture_storage->get_texture(texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE)); glBindTexture(GL_TEXTURE_2D, tex->tex_id); } else { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture->tex_id); - state.current_tex = ct->diffuse; + state.current_tex = p_texture; state.current_tex_ptr = texture; ct->size_cache = Size2i(texture->width, texture->height); @@ -935,7 +1088,7 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe glBindTexture(GL_TEXTURE_2D, tex->tex_id); } else { - glActiveTexture(GL_TEXTURE0 + storage->config->max_texture_image_units - 6); + glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 6); glBindTexture(GL_TEXTURE_2D, normal_map->tex_id); state.current_normal = ct->normal_map; ct->use_normal_cache = true; @@ -948,11 +1101,11 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe if (!specular_map) { state.current_specular = RID(); ct->use_specular_cache = false; - glActiveTexture(GL_TEXTURE0 + storage->config->max_texture_image_units - 7); + glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 7); GLES3::Texture *tex = texture_storage->get_texture(texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE)); glBindTexture(GL_TEXTURE_2D, tex->tex_id); } else { - glActiveTexture(GL_TEXTURE0 + storage->config->max_texture_image_units - 7); + glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 7); glBindTexture(GL_TEXTURE_2D, specular_map->tex_id); state.current_specular = ct->specular; ct->use_specular_cache = true; @@ -977,34 +1130,19 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe state.instance_data_array[r_index].specular_shininess |= uint32_t(CLAMP(ct->specular_color.g * 255.0, 0, 255)) << 8; state.instance_data_array[r_index].specular_shininess |= uint32_t(CLAMP(ct->specular_color.r * 255.0, 0, 255)); - r_texpixel_size.x = 1.0 / float(ct->size_cache.x); - r_texpixel_size.y = 1.0 / float(ct->size_cache.y); - - state.instance_data_array[r_index].color_texture_pixel_size[0] = r_texpixel_size.x; - state.instance_data_array[r_index].color_texture_pixel_size[1] = r_texpixel_size.y; + state.current_pixel_size.x = 1.0 / float(ct->size_cache.x); + state.current_pixel_size.y = 1.0 / float(ct->size_cache.y); - r_last_texture = p_texture; -} - -void RasterizerCanvasGLES3::_set_uniforms() { + state.instance_data_array[r_index].color_texture_pixel_size[0] = state.current_pixel_size.x; + state.instance_data_array[r_index].color_texture_pixel_size[1] = state.current_pixel_size.y; } void RasterizerCanvasGLES3::reset_canvas() { - GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); - glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); - glDisable(GL_DITHER); glEnable(GL_BLEND); - - // Default to Mix. - glBlendEquation(GL_FUNC_ADD); - if (texture_storage->frame.current_rt && texture_storage->frame.current_rt->flags[GLES3::TextureStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } else { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); - } + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); @@ -1218,8 +1356,8 @@ RasterizerCanvasGLES3 *RasterizerCanvasGLES3::get_singleton() { RasterizerCanvasGLES3::RasterizerCanvasGLES3(RasterizerStorageGLES3 *p_storage) { singleton = this; storage = p_storage; - GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); + GLES3::Config *config = GLES3::Config::get_singleton(); // quad buffer { @@ -1342,8 +1480,7 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3(RasterizerStorageGLES3 *p_storage) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } - //state.canvas_shadow_shader.init(); - int uniform_max_size = storage->config->max_uniform_buffer_size; + int uniform_max_size = config->max_uniform_buffer_size; if (uniform_max_size < 65536) { state.max_lights_per_render = 64; state.max_instances_per_batch = 128; @@ -1379,14 +1516,6 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3(RasterizerStorageGLES3 *p_storage) state.canvas_shader_default_version = GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_create(); GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.canvas_shader_default_version, CanvasShaderGLES3::MODE_QUAD); - //state.canvas_shader.set_conditional(CanvasOldShaderGLES3::USE_RGBA_SHADOWS, storage->config->use_rgba_2d_shadows); - - //state.canvas_shader.bind(); - - //state.lens_shader.init(); - - //state.canvas_shader.set_conditional(CanvasOldShaderGLES3::USE_PIXEL_SNAP, GLOBAL_DEF("rendering/quality/2d/use_pixel_snap", false)); - { default_canvas_group_shader = material_storage->shader_allocate(); material_storage->shader_initialize(default_canvas_group_shader); @@ -1412,24 +1541,16 @@ void fragment() { material_storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader); } - default_canvas_texture = texture_storage->canvas_texture_allocate(); - texture_storage->canvas_texture_initialize(default_canvas_texture); - - state.using_light = nullptr; - state.using_transparent_rt = false; - state.using_skeleton = false; state.current_shader_version = state.canvas_shader_default_version; state.time = 0.0; } RasterizerCanvasGLES3::~RasterizerCanvasGLES3() { - GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_free(state.canvas_shader_default_version); material_storage->material_free(default_canvas_group_material); material_storage->shader_free(default_canvas_group_shader); - texture_storage->canvas_texture_free(default_canvas_texture); singleton = nullptr; glDeleteBuffers(1, &data.canvas_quad_vertices); diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index aedde7c265..7fb77f432c 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -171,22 +171,11 @@ public: InstanceData *instance_data_array = nullptr; bool canvas_texscreen_used; - //CanvasShaderGLES3 canvas_shader; RID canvas_shader_current_version; RID canvas_shader_default_version; - //CanvasShadowShaderGLES3 canvas_shadow_shader; - //LensDistortedShaderGLES3 lens_shader; - - bool using_texture_rect; - - bool using_ninepatch; - bool using_skeleton; - - Transform2D skeleton_transform; - Transform2D skeleton_transform_inverse; - Size2i skeleton_texture_size; RID current_tex = RID(); + Size2 current_pixel_size = Size2(); RID current_normal = RID(); RID current_specular = RID(); GLES3::Texture *current_tex_ptr; @@ -195,14 +184,7 @@ public: uint32_t current_primitive_points = 0; Item::Command::Type current_command = Item::Command::TYPE_RECT; - bool end_batch = false; - - Transform3D vp; - Light *using_light = nullptr; - bool using_shadow; - bool using_transparent_rt; - - // FROM RD Renderer + bool transparent_render_target = false; double time = 0.0; @@ -224,16 +206,13 @@ public: RasterizerStorageGLES3 *storage = nullptr; - void _set_uniforms(); - - void canvas_begin(); - void canvas_end(); + void canvas_begin(RID p_to_render_target, bool p_to_backbuffer); //virtual void draw_window_margins(int *black_margin, RID *black_image) override; void draw_lens_distortion_rect(const Rect2 &p_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample); - virtual void reset_canvas(); - virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache); + void reset_canvas(); + void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache); virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) override; @@ -252,7 +231,7 @@ public: bool free(RID p_rid) override; void update() override; - void _bind_canvas_texture(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, uint32_t &r_index, RID &r_last_texture, Size2 &r_texpixel_size); + void _bind_canvas_texture(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, uint32_t &r_index); struct PolygonBuffers { GLuint vertex_buffer; @@ -273,7 +252,6 @@ public: void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer = false); void _render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, uint32_t &r_index); void _render_batch(uint32_t &p_max_index); - void _end_batch(const uint32_t p_index); void _allocate_instance_data_buffer(); void set_time(double p_time); diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 69f69099c7..c8705dc8c8 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -268,6 +268,7 @@ RasterizerGLES3::RasterizerGLES3() { mesh_storage = memnew(GLES3::MeshStorage); particles_storage = memnew(GLES3::ParticlesStorage); light_storage = memnew(GLES3::LightStorage); + copy_effects = memnew(GLES3::CopyEffects); storage = memnew(RasterizerStorageGLES3); canvas = memnew(RasterizerCanvasGLES3(storage)); scene = memnew(RasterizerSceneGLES3(storage)); @@ -281,7 +282,6 @@ void RasterizerGLES3::prepare_for_blitting_render_targets() { void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect) { GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); - ERR_FAIL_COND(texture_storage->frame.current_rt); GLES3::RenderTarget *rt = texture_storage->get_render_target(p_render_target); ERR_FAIL_COND(!rt); @@ -304,12 +304,9 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display // is this p_screen useless in a multi window environment? void RasterizerGLES3::blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) { - // do this once off for all blits - GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); + // All blits are going to the system framebuffer, so just bind once. glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo); - texture_storage->frame.current_rt = nullptr; - for (int i = 0; i < p_amount; i++) { const BlitToScreen &blit = p_render_targets[i]; @@ -339,8 +336,6 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c } glClear(GL_COLOR_BUFFER_BIT); - canvas->canvas_begin(); - RID texture = texture_storage->texture_allocate(); texture_storage->texture_2d_initialize(texture, p_image); @@ -368,7 +363,6 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 1); glBindTexture(GL_TEXTURE_2D, t->tex_id); glBindTexture(GL_TEXTURE_2D, 0); - canvas->canvas_end(); texture_storage->texture_free(texture); diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h index ad3d3d7325..5f1cbab849 100644 --- a/drivers/gles3/rasterizer_gles3.h +++ b/drivers/gles3/rasterizer_gles3.h @@ -33,6 +33,7 @@ #ifdef GLES3_ENABLED +#include "effects/copy_effects.h" #include "rasterizer_canvas_gles3.h" #include "rasterizer_scene_gles3.h" #include "rasterizer_storage_gles3.h" @@ -58,6 +59,7 @@ protected: GLES3::MeshStorage *mesh_storage = nullptr; GLES3::ParticlesStorage *particles_storage = nullptr; GLES3::LightStorage *light_storage = nullptr; + GLES3::CopyEffects *copy_effects = nullptr; RasterizerStorageGLES3 *storage = nullptr; RasterizerCanvasGLES3 *canvas = nullptr; RasterizerSceneGLES3 *scene = nullptr; diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index c3af232046..7ce1300d07 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -36,20 +36,6 @@ #ifdef GLES3_ENABLED -void glTexStorage2DCustom(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type) { -#ifdef GLES_OVER_GL - - for (int i = 0; i < levels; i++) { - glTexImage2D(target, i, internalformat, width, height, 0, format, type, nullptr); - width = MAX(1, (width / 2)); - height = MAX(1, (height / 2)); - } - -#else - glTexStorage2D(target, levels, internalformat, width, height); -#endif -} - uint64_t RasterizerSceneGLES3::auto_exposure_counter = 2; RasterizerSceneGLES3 *RasterizerSceneGLES3::singleton = nullptr; @@ -2480,100 +2466,6 @@ RID RasterizerSceneGLES3::render_buffers_create() { return render_buffers_owner.make_rid(rb); } -/* BACK FBO */ -/* For MSAA */ -/* -#ifndef JAVASCRIPT_ENABLED - if (rt->msaa >= RS::VIEWPORT_MSAA_2X && rt->msaa <= RS::VIEWPORT_MSAA_8X) { - rt->multisample_active = true; - - static const int msaa_value[] = { 0, 2, 4, 8, 16 }; - int msaa = msaa_value[rt->msaa]; - - int max_samples = 0; - glGetIntegerv(GL_MAX_SAMPLES, &max_samples); - if (msaa > max_samples) { - WARN_PRINT("MSAA must be <= GL_MAX_SAMPLES, falling-back to GL_MAX_SAMPLES = " + itos(max_samples)); - msaa = max_samples; - } - - //regular fbo - glGenFramebuffers(1, &rt->multisample_fbo); - bind_framebuffer(rt->multisample_fbo); - - glGenRenderbuffers(1, &rt->multisample_depth); - glBindRenderbuffer(GL_RENDERBUFFER, rt->multisample_depth); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, config.depth_buffer_internalformat, rt->size.x, rt->size.y); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->multisample_depth); - - glGenRenderbuffers(1, &rt->multisample_color); - glBindRenderbuffer(GL_RENDERBUFFER, rt->multisample_color); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, color_internal_format, rt->size.x, rt->size.y); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rt->multisample_color); - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - - if (status != GL_FRAMEBUFFER_COMPLETE) { - // Delete allocated resources and default to no MSAA - WARN_PRINT_ONCE("Cannot allocate back framebuffer for MSAA"); - printf("err status: %x\n", status); - rt->multisample_active = false; - - glDeleteFramebuffers(1, &rt->multisample_fbo); - rt->multisample_fbo = 0; - - glDeleteRenderbuffers(1, &rt->multisample_depth); - rt->multisample_depth = 0; - - glDeleteRenderbuffers(1, &rt->multisample_color); - rt->multisample_color = 0; - } - - glBindRenderbuffer(GL_RENDERBUFFER, 0); - bind_framebuffer(0); - - } else -#endif // JAVASCRIPT_ENABLED - { - rt->multisample_active = false; - } - */ - -// copy texscreen buffers -// if (!(rt->flags[RendererStorage::RENDER_TARGET_NO_SAMPLING])) { -/* -if (false) { -glGenTextures(1, &rt->copy_screen_effect.color); -glBindTexture(GL_TEXTURE_2D, rt->copy_screen_effect.color); - -if (rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rt->size.x, rt->size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); -} else { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rt->size.x, rt->size.y, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); -} - -glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); -glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); -glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - -glGenFramebuffers(1, &rt->copy_screen_effect.fbo); -bind_framebuffer(rt->copy_screen_effect.fbo); -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) { - _clear_render_target(rt); - ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE); -} -} -*/ - void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) { GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); @@ -2595,7 +2487,7 @@ void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_ GLES3::RenderTarget *rt = texture_storage->get_render_target(p_render_target); - rb->is_transparent = rt->flags[RendererTextureStorage::RENDER_TARGET_TRANSPARENT]; + rb->is_transparent = rt->is_transparent; // framebuffer glGenFramebuffers(1, &rb->framebuffer); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index d9a848c0f6..ea6145d2a8 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -553,49 +553,6 @@ protected: }; Blur blur[2]; //the second one starts from the first mipmap - - /* - GLuint fbo = 0; - GLuint color = 0; - GLuint depth = 0; - - GLuint multisample_fbo = 0; - GLuint multisample_color = 0; - GLuint multisample_depth = 0; - bool multisample_active = false; - - struct Effect { - GLuint fbo = 0; - int width = 0; - int height = 0; - - GLuint color = 0; - - Effect() { - } - }; - - Effect copy_screen_effect; - - struct MipMaps { - struct Size { - GLuint fbo; - GLuint color; - int width; - int height; - }; - - Vector<Size> sizes; - GLuint color = 0; - int levels = 0; - - MipMaps() { - } - }; - - MipMaps mip_maps[2]; - - */ }; bool screen_space_roughness_limiter = false; diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 8046a18f05..49c5045453 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -225,7 +225,7 @@ RID RasterizerStorageGLES3::canvas_light_shadow_buffer_create(int p_width) { glGenRenderbuffers(1, &cls->depth); glBindRenderbuffer(GL_RENDERBUFFER, cls->depth); - glRenderbufferStorage(GL_RENDERBUFFER, config->depth_buffer_internalformat, cls->size, cls->height); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, cls->size, cls->height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, cls->depth); glGenTextures(1, &cls->distance); @@ -453,11 +453,8 @@ bool RasterizerStorageGLES3::has_os_feature(const String &p_feature) const { if (p_feature == "bptc") { return config->bptc_supported; } - if (p_feature == "etc") { - return config->etc_supported; - } - if (p_feature == "etc2") { + if (p_feature == "etc" || p_feature == "etc2") { return config->etc2_supported; } @@ -619,9 +616,6 @@ void RasterizerStorageGLES3::initialize() { void RasterizerStorageGLES3::finalize() { } -void RasterizerStorageGLES3::_copy_screen() { - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); -} void RasterizerStorageGLES3::update_memory_info() { } diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index fa74fbd5f6..7ac3db4537 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -258,8 +258,6 @@ public: void initialize(); void finalize(); - void _copy_screen(); - void update_memory_info() override; uint64_t get_rendering_info(RS::RenderingInfo p_info) override; @@ -297,9 +295,6 @@ public: return String(); } - void buffer_orphan_and_upload(unsigned int p_buffer_size, unsigned int p_offset, unsigned int p_data_size, const void *p_data, GLenum p_target = GL_ARRAY_BUFFER, GLenum p_usage = GL_DYNAMIC_DRAW, bool p_optional_orphan = false) const; - bool safe_buffer_sub_data(unsigned int p_total_buffer_size, GLenum p_target, unsigned int p_offset, unsigned int p_data_size, const void *p_data, unsigned int &r_offset_after) const; - //bool validate_framebuffer(); // Validate currently bound framebuffer, does not touch global state String get_framebuffer_error(GLenum p_status); @@ -307,43 +302,6 @@ public: ~RasterizerStorageGLES3(); }; -inline bool RasterizerStorageGLES3::safe_buffer_sub_data(unsigned int p_total_buffer_size, GLenum p_target, unsigned int p_offset, unsigned int p_data_size, const void *p_data, unsigned int &r_offset_after) const { - r_offset_after = p_offset + p_data_size; -#ifdef DEBUG_ENABLED - // we are trying to write across the edge of the buffer - if (r_offset_after > p_total_buffer_size) { - return false; - } -#endif - glBufferSubData(p_target, p_offset, p_data_size, p_data); - return true; -} - -// standardize the orphan / upload in one place so it can be changed per platform as necessary, and avoid future -// bugs causing pipeline stalls -inline void RasterizerStorageGLES3::buffer_orphan_and_upload(unsigned int p_buffer_size, unsigned int p_offset, unsigned int p_data_size, const void *p_data, GLenum p_target, GLenum p_usage, bool p_optional_orphan) const { - // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData - // Was previously #ifndef GLES_OVER_GL however this causes stalls on desktop mac also (and possibly other) - if (!p_optional_orphan || (config->should_orphan)) { - glBufferData(p_target, p_buffer_size, nullptr, p_usage); -#ifdef RASTERIZER_EXTRA_CHECKS - // fill with garbage off the end of the array - if (p_buffer_size) { - unsigned int start = p_offset + p_data_size; - unsigned int end = start + 1024; - if (end < p_buffer_size) { - uint8_t *garbage = (uint8_t *)alloca(1024); - for (int n = 0; n < 1024; n++) { - garbage[n] = Math::random(0, 255); - } - glBufferSubData(p_target, start, 1024, garbage); - } - } -#endif - } - glBufferSubData(p_target, p_offset, p_data_size, p_data); -} - inline String RasterizerStorageGLES3::get_framebuffer_error(GLenum p_status) { #if defined(DEBUG_ENABLED) && defined(GLES_OVER_GL) if (p_status == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT) { diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index 33d5494837..21ccef3518 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -673,7 +673,7 @@ void ShaderGLES3::initialize(const String &p_general_defines, int p_base_texture print_verbose("Shader '" + name + "' SHA256: " + base_sha256); } - glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_image_units); + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_image_units); } void ShaderGLES3::set_shader_cache_dir(const String &p_dir) { diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h index 228bed6f9b..e1385669cd 100644 --- a/drivers/gles3/shader_gles3.h +++ b/drivers/gles3/shader_gles3.h @@ -31,6 +31,7 @@ #ifndef SHADER_OPENGL_H #define SHADER_OPENGL_H +#include "core/math/camera_matrix.h" #include "core/os/mutex.h" #include "core/string/string_builder.h" #include "core/templates/hash_map.h" diff --git a/drivers/gles3/shaders/copy.glsl b/drivers/gles3/shaders/copy.glsl index 62332a15a7..ca2fc7e36d 100644 --- a/drivers/gles3/shaders/copy.glsl +++ b/drivers/gles3/shaders/copy.glsl @@ -1,204 +1,59 @@ /* clang-format off */ #[modes] -mode_default = -mode_cubemap = #define USE_CUBEMAP -mode_panorama = #define USE_PANORAMA +mode_default = #define MODE_SIMPLE_COPY mode_copy_section = #define USE_COPY_SECTION -mode_asym_pano = #define USE_ASYM_PANO -mode_no_alpha = #define USE_NO_ALPHA -mode_custom_alpha = #define USE_CUSTOM_ALPHA -mode_multiplier = #define USE_MULTIPLIER -mode_sep_cbcr_texture = #define USE_SEP_CBCR_TEXTURE -mode_ycbcr_to_rgb = #define USE_YCBCR_TO_RGB +mode_gaussian_blur = #define MODE_GAUSSIAN_BLUR +mode_mipmap = #define MODE_MIPMAP +mode_simple_color = #define MODE_SIMPLE_COLOR \n#define USE_COPY_SECTION #[specializations] - #[vertex] -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -precision highp float; -precision highp int; -#endif - -layout(location = 0) in highp vec4 vertex_attrib; -/* clang-format on */ - -#if defined(USE_CUBEMAP) || defined(USE_PANORAMA) -layout(location = 4) in vec3 cube_in; -#else -layout(location = 4) in vec2 uv_in; -#endif - -layout(location = 5) in vec2 uv2_in; +layout(location = 0) in vec2 vertex_attrib; -#if defined(USE_CUBEMAP) || defined(USE_PANORAMA) -out vec3 cube_interp; -#else out vec2 uv_interp; -#endif -out vec2 uv2_interp; +/* clang-format on */ #ifdef USE_COPY_SECTION uniform highp vec4 copy_section; -#elif defined(USE_DISPLAY_TRANSFORM) -uniform highp mat4 display_transform; #endif void main() { -#if defined(USE_CUBEMAP) || defined(USE_PANORAMA) - cube_interp = cube_in; -#elif defined(USE_ASYM_PANO) - uv_interp = vertex_attrib.xy; -#else - uv_interp = uv_in; -#endif - - uv2_interp = uv2_in; - gl_Position = vertex_attrib; + uv_interp = vertex_attrib * 0.5 + 0.5; + gl_Position = vec4(vertex_attrib, 1.0, 1.0); #ifdef USE_COPY_SECTION + gl_Position.xy = (copy_section.xy + (uv_interp.xy * 0.5 + 0.5) * copy_section.zw) * 2.0 - 1.0; uv_interp = copy_section.xy + uv_interp * copy_section.zw; - gl_Position.xy = (copy_section.xy + (gl_Position.xy * 0.5 + 0.5) * copy_section.zw) * 2.0 - 1.0; -#elif defined(USE_DISPLAY_TRANSFORM) - uv_interp = (display_transform * vec4(uv_in, 1.0, 1.0)).xy; #endif } /* clang-format off */ #[fragment] -#define M_PI 3.14159265359 - -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -#if defined(USE_HIGHP_PRECISION) -precision highp float; -precision highp int; -#else -precision mediump float; -precision mediump int; -#endif -#endif - -#if defined(USE_CUBEMAP) || defined(USE_PANORAMA) -in vec3 cube_interp; -#else in vec2 uv_interp; -#endif /* clang-format on */ - -#ifdef USE_ASYM_PANO -uniform highp mat4 pano_transform; -uniform highp vec4 asym_proj; -#endif - -#ifdef USE_CUBEMAP -uniform samplerCube source_cube; // texunit:0 -#else -uniform sampler2D source; // texunit:0 -#endif - -#ifdef USE_SEP_CBCR_TEXTURE -uniform sampler2D CbCr; //texunit:1 -#endif - -in vec2 uv2_interp; - -#ifdef USE_MULTIPLIER -uniform float multiplier; +#ifdef MODE_SIMPLE_COLOR +uniform vec4 color_in; #endif -#ifdef USE_CUSTOM_ALPHA -uniform float custom_alpha; +#ifdef MODE_GAUSSIAN_BLUR +uniform highp vec2 pixel_size; #endif -#if defined(USE_PANORAMA) || defined(USE_ASYM_PANO) -uniform highp mat4 sky_transform; - -vec4 texturePanorama(sampler2D pano, vec3 normal) { - vec2 st = vec2( - atan(normal.x, normal.z), - acos(normal.y)); - - if (st.x < 0.0) - st.x += M_PI * 2.0; - - st /= vec2(M_PI * 2.0, M_PI); - - return texture(pano, st); -} - -#endif +uniform sampler2D source; // texunit:0 layout(location = 0) out vec4 frag_color; void main() { -#ifdef USE_PANORAMA - - vec3 cube_normal = normalize(cube_interp); - cube_normal.z = -cube_normal.z; - cube_normal = mat3(sky_transform) * cube_normal; - cube_normal.z = -cube_normal.z; - - vec4 color = texturePanorama(source, cube_normal); - -#elif defined(USE_ASYM_PANO) - - // When an asymmetrical projection matrix is used (applicable for stereoscopic rendering i.e. VR) we need to do this calculation per fragment to get a perspective correct result. - // Asymmetrical projection means the center of projection is no longer in the center of the screen but shifted. - // The Matrix[2][0] (= asym_proj.x) and Matrix[2][1] (= asym_proj.z) values are what provide the right shift in the image. - - vec3 cube_normal; - cube_normal.z = -1.0; - cube_normal.x = (cube_normal.z * (-uv_interp.x - asym_proj.x)) / asym_proj.y; - cube_normal.y = (cube_normal.z * (-uv_interp.y - asym_proj.z)) / asym_proj.a; - cube_normal = mat3(sky_transform) * mat3(pano_transform) * cube_normal; - cube_normal.z = -cube_normal.z; - - vec4 color = texturePanorama(source, normalize(cube_normal.xyz)); - -#elif defined(USE_CUBEMAP) - vec4 color = texture(source_cube, normalize(cube_interp)); -#elif defined(USE_SEP_CBCR_TEXTURE) - vec4 color; - color.r = texture(source, uv_interp).r; - color.gb = texture(CbCr, uv_interp).rg - vec2(0.5, 0.5); - color.a = 1.0; -#else +#ifdef MODE_SIMPLE_COPY vec4 color = texture(source, uv_interp); + frag_color = color; #endif -#ifdef USE_YCBCR_TO_RGB - // YCbCr -> RGB conversion - - // Using BT.601, which is the standard for SDTV is provided as a reference - color.rgb = mat3( - vec3(1.00000, 1.00000, 1.00000), - vec3(0.00000, -0.34413, 1.77200), - vec3(1.40200, -0.71414, 0.00000)) * - color.rgb; -#endif - -#ifdef USE_NO_ALPHA - color.a = 1.0; -#endif - -#ifdef USE_CUSTOM_ALPHA - color.a = custom_alpha; -#endif - -#ifdef USE_MULTIPLIER - color.rgb *= multiplier; +#ifdef MODE_SIMPLE_COLOR + frag_color = color_in; #endif - - frag_color = color; } diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp index 49a2a79cb2..f2809734a9 100644 --- a/drivers/gles3/storage/config.cpp +++ b/drivers/gles3/storage/config.cpp @@ -55,82 +55,34 @@ Config::Config() { } } - keep_original_textures = true; // false - depth_internalformat = GL_DEPTH_COMPONENT; - depth_type = GL_UNSIGNED_INT; - - srgb_decode_supported = extensions.has("GL_EXT_texture_sRGB_decode"); - etc2_supported = true; + bptc_supported = extensions.has("GL_ARB_texture_compression_bptc") || extensions.has("EXT_texture_compression_bptc"); #ifdef GLES_OVER_GL float_texture_supported = true; + etc2_supported = false; s3tc_supported = true; - etc_supported = false; // extensions.has("GL_OES_compressed_ETC1_RGB8_texture"); - bptc_supported = extensions.has("GL_ARB_texture_compression_bptc") || extensions.has("EXT_texture_compression_bptc"); - rgtc_supported = extensions.has("GL_EXT_texture_compression_rgtc") || extensions.has("GL_ARB_texture_compression_rgtc") || extensions.has("EXT_texture_compression_rgtc"); - support_npot_repeat_mipmap = true; - depth_buffer_internalformat = GL_DEPTH_COMPONENT24; + rgtc_supported = true; //RGTC - core since OpenGL version 3.0 #else float_texture_supported = extensions.has("GL_ARB_texture_float") || extensions.has("GL_OES_texture_float"); - s3tc_supported = extensions.has("GL_EXT_texture_compression_s3tc") || extensions.has("WEBGL_compressed_texture_s3tc"); - etc_supported = extensions.has("GL_OES_compressed_ETC1_RGB8_texture") || extensions.has("WEBGL_compressed_texture_etc1"); - bptc_supported = false; - rgtc_supported = false; - support_npot_repeat_mipmap = extensions.has("GL_OES_texture_npot"); - -#ifdef JAVASCRIPT_ENABLED - // RenderBuffer internal format must be 16 bits in WebGL, - // but depth_texture should default to 32 always - // if the implementation doesn't support 32, it should just quietly use 16 instead - // https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/ - depth_buffer_internalformat = GL_DEPTH_COMPONENT16; - depth_type = GL_UNSIGNED_INT; -#else - // on mobile check for 24 bit depth support for RenderBufferStorage - if (extensions.has("GL_OES_depth24")) { - depth_buffer_internalformat = _DEPTH_COMPONENT24_OES; - depth_type = GL_UNSIGNED_INT; - } else { - depth_buffer_internalformat = GL_DEPTH_COMPONENT16; - depth_type = GL_UNSIGNED_SHORT; - } -#endif + etc2_supported = true; + s3tc_supported = extensions.has("GL_EXT_texture_compression_dxt1") || extensions.has("GL_EXT_texture_compression_s3tc") || extensions.has("WEBGL_compressed_texture_s3tc"); + rgtc_supported = extensions.has("GL_EXT_texture_compression_rgtc") || extensions.has("GL_ARB_texture_compression_rgtc") || extensions.has("EXT_texture_compression_rgtc"); #endif #ifdef GLES_OVER_GL use_rgba_2d_shadows = false; - use_rgba_3d_shadows = false; - support_depth_cubemaps = true; #else use_rgba_2d_shadows = !(float_texture_supported && extensions.has("GL_EXT_texture_rg")); - use_rgba_3d_shadows = false; - support_depth_cubemaps = extensions.has("GL_OES_depth_texture_cube_map"); -#endif - -#ifdef GLES_OVER_GL - support_32_bits_indices = true; -#else - support_32_bits_indices = extensions.has("GL_OES_element_index_uint"); #endif -#ifdef GLES_OVER_GL - support_write_depth = true; -#elif defined(JAVASCRIPT_ENABLED) - support_write_depth = false; -#else - support_write_depth = extensions.has("GL_EXT_frag_depth"); -#endif + glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &max_vertex_texture_image_units); + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_image_units); + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); + glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_buffer_size); - //picky requirements for these - support_shadow_cubemaps = support_write_depth && support_depth_cubemaps; // the use skeleton software path should be used if either float texture is not supported, // OR max_vertex_texture_image_units is zero use_skeleton_software = (float_texture_supported == false) || (max_vertex_texture_image_units == 0); - glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &max_vertex_texture_image_units); - glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_texture_image_units); - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); - glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_buffer_size); - support_anisotropic_filter = extensions.has("GL_EXT_texture_filter_anisotropic"); if (support_anisotropic_filter) { glGetFloatv(_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropic_level); diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h index c93c030498..db76aa79fb 100644 --- a/drivers/gles3/storage/config.h +++ b/drivers/gles3/storage/config.h @@ -53,6 +53,8 @@ private: public: bool use_nearest_mip_filter = false; bool use_skeleton_software = false; + bool use_depth_prepass = true; + bool use_rgba_2d_shadows = false; int max_vertex_texture_image_units = 0; int max_texture_image_units = 0; @@ -69,38 +71,15 @@ public: bool float_texture_supported = false; bool s3tc_supported = false; - bool latc_supported = false; bool rgtc_supported = false; bool bptc_supported = false; - bool etc_supported = false; bool etc2_supported = false; - bool srgb_decode_supported = false; - - bool keep_original_textures = false; bool force_vertex_shading = false; - bool use_rgba_2d_shadows = false; - bool use_rgba_3d_shadows = false; - - bool support_32_bits_indices = false; - bool support_write_depth = false; - bool support_npot_repeat_mipmap = false; - bool support_depth_cubemaps = false; - bool support_shadow_cubemaps = false; bool support_anisotropic_filter = false; float anisotropic_level = 0.0f; - GLuint depth_internalformat = 0; - GLuint depth_type = 0; - GLuint depth_buffer_internalformat = 0; - - // in some cases the legacy render didn't orphan. We will mark these - // so the user can switch orphaning off for them. - bool should_orphan = true; - - bool use_depth_prepass = true; - static Config *get_singleton() { return singleton; }; Config(); diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index a57c899133..698bcf3ec2 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -1184,8 +1184,6 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet p_textures[k++] = gl_texture; } } else { - //bool srgb = p_use_linear_color && p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR; - for (int j = 0; j < textures.size(); j++) { Texture *tex = TextureStorage::get_singleton()->get_texture(textures[j]); @@ -1671,10 +1669,6 @@ ShaderCompiler::DefaultIdentifierActions actions; shaders.compiler_sky.initialize(actions); } - - //shaders.copy.initialize(); - //shaders.copy_version = shaders.copy.version_create(); //TODO - //shaders.copy.version_bind_shader(shaders.copy_version, CopyShaderGLES3::MODE_COPY_SECTION); } MaterialStorage::~MaterialStorage() { @@ -2748,7 +2742,7 @@ void CanvasShaderData::set_code(const String &p_code) { ShaderCompiler::GeneratedCode gen_code; - int blend_mode = BLEND_MODE_MIX; + int blend_modei = BLEND_MODE_MIX; uses_screen_texture = false; ShaderCompiler::IdentifierActions actions; @@ -2756,12 +2750,12 @@ void CanvasShaderData::set_code(const String &p_code) { actions.entry_point_stages["fragment"] = ShaderCompiler::STAGE_FRAGMENT; actions.entry_point_stages["light"] = ShaderCompiler::STAGE_FRAGMENT; - actions.render_mode_values["blend_add"] = Pair<int *, int>(&blend_mode, BLEND_MODE_ADD); - actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MIX); - actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_mode, BLEND_MODE_SUB); - actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MUL); - actions.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&blend_mode, BLEND_MODE_PMALPHA); - actions.render_mode_values["blend_disabled"] = Pair<int *, int>(&blend_mode, BLEND_MODE_DISABLED); + actions.render_mode_values["blend_add"] = Pair<int *, int>(&blend_modei, BLEND_MODE_ADD); + actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MIX); + actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_modei, BLEND_MODE_SUB); + actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MUL); + actions.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&blend_modei, BLEND_MODE_PMALPHA); + actions.render_mode_values["blend_disabled"] = Pair<int *, int>(&blend_modei, BLEND_MODE_DISABLED); actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture; actions.usage_flag_pointers["texture_sdf"] = &uses_sdf; @@ -2775,6 +2769,8 @@ void CanvasShaderData::set_code(const String &p_code) { version = MaterialStorage::get_singleton()->shaders.canvas_shader.version_create(); } + blend_mode = BlendMode(blend_modei); + #if 0 print_line("**compiling shader:"); print_line("**defines:\n"); diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h index 053dbacc05..09f6680bec 100644 --- a/drivers/gles3/storage/material_storage.h +++ b/drivers/gles3/storage/material_storage.h @@ -42,8 +42,6 @@ #include "servers/rendering/shader_language.h" #include "servers/rendering/storage/material_storage.h" -#include "drivers/gles3/shaders/copy.glsl.gen.h" - #include "../shaders/canvas.glsl.gen.h" #include "../shaders/cubemap_filter.glsl.gen.h" #include "../shaders/scene.glsl.gen.h" @@ -53,18 +51,6 @@ namespace GLES3 { /* Shader Structs */ -struct Shaders { - CanvasShaderGLES3 canvas_shader; - SkyShaderGLES3 sky_shader; - SceneShaderGLES3 scene_shader; - CubemapFilterShaderGLES3 cubemap_filter_shader; - - ShaderCompiler compiler_canvas; - ShaderCompiler compiler_scene; - ShaderCompiler compiler_particles; - ShaderCompiler compiler_sky; -}; - struct ShaderData { virtual void set_code(const String &p_Code) = 0; virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0; @@ -159,8 +145,8 @@ struct CanvasShaderData : public ShaderData { bool valid; RID version; - //PipelineVariants pipeline_variants; String path; + BlendMode blend_mode = BLEND_MODE_MIX; HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; @@ -467,7 +453,17 @@ public: MaterialStorage(); virtual ~MaterialStorage(); - Shaders shaders; + struct Shaders { + CanvasShaderGLES3 canvas_shader; + SkyShaderGLES3 sky_shader; + SceneShaderGLES3 scene_shader; + CubemapFilterShaderGLES3 cubemap_filter_shader; + + ShaderCompiler compiler_canvas; + ShaderCompiler compiler_scene; + ShaderCompiler compiler_particles; + ShaderCompiler compiler_sky; + } shaders; /* GLOBAL VARIABLE API */ diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index f932fa8bad..42c80da39a 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -32,6 +32,7 @@ #include "texture_storage.h" #include "config.h" +#include "drivers/gles3/effects/copy_effects.h" using namespace GLES3; @@ -55,8 +56,6 @@ TextureStorage::TextureStorage() { system_fbo = 0; - frame.current_rt = nullptr; - { //create default textures { // White Textures @@ -247,7 +246,7 @@ void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS: /* Texture API */ -Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const { +Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const { Config *config = Config::get_singleton(); r_gl_format = 0; Ref<Image> image = p_image; @@ -295,14 +294,12 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I r_gl_internal_format = GL_RGB8; r_gl_format = GL_RGB; r_gl_type = GL_UNSIGNED_BYTE; - //r_srgb = true; } break; case Image::FORMAT_RGBA8: { r_gl_format = GL_RGBA; r_gl_internal_format = GL_RGBA8; r_gl_type = GL_UNSIGNED_BYTE; - //r_srgb = true; } break; case Image::FORMAT_RGBA4444: { @@ -311,12 +308,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I r_gl_type = GL_UNSIGNED_SHORT_4_4_4_4; } break; - //case Image::FORMAT_RGBA5551: { - // r_gl_internal_format = GL_RGB5_A1; - // r_gl_format = GL_RGBA; - // r_gl_type = GL_UNSIGNED_SHORT_5_5_5_1; - // - //} break; case Image::FORMAT_RF: { r_gl_internal_format = GL_R32F; r_gl_format = GL_RED; @@ -376,8 +367,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - //r_srgb = true; - } else { need_decompress = true; } @@ -388,8 +377,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - //r_srgb = true; - } else { need_decompress = true; } @@ -400,8 +387,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - //r_srgb = true; - } else { need_decompress = true; } @@ -412,7 +397,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - } else { need_decompress = true; } @@ -433,8 +417,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - //r_srgb = true; - } else { need_decompress = true; } @@ -459,19 +441,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I need_decompress = true; } } break; - case Image::FORMAT_ETC: { - if (config->etc_supported) { - r_gl_internal_format = _EXT_ETC1_RGB8_OES; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - need_decompress = true; - } - - } break; - /* case Image::FORMAT_ETC2_R11: { if (config->etc2_supported) { r_gl_internal_format = _EXT_COMPRESSED_R11_EAC; @@ -516,13 +485,13 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I need_decompress = true; } } break; + case Image::FORMAT_ETC: case Image::FORMAT_ETC2_RGB8: { if (config->etc2_supported) { r_gl_internal_format = _EXT_COMPRESSED_RGB8_ETC2; r_gl_format = GL_RGB; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - //r_srgb = true; } else { need_decompress = true; @@ -534,7 +503,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - //r_srgb = true; } else { need_decompress = true; @@ -546,13 +514,11 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - //r_srgb = true; } else { need_decompress = true; } } break; - */ default: { ERR_FAIL_V_MSG(Ref<Image>(), "Image Format: " + itos(p_format) + " is not supported by the OpenGL3 Renderer"); } @@ -643,7 +609,7 @@ void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_im texture.format = p_image->get_format(); texture.type = Texture::TYPE_2D; texture.target = GL_TEXTURE_2D; - _get_gl_image_and_format(Ref<Image>(), texture.format, 0, texture.real_format, texture.gl_format_cache, texture.gl_internal_format_cache, texture.gl_type_cache, texture.compressed, false); + _get_gl_image_and_format(Ref<Image>(), texture.format, texture.real_format, texture.gl_format_cache, texture.gl_internal_format_cache, texture.gl_type_cache, texture.compressed, false); //texture.total_data_size = p_image->get_image_data_size(); // verify that this returns size in bytes texture.active = true; glGenTextures(1, &texture.tex_id); @@ -880,11 +846,6 @@ void TextureStorage::texture_set_detect_3d_callback(RID p_texture, RS::TextureDe } void TextureStorage::texture_set_detect_srgb_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { - Texture *texture = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!texture); - - texture->detect_srgb = p_callback; - texture->detect_srgb_ud = p_userdata; } void TextureStorage::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { @@ -967,7 +928,7 @@ void TextureStorage::texture_set_data(RID p_texture, const Ref<Image> &p_image, // print_line("texture_set_data width " + itos (p_image->get_width()) + " height " + itos(p_image->get_height())); Image::Format real_format; - Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), 0, real_format, format, internal_format, type, compressed, texture->resize_to_po2); + Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), real_format, format, internal_format, type, compressed, texture->resize_to_po2); ERR_FAIL_COND(img.is_null()); if (texture->resize_to_po2) { if (p_image->is_compressed()) { @@ -1054,11 +1015,6 @@ void TextureStorage::texture_set_data(RID p_texture, const Ref<Image> &p_image, texture->stored_cube_sides |= (1 << p_layer); - //if ((texture->flags & TEXTURE_FLAG_MIPMAPS) && mipmaps == 1 && !texture->ignore_mipmaps && (texture->type != RenderingDevice::TEXTURE_TYPE_CUBE || texture->stored_cube_sides == (1 << 6) - 1)) { - //generate mipmaps if they were requested and the image does not contain them - // glGenerateMipmap(texture->target); - //} - texture->mipmaps = mipmaps; } @@ -1066,128 +1022,6 @@ void TextureStorage::texture_set_data_partial(RID p_texture, const Ref<Image> &p ERR_PRINT("Not implemented yet, sorry :("); } -/* -Ref<Image> TextureStorage::texture_get_data(RID p_texture, int p_layer) const { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND_V(!texture, Ref<Image>()); - ERR_FAIL_COND_V(!texture->active, Ref<Image>()); - ERR_FAIL_COND_V(texture->data_size == 0 && !texture->render_target, Ref<Image>()); - - -#ifdef GLES_OVER_GL - - Image::Format real_format; - GLenum gl_format; - GLenum gl_internal_format; - GLenum gl_type; - bool compressed; - _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, false); - - PoolVector<uint8_t> data; - - int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1); - - data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers - PoolVector<uint8_t>::Write wb = data.write(); - - glActiveTexture(GL_TEXTURE0); - - glBindTexture(texture->target, texture->tex_id); - - glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); - - for (int i = 0; i < texture->mipmaps; i++) { - int ofs = Image::get_image_mipmap_offset(texture->alloc_width, texture->alloc_height, real_format, i); - - if (texture->compressed) { - glPixelStorei(GL_PACK_ALIGNMENT, 4); - glGetCompressedTexImage(texture->target, i, &wb[ofs]); - } else { - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glGetTexImage(texture->target, i, texture->gl_format_cache, texture->gl_type_cache, &wb[ofs]); - } - } - - wb.release(); - - data.resize(data_size); - - Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, texture->mipmaps > 1, real_format, data)); - - return Ref<Image>(img); -#else - - Image::Format real_format; - GLenum gl_format; - GLenum gl_internal_format; - GLenum gl_type; - bool compressed; - _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, texture->resize_to_po2); - - PoolVector<uint8_t> data; - - int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false); - - data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers - PoolVector<uint8_t>::Write wb = data.write(); - - GLuint temp_framebuffer; - glGenFramebuffers(1, &temp_framebuffer); - - GLuint temp_color_texture; - glGenTextures(1, &temp_color_texture); - - glBindFramebuffer(GL_FRAMEBUFFER, temp_framebuffer); - - glBindTexture(GL_TEXTURE_2D, temp_color_texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temp_color_texture, 0); - - glDepthMask(GL_FALSE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glDisable(GL_BLEND); - glDepthFunc(GL_LEQUAL); - glColorMask(1, 1, 1, 1); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture->tex_id); - - glViewport(0, 0, texture->alloc_width, texture->alloc_height); - - shaders.copy.bind(); - - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - bind_quad_array(); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &wb[0]); - - glDeleteTextures(1, &temp_color_texture); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glDeleteFramebuffers(1, &temp_framebuffer); - - wb.release(); - - data.resize(data_size); - - Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, false, Image::FORMAT_RGBA8, data)); - if (!texture->compressed) { - img->convert(real_format); - } - - return Ref<Image>(img); - -#endif -} -*/ - Image::Format TextureStorage::texture_get_format(RID p_texture) const { Texture *texture = texture_owner.get_or_null(p_texture); @@ -1285,32 +1119,6 @@ AABB TextureStorage::decal_get_aabb(RID p_decal) const { GLuint TextureStorage::system_fbo = 0; -void TextureStorage::_set_current_render_target(RID p_render_target) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - - if (rt) { - if (rt->allocate_is_dirty) { - rt->allocate_is_dirty = false; - //_clear_render_target(rt); - //_update_render_target(rt); - } - - frame.current_rt = rt; - ERR_FAIL_COND(!rt); - - glViewport(rt->position.x, rt->position.y, rt->size.x, rt->size.y); - - _dims.rt_width = rt->size.x; - _dims.rt_height = rt->size.y; - _dims.win_width = rt->size.x; - _dims.win_height = rt->size.y; - - } else { - frame.current_rt = nullptr; - glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo); - } -} - void TextureStorage::_update_render_target(RenderTarget *rt) { // do not allocate a render target with no size if (rt->size.x <= 0 || rt->size.y <= 0) { @@ -1318,14 +1126,14 @@ void TextureStorage::_update_render_target(RenderTarget *rt) { } // do not allocate a render target that is attached to the screen - if (rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) { + if (rt->direct_to_screen) { rt->fbo = system_fbo; return; } - rt->color_internal_format = rt->flags[RENDER_TARGET_TRANSPARENT] ? GL_RGBA8 : GL_RGB10_A2; + rt->color_internal_format = rt->is_transparent ? GL_RGBA8 : GL_RGB10_A2; rt->color_format = GL_RGBA; - rt->color_type = rt->flags[RENDER_TARGET_TRANSPARENT] ? GL_BYTE : GL_UNSIGNED_INT_2_10_10_10_REV; + rt->color_type = rt->is_transparent ? GL_BYTE : GL_UNSIGNED_INT_2_10_10_10_REV; rt->image_format = Image::FORMAT_RGBA8; glDisable(GL_SCISSOR_TEST); @@ -1388,87 +1196,64 @@ void TextureStorage::_update_render_target(RenderTarget *rt) { glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); + glBindFramebuffer(GL_FRAMEBUFFER, system_fbo); +} +void TextureStorage::_create_render_target_backbuffer(RenderTarget *rt) { + ERR_FAIL_COND_MSG(rt->backbuffer_fbo != 0, "Cannot allocate RenderTarget backbuffer: already initialized."); + ERR_FAIL_COND(rt->direct_to_screen); // Allocate mipmap chains for full screen blur - if (rt->size.x >= 2 && rt->size.y >= 2) { - for (int i = 0; i < 2; i++) { - ERR_FAIL_COND(rt->mip_maps[i].sizes.size()); - int w = rt->size.x; - int h = rt->size.y; - - if (i > 0) { - w >>= 1; - h >>= 1; - } - - int level = 0; - GLsizei width = w; - GLsizei height = h; + // Limit mipmaps so smallest is 32x32 to avoid unnecessary framebuffer switches + int count = MAX(1, Image::get_image_required_mipmaps(rt->size.x, rt->size.y, Image::FORMAT_RGBA8) - 4); + if (rt->size.x > 40 && rt->size.y > 40) { + GLsizei width = rt->size.x; + GLsizei height = rt->size.y; - while (true) { - RenderTarget::MipMaps::Size mm; - mm.width = w; - mm.height = h; - rt->mip_maps[i].sizes.push_back(mm); + rt->mipmap_count = count; - w >>= 1; - h >>= 1; + glGenTextures(1, &rt->backbuffer); + glBindTexture(GL_TEXTURE_2D, rt->backbuffer); - if (w < 2 || h < 2) { - break; - } - - level++; - } - - glGenTextures(1, &rt->mip_maps[i].color); - glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].color); - - for (int l = 0; l < level + 1; l++) { - glTexImage2D(GL_TEXTURE_2D, l, rt->color_internal_format, width, height, 0, rt->color_format, rt->color_type, nullptr); - width = MAX(1, (width / 2)); - height = MAX(1, (height / 2)); - } -#ifdef GLES_OVER_GL - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level); -#endif + for (int l = 0; l < count; l++) { + glTexImage2D(GL_TEXTURE_2D, l, rt->color_internal_format, width, height, 0, rt->color_format, rt->color_type, nullptr); + width = MAX(1, (width / 2)); + height = MAX(1, (height / 2)); + } - for (int j = 0; j < rt->mip_maps[i].sizes.size(); j++) { - RenderTarget::MipMaps::Size &mm = rt->mip_maps[i].sizes.write[j]; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, count - 1); - glGenFramebuffers(1, &mm.fbo); - bind_framebuffer(mm.fbo); + glGenFramebuffers(1, &rt->backbuffer_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, rt->backbuffer_fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->mip_maps[i].color, j); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->backbuffer, 0); - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - WARN_PRINT_ONCE("Cannot allocate mipmaps for canvas screen blur. Status: " + get_framebuffer_error(status)); - bind_framebuffer_system(); - return; - } + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + WARN_PRINT_ONCE("Cannot allocate mipmaps for canvas screen blur. Status: " + get_framebuffer_error(status)); + glBindFramebuffer(GL_FRAMEBUFFER, system_fbo); + return; + } - glClearColor(1.0, 0.0, 1.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - } + // Initialize all levels to opaque Magenta. + for (int j = 0; j < count; j++) { + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->backbuffer, j); + glClearColor(1.0, 0.0, 1.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + } - rt->mip_maps[i].levels = level; + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->backbuffer, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } - rt->mip_maps_allocated = true; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } - - bind_framebuffer_system(); } void TextureStorage::_clear_render_target(RenderTarget *rt) { // there is nothing to clear when DIRECT_TO_SCREEN is used - if (rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) { + if (rt->direct_to_screen) { return; } @@ -1504,17 +1289,11 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) { tex->height = 0; tex->active = false; - for (int i = 0; i < 2; i++) { - if (rt->mip_maps[i].sizes.size()) { - for (int j = 0; j < rt->mip_maps[i].sizes.size(); j++) { - glDeleteFramebuffers(1, &rt->mip_maps[i].sizes[j].fbo); - } - - glDeleteTextures(1, &rt->mip_maps[i].color); - rt->mip_maps[i].sizes.clear(); - rt->mip_maps[i].levels = 0; - rt->mip_maps[i].color = 0; - } + if (rt->backbuffer_fbo != 0) { + glDeleteFramebuffers(1, &rt->backbuffer_fbo); + glDeleteTextures(1, &rt->backbuffer); + rt->backbuffer = 0; + rt->backbuffer_fbo = 0; } } @@ -1523,9 +1302,6 @@ RID TextureStorage::render_target_create() { //render_target.was_used = false; render_target.clear_requested = false; - for (int i = 0; i < RENDER_TARGET_FLAG_MAX; i++) { - render_target.flags[i] = false; - } Texture t; t.active = true; t.render_target = &render_target; @@ -1568,9 +1344,6 @@ void TextureStorage::render_target_set_size(RID p_render_target, int p_width, in rt->size = Size2i(p_width, p_height); - // print_line("render_target_set_size " + itos(p_render_target.get_id()) + ", w " + itos(p_width) + " h " + itos(p_height)); - - rt->allocate_is_dirty = true; _update_render_target(rt); } @@ -1642,7 +1415,6 @@ void TextureStorage::render_target_set_external_texture(RID p_render_target, uns t->gl_format_cache = 0; t->gl_internal_format_cache = 0; t->gl_type_cache = 0; - t->srgb = false; t->total_data_size = 0; t->mipmaps = 1; t->active = true; @@ -1688,29 +1460,28 @@ void TextureStorage::render_target_set_external_texture(RID p_render_target, uns } } -void TextureStorage::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) { +void TextureStorage::render_target_set_transparent(RID p_render_target, bool p_transparent) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); - // When setting DIRECT_TO_SCREEN, you need to clear before the value is set, but allocate after as - // those functions change how they operate depending on the value of DIRECT_TO_SCREEN - if (p_flag == RENDER_TARGET_DIRECT_TO_SCREEN && p_value != rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) { - _clear_render_target(rt); - rt->flags[p_flag] = p_value; - _update_render_target(rt); - } + rt->is_transparent = p_transparent; - rt->flags[p_flag] = p_value; + _clear_render_target(rt); + _update_render_target(rt); +} - switch (p_flag) { - case RENDER_TARGET_TRANSPARENT: { - //must reset for these formats - _clear_render_target(rt); - _update_render_target(rt); - } break; - default: { - } +void TextureStorage::render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND(!rt); + + if (p_direct_to_screen == rt->direct_to_screen) { + return; } + // When setting DIRECT_TO_SCREEN, you need to clear before the value is set, but allocate after as + // those functions change how they operate depending on the value of DIRECT_TO_SCREEN + _clear_render_target(rt); + rt->direct_to_screen = p_direct_to_screen; + _update_render_target(rt); } bool TextureStorage::render_target_was_used(RID p_render_target) { @@ -1772,4 +1543,85 @@ Rect2i TextureStorage::render_target_get_sdf_rect(RID p_render_target) const { void TextureStorage::render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) { } +void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps) { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND(!rt); + ERR_FAIL_COND(rt->direct_to_screen); + + if (rt->backbuffer_fbo == 0) { + _create_render_target_backbuffer(rt); + } + + Rect2i region; + if (p_region == Rect2i()) { + region.size = rt->size; + } else { + region = Rect2i(Size2i(), rt->size).intersection(p_region); + if (region.size == Size2i()) { + return; //nothing to do + } + } + + glDisable(GL_BLEND); + //single texture copy for backbuffer + glBindFramebuffer(GL_FRAMEBUFFER, rt->backbuffer_fbo); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, rt->color); + GLES3::CopyEffects::get_singleton()->copy_screen(); + + if (p_gen_mipmaps) { + GLES3::CopyEffects::get_singleton()->bilinear_blur(rt->backbuffer, rt->mipmap_count, region); + glBindFramebuffer(GL_FRAMEBUFFER, rt->backbuffer_fbo); + } + + glEnable(GL_BLEND); // 2D almost always uses blend. +} + +void TextureStorage::render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color) { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND(!rt); + ERR_FAIL_COND(rt->direct_to_screen); + + if (rt->backbuffer_fbo == 0) { + _create_render_target_backbuffer(rt); + } + + Rect2i region; + if (p_region == Rect2i()) { + // Just do a full screen clear; + glBindFramebuffer(GL_FRAMEBUFFER, rt->backbuffer_fbo); + glClearColor(p_color.r, p_color.g, p_color.b, p_color.a); + glClear(GL_COLOR_BUFFER_BIT); + } else { + region = Rect2i(Size2i(), rt->size).intersection(p_region); + if (region.size == Size2i()) { + return; //nothing to do + } + glBindFramebuffer(GL_FRAMEBUFFER, rt->backbuffer_fbo); + GLES3::CopyEffects::get_singleton()->set_color(p_color, region); + } +} + +void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND(!rt); + + if (rt->backbuffer_fbo == 0) { + _create_render_target_backbuffer(rt); + } + + Rect2i region; + if (p_region == Rect2i()) { + region.size = rt->size; + } else { + region = Rect2i(Size2i(), rt->size).intersection(p_region); + if (region.size == Size2i()) { + return; //nothing to do + } + } + + GLES3::CopyEffects::get_singleton()->bilinear_blur(rt->backbuffer, rt->mipmap_count, region); + glBindFramebuffer(GL_FRAMEBUFFER, rt->backbuffer_fbo); +} + #endif // GLES3_ENABLED diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h index b092a009c1..d6d04e45a1 100644 --- a/drivers/gles3/storage/texture_storage.h +++ b/drivers/gles3/storage/texture_storage.h @@ -71,6 +71,17 @@ namespace GLES3 { #define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E #define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F +#define _EXT_COMPRESSED_R11_EAC 0x9270 +#define _EXT_COMPRESSED_SIGNED_R11_EAC 0x9271 +#define _EXT_COMPRESSED_RG11_EAC 0x9272 +#define _EXT_COMPRESSED_SIGNED_RG11_EAC 0x9273 +#define _EXT_COMPRESSED_RGB8_ETC2 0x9274 +#define _EXT_COMPRESSED_SRGB8_ETC2 0x9275 +#define _EXT_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 +#define _EXT_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 +#define _EXT_COMPRESSED_RGBA8_ETC2_EAC 0x9278 +#define _EXT_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 + #define _GL_TEXTURE_EXTERNAL_OES 0x8D65 #ifdef GLES_OVER_GL @@ -161,8 +172,6 @@ struct Texture { bool compressed = false; - bool srgb = false; - bool resize_to_po2 = false; bool active = false; @@ -179,9 +188,6 @@ struct Texture { RS::TextureDetectCallback detect_3d_callback = nullptr; void *detect_3d_callback_ud = nullptr; - RS::TextureDetectCallback detect_srgb = nullptr; - void *detect_srgb_ud = nullptr; - RS::TextureDetectCallback detect_normal_callback = nullptr; void *detect_normal_callback_ud = nullptr; @@ -213,8 +219,6 @@ struct Texture { redraw_if_visible = o.redraw_if_visible; detect_3d_callback = o.detect_3d_callback; detect_3d_callback_ud = o.detect_3d_callback_ud; - detect_srgb = o.detect_srgb; - detect_srgb_ud = o.detect_srgb_ud; detect_normal_callback = o.detect_normal_callback; detect_normal_callback_ud = o.detect_normal_callback_ud; detect_roughness_callback = o.detect_roughness_callback; @@ -311,21 +315,6 @@ private: }; struct RenderTarget { - struct MipMaps { - struct Size { - GLuint fbo; - int width; - int height; - }; - - Vector<Size> sizes; - GLuint color = 0; - int levels = 0; - - MipMaps() { - } - }; - struct External { GLuint fbo = 0; GLuint color = 0; @@ -338,23 +327,21 @@ struct RenderTarget { Point2i position = Point2i(0, 0); Size2i size = Size2i(0, 0); + int mipmap_count = 1; RID self; GLuint fbo = 0; GLuint color = 0; + GLuint backbuffer_fbo = 0; + GLuint backbuffer = 0; GLuint color_internal_format = GL_RGBA8; GLuint color_format = GL_RGBA; GLuint color_type = GL_UNSIGNED_BYTE; Image::Format image_format = Image::FORMAT_RGBA8; - MipMaps mip_maps[2]; - bool mip_maps_allocated = false; - - bool flags[RendererTextureStorage::RENDER_TARGET_FLAG_MAX]; + bool is_transparent = false; + bool direct_to_screen = false; - // instead of allocating sized render targets immediately, - // defer this for faster startup - bool allocate_is_dirty = false; bool used_in_frame = false; RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED; @@ -364,9 +351,6 @@ struct RenderTarget { bool clear_requested = false; RenderTarget() { - for (int i = 0; i < RendererTextureStorage::RENDER_TARGET_FLAG_MAX; ++i) { - flags[i] = false; - } } }; @@ -384,28 +368,15 @@ private: mutable RID_Owner<Texture> texture_owner; - Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const; + Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const; /* Render Target API */ mutable RID_Owner<RenderTarget> render_target_owner; - // make access easier to these - struct Dimensions { - // render target - int rt_width; - int rt_height; - - // window - int win_width; - int win_height; - Dimensions() { - rt_width = 0; - rt_height = 0; - win_width = 0; - win_height = 0; - } - } _dims; + void _clear_render_target(RenderTarget *rt); + void _update_render_target(RenderTarget *rt); + void _create_render_target_backbuffer(RenderTarget *rt); public: static TextureStorage *get_singleton(); @@ -522,20 +493,9 @@ public: static GLuint system_fbo; - // TODO this should be moved back to storage or removed - struct Frame { - GLES3::RenderTarget *current_rt; - } frame; - 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); }; - // TODO these internals should be private - void _clear_render_target(RenderTarget *rt); - void _update_render_target(RenderTarget *rt); - void _create_render_target_backbuffer(RenderTarget *rt); - void _set_current_render_target(RID p_render_target); - virtual RID render_target_create() override; virtual void render_target_free(RID p_rid) override; virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override; @@ -544,7 +504,8 @@ public: virtual RID render_target_get_texture(RID p_render_target) override; virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override; - virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override; + virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) override; + virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) override; virtual bool render_target_was_used(RID p_render_target) override; void render_target_clear_used(RID p_render_target); @@ -563,13 +524,9 @@ public: Rect2i render_target_get_sdf_rect(RID p_render_target) const override; void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override; - void bind_framebuffer(GLuint framebuffer) { - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - } - - void bind_framebuffer_system() { - glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo); - } + void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps); + void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color); + void render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region); String get_framebuffer_error(GLenum p_status); }; diff --git a/drivers/gles3/texture_loader_gles3.cpp b/drivers/gles3/texture_loader_gles3.cpp deleted file mode 100644 index ba4ddb3b37..0000000000 --- a/drivers/gles3/texture_loader_gles3.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/*************************************************************************/ -/* texture_loader_gles3.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "texture_loader_gles3.h" - -#ifdef GLES3_ENABLED - -#include "core/io/file_access.h" -#include "core/string/print_string.h" - -#include <string.h> - -Ref<Resource> ResourceFormatGLES2Texture::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { - unsigned int width = 8; - unsigned int height = 8; - - //We just use some format - Image::Format fmt = Image::FORMAT_RGB8; - int rowsize = 3 * width; - - Vector<uint8_t> dstbuff; - - dstbuff.resize(rowsize * height); - - uint8_t **row_p = memnew_arr(uint8_t *, height); - - for (unsigned int i = 0; i < height; i++) { - row_p[i] = nullptr; // No colors any more, I want them to turn black. - } - - memdelete_arr(row_p); - - Ref<Image> img = memnew(Image(width, height, 0, fmt, dstbuff)); - - Ref<ImageTexture> texture = memnew(ImageTexture); - texture->create_from_image(img); - - if (r_error) { - *r_error = OK; - } - - return texture; -} - -void ResourceFormatGLES2Texture::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("bmp"); - p_extensions->push_back("dds"); - p_extensions->push_back("exr"); - p_extensions->push_back("jpeg"); - p_extensions->push_back("jpg"); - p_extensions->push_back("hdr"); - p_extensions->push_back("pkm"); - p_extensions->push_back("png"); - p_extensions->push_back("pvr"); - p_extensions->push_back("svg"); - p_extensions->push_back("tga"); - p_extensions->push_back("webp"); -} - -bool ResourceFormatGLES2Texture::handles_type(const String &p_type) const { - return ClassDB::is_parent_class(p_type, "Texture2D"); -} - -String ResourceFormatGLES2Texture::get_resource_type(const String &p_path) const { - String extension = p_path.get_extension().to_lower(); - if ( - extension == "bmp" || - extension == "dds" || - extension == "exr" || - extension == "jpeg" || - extension == "jpg" || - extension == "hdr" || - extension == "pkm" || - extension == "png" || - extension == "pvr" || - extension == "svg" || - extension == "tga" || - extension == "webp") { - return "ImageTexture"; - } - - return ""; -} - -#endif diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h index 534b9f07d8..11d827a6e3 100644 --- a/servers/rendering/dummy/storage/texture_storage.h +++ b/servers/rendering/dummy/storage/texture_storage.h @@ -152,7 +152,8 @@ public: virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override {} virtual RID render_target_get_texture(RID p_render_target) override { return RID(); } virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override {} - virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override {} + virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) override {} + virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) override {} virtual bool render_target_was_used(RID p_render_target) override { return false; } virtual void render_target_set_as_unused(RID p_render_target) override {} diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index 7d4808f936..329c23bad0 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -2075,7 +2075,7 @@ void TextureStorage::_update_render_target(RenderTarget *rt) { //until we implement support for HDR monitors (and render target is attached to screen), this is enough. rt->color_format = RD::DATA_FORMAT_R8G8B8A8_UNORM; rt->color_format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - rt->image_format = rt->flags[RENDER_TARGET_TRANSPARENT] ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8; + rt->image_format = rt->is_transparent ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8; RD::TextureFormat rd_format; RD::TextureView rd_view; @@ -2127,7 +2127,7 @@ void TextureStorage::_update_render_target(RenderTarget *rt) { //so transparent can be supported RD::TextureView view; view.format_override = rt->color_format; - if (!rt->flags[RENDER_TARGET_TRANSPARENT]) { + if (!rt->is_transparent) { view.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; } tex->rd_texture = RD::get_singleton()->texture_create_shared(view, rt->color); @@ -2194,9 +2194,6 @@ RID TextureStorage::render_target_create() { render_target.was_used = false; render_target.clear_requested = false; - for (int i = 0; i < RENDER_TARGET_FLAG_MAX; i++) { - render_target.flags[i] = false; - } _update_render_target(&render_target); return render_target_owner.make_rid(render_target); } @@ -2240,13 +2237,16 @@ RID TextureStorage::render_target_get_texture(RID p_render_target) { void TextureStorage::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) { } -void TextureStorage::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) { +void TextureStorage::render_target_set_transparent(RID p_render_target, bool p_is_transparent) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); - rt->flags[p_flag] = p_value; + rt->is_transparent = p_is_transparent; _update_render_target(rt); } +void TextureStorage::render_target_set_direct_to_screen(RID p_render_target, bool p_value) { +} + bool TextureStorage::render_target_was_used(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND_V(!rt, false); diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index 418eb82808..901f764085 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -207,7 +207,7 @@ struct RenderTarget { RD::DataFormat color_format_srgb = RD::DATA_FORMAT_R4G4_UNORM_PACK8; Image::Format image_format = Image::FORMAT_L8; - bool flags[RendererTextureStorage::RENDER_TARGET_FLAG_MAX]; + bool is_transparent = false; bool sdf_enabled = false; @@ -525,7 +525,8 @@ public: virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override; virtual RID render_target_get_texture(RID p_render_target) override; virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override; - virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override; + virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) override; + virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) override; virtual bool render_target_was_used(RID p_render_target) override; virtual void render_target_set_as_unused(RID p_render_target) override; diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 7c2d7a1e1d..74fafe8381 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -866,7 +866,7 @@ void RendererViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count()); } - RSG::texture_storage->render_target_set_flag(viewport->render_target, RendererTextureStorage::RENDER_TARGET_DIRECT_TO_SCREEN, p_enable); + RSG::texture_storage->render_target_set_direct_to_screen(viewport->render_target, p_enable); viewport->viewport_render_direct_to_screen = p_enable; // if attached to screen already, setup screen size and position, this needs to happen after setting flag to avoid an unnecessary buffer allocation @@ -980,7 +980,7 @@ void RendererViewport::viewport_set_transparent_background(RID p_viewport, bool Viewport *viewport = viewport_owner.get_or_null(p_viewport); ERR_FAIL_COND(!viewport); - RSG::texture_storage->render_target_set_flag(viewport->render_target, RendererTextureStorage::RENDER_TARGET_TRANSPARENT, p_enabled); + RSG::texture_storage->render_target_set_transparent(viewport->render_target, p_enabled); viewport->transparent_bg = p_enabled; } diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h index 4c4213d7c1..e3a969d032 100644 --- a/servers/rendering/storage/texture_storage.h +++ b/servers/rendering/storage/texture_storage.h @@ -111,12 +111,6 @@ public: /* RENDER TARGET */ - enum RenderTargetFlags { - RENDER_TARGET_TRANSPARENT, - RENDER_TARGET_DIRECT_TO_SCREEN, - RENDER_TARGET_FLAG_MAX - }; - virtual RID render_target_create() = 0; virtual void render_target_free(RID p_rid) = 0; @@ -124,7 +118,8 @@ public: virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) = 0; virtual RID render_target_get_texture(RID p_render_target) = 0; virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) = 0; - virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) = 0; + virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) = 0; + virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) = 0; virtual bool render_target_was_used(RID p_render_target) = 0; virtual void render_target_set_as_unused(RID p_render_target) = 0; |