Add clipping, backbuffer, and CanvasGroups to 2D GLES3 renderer

As well as significant consequent cleanup in the RenderTarget, Texture, and Canvas renderer code
This commit is contained in:
clayjohn 2022-05-18 08:04:41 -07:00
parent d81c5eab8c
commit 3e20c1347d
27 changed files with 734 additions and 1173 deletions

View file

@ -6,3 +6,4 @@ env.add_source_files(env.drivers_sources, "*.cpp")
SConscript("shaders/SCsub")
SConscript("storage/SCsub")
SConscript("effects/SCsub")

View file

@ -0,0 +1,5 @@
#!/usr/bin/env python
Import("env")
env.add_source_files(env.drivers_sources, "*.cpp")

View file

@ -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

View file

@ -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();
virtual ~ResourceFormatGLES2Texture() {}
CopyEffects();
~CopyEffects();
// 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

View file

@ -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 (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->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 (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.current_pixel_size.x = 1.0 / float(ct->size_cache.x);
state.current_pixel_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;
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);

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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() {
}

View file

@ -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) {

View file

@ -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) {

View file

@ -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"

View file

@ -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 vec2 vertex_attrib;
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;
#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;
#ifdef MODE_SIMPLE_COLOR
uniform vec4 color_in;
#endif
#ifdef MODE_GAUSSIAN_BLUR
uniform highp vec2 pixel_size;
#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;
#endif
#ifdef USE_CUSTOM_ALPHA
uniform float custom_alpha;
#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
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);
#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;
#endif
frag_color = color;
#endif
#ifdef MODE_SIMPLE_COLOR
frag_color = color_in;
#endif
}

View file

@ -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
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);
#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
//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);

View file

@ -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();

View file

@ -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");

View file

@ -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 */

View file

@ -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;
// 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;
if (i > 0) {
w >>= 1;
h >>= 1;
}
rt->mipmap_count = count;
int level = 0;
GLsizei width = w;
GLsizei height = h;
glGenTextures(1, &rt->backbuffer);
glBindTexture(GL_TEXTURE_2D, rt->backbuffer);
while (true) {
RenderTarget::MipMaps::Size mm;
mm.width = w;
mm.height = h;
rt->mip_maps[i].sizes.push_back(mm);
w >>= 1;
h >>= 1;
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 j = 0; j < rt->mip_maps[i].sizes.size(); j++) {
RenderTarget::MipMaps::Size &mm = rt->mip_maps[i].sizes.write[j];
glGenFramebuffers(1, &mm.fbo);
bind_framebuffer(mm.fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->mip_maps[i].color, j);
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;
}
glClearColor(1.0, 0.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
}
rt->mip_maps[i].levels = level;
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);
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));
}
rt->mip_maps_allocated = true;
}
bind_framebuffer_system();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, count - 1);
glGenFramebuffers(1, &rt->backbuffer_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, rt->backbuffer_fbo);
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));
glBindFramebuffer(GL_FRAMEBUFFER, system_fbo);
return;
}
// 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);
}
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);
}
}
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);
rt->is_transparent = p_transparent;
_clear_render_target(rt);
_update_render_target(rt);
}
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
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->flags[p_flag] = p_value;
switch (p_flag) {
case RENDER_TARGET_TRANSPARENT: {
//must reset for these formats
_clear_render_target(rt);
_update_render_target(rt);
} break;
default: {
}
}
_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

View file

@ -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 is_transparent = false;
bool direct_to_screen = false;
bool flags[RendererTextureStorage::RENDER_TARGET_FLAG_MAX];
// 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);
};

View file

@ -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

View file

@ -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 {}

View file

@ -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);

View file

@ -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;

View file

@ -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;
}

View file

@ -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;