summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorclayjohn <claynjohn@gmail.com>2022-05-18 08:04:41 -0700
committerclayjohn <claynjohn@gmail.com>2022-05-24 11:00:34 -0700
commit3e20c1347db323438a76693bb9f7eea87f3a305d (patch)
tree98ed91197c8eaf8e4604089eea44c3c420ef5d22
parentd81c5eab8cfd1d91ef2cf1599a6b929ccbed0a3a (diff)
Add clipping, backbuffer, and CanvasGroups to 2D GLES3 renderer
As well as significant consequent cleanup in the RenderTarget, Texture, and Canvas renderer code
-rw-r--r--drivers/gles3/SCsub1
-rw-r--r--drivers/gles3/effects/SCsub5
-rw-r--r--drivers/gles3/effects/copy_effects.cpp164
-rw-r--r--drivers/gles3/effects/copy_effects.h (renamed from drivers/gles3/texture_loader_gles3.h)48
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp401
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h34
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp10
-rw-r--r--drivers/gles3/rasterizer_gles3.h2
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp110
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h43
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp10
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h42
-rw-r--r--drivers/gles3/shader_gles3.cpp2
-rw-r--r--drivers/gles3/shader_gles3.h1
-rw-r--r--drivers/gles3/shaders/copy.glsl181
-rw-r--r--drivers/gles3/storage/config.cpp68
-rw-r--r--drivers/gles3/storage/config.h25
-rw-r--r--drivers/gles3/storage/material_storage.cpp22
-rw-r--r--drivers/gles3/storage/material_storage.h28
-rw-r--r--drivers/gles3/storage/texture_storage.cpp450
-rw-r--r--drivers/gles3/storage/texture_storage.h93
-rw-r--r--drivers/gles3/texture_loader_gles3.cpp112
-rw-r--r--servers/rendering/dummy/storage/texture_storage.h3
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp14
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.h5
-rw-r--r--servers/rendering/renderer_viewport.cpp4
-rw-r--r--servers/rendering/storage/texture_storage.h9
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 *&current_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 *&current_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;