mirror of
https://github.com/godotengine/godot.git
synced 2024-11-12 23:24:26 +00:00
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:
parent
d81c5eab8c
commit
3e20c1347d
@ -6,3 +6,4 @@ env.add_source_files(env.drivers_sources, "*.cpp")
|
||||
|
||||
SConscript("shaders/SCsub")
|
||||
SConscript("storage/SCsub")
|
||||
SConscript("effects/SCsub")
|
||||
|
5
drivers/gles3/effects/SCsub
Normal file
5
drivers/gles3/effects/SCsub
Normal file
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
Import("env")
|
||||
|
||||
env.add_source_files(env.drivers_sources, "*.cpp")
|
164
drivers/gles3/effects/copy_effects.cpp
Normal file
164
drivers/gles3/effects/copy_effects.cpp
Normal 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
|
@ -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
|
@ -119,12 +119,11 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
|
||||
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
|
||||
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
|
||||
|
||||
texture_storage->frame.current_rt = nullptr;
|
||||
|
||||
texture_storage->_set_current_render_target(p_to_render_target);
|
||||
|
||||
Transform2D canvas_transform_inverse = p_canvas_transform.affine_inverse();
|
||||
|
||||
// Clear out any state that may have been left from the 3D pass.
|
||||
reset_canvas();
|
||||
|
||||
// TODO: Setup Directional Lights
|
||||
|
||||
// TODO: Setup lights
|
||||
@ -156,6 +155,9 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
|
||||
state_buffer.screen_pixel_size[0] = 1.0 / render_target_size.x;
|
||||
state_buffer.screen_pixel_size[1] = 1.0 / render_target_size.y;
|
||||
|
||||
// TODO: temporary, this should be set at the top of this function
|
||||
glViewport(0, 0, render_target_size.x, render_target_size.y);
|
||||
|
||||
state_buffer.time = state.time;
|
||||
state_buffer.use_pixel_snap = p_snap_2d_vertices_to_pixel;
|
||||
|
||||
@ -177,7 +179,6 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
|
||||
state_buffer.sdf_to_tex[2] = -sdf_tex_rect.position.x / sdf_tex_rect.size.width;
|
||||
state_buffer.sdf_to_tex[3] = -sdf_tex_rect.position.y / sdf_tex_rect.size.height;
|
||||
|
||||
//print_line("w: " + itos(ssize.width) + " s: " + rtos(canvas_scale));
|
||||
state_buffer.tex_to_sdf = 1.0 / ((canvas_scale.x + canvas_scale.y) * 0.5);
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, BASE_UNIFORM_LOCATION, state.canvas_state_buffer);
|
||||
glBufferData(GL_UNIFORM_BUFFER, sizeof(StateBuffer), &state_buffer, GL_STREAM_DRAW);
|
||||
@ -193,17 +194,100 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
|
||||
state.default_repeat = p_default_repeat;
|
||||
}
|
||||
|
||||
state.current_tex = RID();
|
||||
state.current_tex_ptr = nullptr;
|
||||
state.current_normal = RID();
|
||||
state.current_specular = RID();
|
||||
state.canvas_texscreen_used = false;
|
||||
|
||||
r_sdf_used = false;
|
||||
int item_count = 0;
|
||||
bool backbuffer_cleared = false;
|
||||
bool time_used = false;
|
||||
bool material_screen_texture_found = false;
|
||||
Rect2 back_buffer_rect;
|
||||
bool backbuffer_copy = false;
|
||||
|
||||
Item *ci = p_item_list;
|
||||
Item *canvas_group_owner = nullptr;
|
||||
|
||||
while (ci) {
|
||||
if (ci->copy_back_buffer && canvas_group_owner == nullptr) {
|
||||
backbuffer_copy = true;
|
||||
|
||||
if (ci->copy_back_buffer->full) {
|
||||
back_buffer_rect = Rect2();
|
||||
} else {
|
||||
back_buffer_rect = ci->copy_back_buffer->rect;
|
||||
}
|
||||
}
|
||||
|
||||
// Check material for something that may change flow of rendering, but do not bind for now.
|
||||
RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
|
||||
if (material.is_valid()) {
|
||||
GLES3::CanvasMaterialData *md = static_cast<GLES3::CanvasMaterialData *>(material_storage->material_get_data(material, RS::SHADER_CANVAS_ITEM));
|
||||
if (md && md->shader_data->valid) {
|
||||
if (md->shader_data->uses_screen_texture && canvas_group_owner == nullptr) {
|
||||
if (!material_screen_texture_found) {
|
||||
backbuffer_copy = true;
|
||||
back_buffer_rect = Rect2();
|
||||
}
|
||||
}
|
||||
|
||||
if (md->shader_data->uses_sdf) {
|
||||
r_sdf_used = true;
|
||||
}
|
||||
if (md->shader_data->uses_time) {
|
||||
time_used = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ci->canvas_group_owner != nullptr) {
|
||||
if (canvas_group_owner == nullptr) {
|
||||
// Canvas group begins here, render until before this item
|
||||
|
||||
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
|
||||
item_count = 0;
|
||||
|
||||
Rect2i group_rect = ci->canvas_group_owner->global_rect_cache;
|
||||
|
||||
if (ci->canvas_group_owner->canvas_group->mode == RS::CANVAS_GROUP_MODE_OPAQUE) {
|
||||
texture_storage->render_target_copy_to_back_buffer(p_to_render_target, group_rect, false);
|
||||
} else if (!backbuffer_cleared) {
|
||||
texture_storage->render_target_clear_back_buffer(p_to_render_target, Rect2i(), Color(0, 0, 0, 0));
|
||||
backbuffer_cleared = true;
|
||||
}
|
||||
|
||||
backbuffer_copy = false;
|
||||
canvas_group_owner = ci->canvas_group_owner; //continue until owner found
|
||||
}
|
||||
|
||||
ci->canvas_group_owner = nullptr; //must be cleared
|
||||
}
|
||||
|
||||
if (!backbuffer_cleared && canvas_group_owner == nullptr && ci->canvas_group != nullptr && !backbuffer_copy) {
|
||||
texture_storage->render_target_clear_back_buffer(p_to_render_target, Rect2i(), Color(0, 0, 0, 0));
|
||||
backbuffer_cleared = true;
|
||||
}
|
||||
|
||||
if (ci == canvas_group_owner) {
|
||||
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, true);
|
||||
item_count = 0;
|
||||
|
||||
if (ci->canvas_group->blur_mipmaps) {
|
||||
texture_storage->render_target_gen_back_buffer_mipmaps(p_to_render_target, ci->global_rect_cache);
|
||||
}
|
||||
|
||||
canvas_group_owner = nullptr;
|
||||
}
|
||||
|
||||
if (backbuffer_copy) {
|
||||
//render anything pending, including clearing if no items
|
||||
|
||||
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
|
||||
item_count = 0;
|
||||
|
||||
texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, true);
|
||||
|
||||
backbuffer_copy = false;
|
||||
material_screen_texture_found = true; //after a backbuffer copy, screen texture makes no further copies
|
||||
}
|
||||
|
||||
// just add all items for now
|
||||
items[item_count++] = ci;
|
||||
|
||||
@ -215,27 +299,52 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
|
||||
|
||||
ci = ci->next;
|
||||
}
|
||||
|
||||
if (time_used) {
|
||||
RenderingServerDefault::redraw_request();
|
||||
}
|
||||
|
||||
// Clear out state used in 2D pass
|
||||
reset_canvas();
|
||||
}
|
||||
|
||||
void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer) {
|
||||
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
|
||||
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
|
||||
Item *current_clip = nullptr;
|
||||
|
||||
Transform2D canvas_transform_inverse = p_canvas_transform_inverse;
|
||||
|
||||
RID framebuffer;
|
||||
Vector<Color> clear_colors;
|
||||
|
||||
canvas_begin();
|
||||
canvas_begin(p_to_render_target, p_to_backbuffer);
|
||||
|
||||
RID prev_material;
|
||||
uint32_t index = 0;
|
||||
GLES3::CanvasShaderData::BlendMode last_blend_mode = GLES3::CanvasShaderData::BLEND_MODE_MIX;
|
||||
GLES3::CanvasShaderData *shader_data_cache = nullptr;
|
||||
|
||||
state.current_tex = texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE);
|
||||
state.current_tex_ptr = nullptr;
|
||||
state.current_normal = RID();
|
||||
state.current_specular = RID();
|
||||
state.canvas_texscreen_used = false;
|
||||
state.current_shader_version = state.canvas_shader_default_version;
|
||||
|
||||
for (int i = 0; i < p_item_count; i++) {
|
||||
Item *ci = items[i];
|
||||
|
||||
if (current_clip != ci->final_clip_owner) {
|
||||
_render_batch(index);
|
||||
|
||||
current_clip = ci->final_clip_owner;
|
||||
//setup clip
|
||||
if (current_clip) {
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glScissor(current_clip->final_clip_rect.position.x, current_clip->final_clip_rect.position.y, current_clip->final_clip_rect.size.x, current_clip->final_clip_rect.size.y);
|
||||
} else {
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
|
||||
|
||||
if (material.is_null() && ci->canvas_group != nullptr) {
|
||||
@ -243,6 +352,7 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
|
||||
}
|
||||
|
||||
if (material != prev_material) {
|
||||
_render_batch(index);
|
||||
GLES3::CanvasMaterialData *material_data = nullptr;
|
||||
if (material.is_valid()) {
|
||||
material_data = static_cast<GLES3::CanvasMaterialData *>(material_storage->material_get_data(material, RS::SHADER_CANVAS_ITEM));
|
||||
@ -252,22 +362,86 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
|
||||
// Bind uniform buffer and textures
|
||||
material_data->bind_uniforms();
|
||||
state.current_shader_version = material_data->shader_data->version;
|
||||
shader_data_cache = material_data->shader_data;
|
||||
} else {
|
||||
state.current_shader_version = state.canvas_shader_default_version;
|
||||
shader_data_cache = nullptr;
|
||||
}
|
||||
} else {
|
||||
state.current_shader_version = state.canvas_shader_default_version;
|
||||
shader_data_cache = nullptr;
|
||||
}
|
||||
prev_material = material;
|
||||
}
|
||||
|
||||
GLES3::CanvasShaderData::BlendMode blend_mode = shader_data_cache ? shader_data_cache->blend_mode : GLES3::CanvasShaderData::BLEND_MODE_MIX;
|
||||
|
||||
if (last_blend_mode != blend_mode) {
|
||||
if (last_blend_mode == GLES3::CanvasShaderData::BLEND_MODE_DISABLED) {
|
||||
// re-enable it
|
||||
glEnable(GL_BLEND);
|
||||
} else if (blend_mode == GLES3::CanvasShaderData::BLEND_MODE_DISABLED) {
|
||||
// disable it
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
switch (blend_mode) {
|
||||
case GLES3::CanvasShaderData::BLEND_MODE_DISABLED: {
|
||||
// Nothing to do here.
|
||||
|
||||
} break;
|
||||
case GLES3::CanvasShaderData::BLEND_MODE_MIX: {
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
if (state.transparent_render_target) {
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
} else {
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
|
||||
}
|
||||
|
||||
} break;
|
||||
case GLES3::CanvasShaderData::BLEND_MODE_ADD: {
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
if (state.transparent_render_target) {
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_SRC_ALPHA, GL_ONE);
|
||||
} else {
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
|
||||
}
|
||||
|
||||
} break;
|
||||
case GLES3::CanvasShaderData::BLEND_MODE_SUB: {
|
||||
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
|
||||
if (state.transparent_render_target) {
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_SRC_ALPHA, GL_ONE);
|
||||
} else {
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
|
||||
}
|
||||
} break;
|
||||
case GLES3::CanvasShaderData::BLEND_MODE_MUL: {
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
if (state.transparent_render_target) {
|
||||
glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_DST_ALPHA, GL_ZERO);
|
||||
} else {
|
||||
glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ZERO, GL_ONE);
|
||||
}
|
||||
|
||||
} break;
|
||||
case GLES3::CanvasShaderData::BLEND_MODE_PMALPHA: {
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
if (state.transparent_render_target) {
|
||||
glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
} else {
|
||||
glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
|
||||
}
|
||||
|
||||
} break;
|
||||
}
|
||||
last_blend_mode = blend_mode;
|
||||
}
|
||||
|
||||
_render_item(p_to_render_target, ci, canvas_transform_inverse, current_clip, p_lights, index);
|
||||
}
|
||||
// Render last command
|
||||
state.end_batch = true;
|
||||
_render_batch(index);
|
||||
|
||||
canvas_end();
|
||||
}
|
||||
|
||||
void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, uint32_t &r_index) {
|
||||
@ -289,8 +463,7 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
|
||||
|
||||
uint32_t base_flags = 0;
|
||||
|
||||
RID last_texture;
|
||||
Size2 texpixel_size;
|
||||
bool reclip = false;
|
||||
|
||||
bool skipping = false;
|
||||
|
||||
@ -326,21 +499,20 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
|
||||
current_repeat = RenderingServer::CanvasItemTextureRepeat::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED;
|
||||
}
|
||||
|
||||
if (rect->texture != last_texture || state.current_primitive_points != 0 || state.current_command != Item::Command::TYPE_RECT) {
|
||||
state.end_batch = true;
|
||||
if (rect->texture != state.current_tex || state.current_primitive_points != 0 || state.current_command != Item::Command::TYPE_RECT) {
|
||||
_render_batch(r_index);
|
||||
|
||||
state.current_primitive_points = 0;
|
||||
state.current_command = Item::Command::TYPE_RECT;
|
||||
}
|
||||
_bind_canvas_texture(rect->texture, current_filter, current_repeat, r_index, last_texture, texpixel_size);
|
||||
_bind_canvas_texture(rect->texture, current_filter, current_repeat, r_index);
|
||||
GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_QUAD);
|
||||
|
||||
Rect2 src_rect;
|
||||
Rect2 dst_rect;
|
||||
|
||||
if (rect->texture != RID()) {
|
||||
src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * texpixel_size, rect->source.size * texpixel_size) : Rect2(0, 0, 1, 1);
|
||||
src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * state.current_pixel_size, rect->source.size * state.current_pixel_size) : Rect2(0, 0, 1, 1);
|
||||
dst_rect = Rect2(rect->rect.position, rect->rect.size);
|
||||
|
||||
if (dst_rect.size.width < 0) {
|
||||
@ -408,8 +580,6 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
|
||||
//_render_batch(r_index);
|
||||
r_index++;
|
||||
if (r_index >= state.max_instances_per_batch - 1) {
|
||||
//r_index--;
|
||||
state.end_batch = true;
|
||||
_render_batch(r_index);
|
||||
}
|
||||
} break;
|
||||
@ -426,18 +596,18 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
|
||||
|
||||
//bind textures
|
||||
|
||||
_bind_canvas_texture(p_draw_list, np->texture, current_filter, current_repeat, index, last_texture, texpixel_size);
|
||||
_bind_canvas_texture(p_draw_list, np->texture, current_filter, current_repeat, index);
|
||||
|
||||
Rect2 src_rect;
|
||||
Rect2 dst_rect(np->rect.position.x, np->rect.position.y, np->rect.size.x, np->rect.size.y);
|
||||
|
||||
if (np->texture == RID()) {
|
||||
texpixel_size = Size2(1, 1);
|
||||
state.current_pixel_size = Size2(1, 1);
|
||||
src_rect = Rect2(0, 0, 1, 1);
|
||||
|
||||
} else {
|
||||
if (np->source != Rect2()) {
|
||||
src_rect = Rect2(np->source.position.x * texpixel_size.width, np->source.position.y * texpixel_size.height, np->source.size.x * texpixel_size.width, np->source.size.y * texpixel_size.height);
|
||||
src_rect = Rect2(np->source.position.x * state.current_pixel_size.width, np->source.position.y * state.current_pixel_size.height, np->source.size.x * state.current_pixel_size.width, np->source.size.y * state.current_pixel_size.height);
|
||||
state.instance_data_array[r_index].color_texture_pixel_size[0] = 1.0 / np->source.size.width;
|
||||
state.instance_data_array[r_index].color_texture_pixel_size[1] = 1.0 / np->source.size.height;
|
||||
|
||||
@ -478,8 +648,8 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
|
||||
RD::get_singleton()->draw_list_draw(p_draw_list, true);
|
||||
|
||||
// Restore if overridden.
|
||||
state.instance_data_array[r_index].color_texture_pixel_size[0] = texpixel_size.x;
|
||||
state.instance_data_array[r_index].color_texture_pixel_size[1] = texpixel_size.y;
|
||||
state.instance_data_array[r_index].color_texture_pixel_size[0] = state.current_pixel_size.x;
|
||||
state.instance_data_array[r_index].color_texture_pixel_size[1] = state.current_pixel_size.y;
|
||||
*/
|
||||
} break;
|
||||
|
||||
@ -489,14 +659,13 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
|
||||
PolygonBuffers *pb = polygon_buffers.polygons.getptr(polygon->polygon.polygon_id);
|
||||
ERR_CONTINUE(!pb);
|
||||
|
||||
if (polygon->texture != last_texture || state.current_primitive_points != 0 || state.current_command != Item::Command::TYPE_POLYGON) {
|
||||
state.end_batch = true;
|
||||
if (polygon->texture != state.current_tex || state.current_primitive_points != 0 || state.current_command != Item::Command::TYPE_POLYGON) {
|
||||
_render_batch(r_index);
|
||||
|
||||
state.current_primitive_points = 0;
|
||||
state.current_command = Item::Command::TYPE_POLYGON;
|
||||
}
|
||||
_bind_canvas_texture(polygon->texture, current_filter, current_repeat, r_index, last_texture, texpixel_size);
|
||||
_bind_canvas_texture(polygon->texture, current_filter, current_repeat, r_index);
|
||||
GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_ATTRIBUTES);
|
||||
|
||||
state.current_primitive = polygon->primitive;
|
||||
@ -549,13 +718,12 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
|
||||
case Item::Command::TYPE_PRIMITIVE: {
|
||||
const Item::CommandPrimitive *primitive = static_cast<const Item::CommandPrimitive *>(c);
|
||||
|
||||
if (last_texture != default_canvas_texture || state.current_primitive_points != primitive->point_count || state.current_command != Item::Command::TYPE_PRIMITIVE) {
|
||||
state.end_batch = true;
|
||||
if (state.current_primitive_points != primitive->point_count || state.current_command != Item::Command::TYPE_PRIMITIVE) {
|
||||
_render_batch(r_index);
|
||||
state.current_primitive_points = primitive->point_count;
|
||||
state.current_command = Item::Command::TYPE_PRIMITIVE;
|
||||
}
|
||||
_bind_canvas_texture(RID(), current_filter, current_repeat, r_index, last_texture, texpixel_size);
|
||||
_bind_canvas_texture(RID(), current_filter, current_repeat, r_index);
|
||||
GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_PRIMITIVE);
|
||||
|
||||
for (uint32_t j = 0; j < MIN(3u, primitive->point_count); j++) {
|
||||
@ -589,8 +757,6 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
|
||||
r_index++;
|
||||
}
|
||||
if (r_index >= state.max_instances_per_batch - 1) {
|
||||
//r_index--;
|
||||
state.end_batch = true;
|
||||
_render_batch(r_index);
|
||||
}
|
||||
} break;
|
||||
@ -643,14 +809,13 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
|
||||
break;
|
||||
}
|
||||
|
||||
if (texture != last_texture || state.current_primitive_points != 0 || state.current_command != Item::Command::TYPE_PRIMITIVE) {
|
||||
state.end_batch = true;
|
||||
if (texture != state.current_tex || state.current_primitive_points != 0 || state.current_command != Item::Command::TYPE_PRIMITIVE) {
|
||||
_render_batch(r_index);
|
||||
state.current_primitive_points = 0;
|
||||
state.current_command = c->type;
|
||||
}
|
||||
|
||||
_bind_canvas_texture(texture, current_filter, current_repeat, r_index, last_texture, texpixel_size);
|
||||
_bind_canvas_texture(texture, current_filter, current_repeat, r_index);
|
||||
|
||||
uint32_t surf_count = storage->mesh_get_surface_count(mesh);
|
||||
|
||||
@ -684,20 +849,19 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
|
||||
} break;
|
||||
|
||||
case Item::Command::TYPE_CLIP_IGNORE: {
|
||||
/*
|
||||
const Item::CommandClipIgnore *ci = static_cast<const Item::CommandClipIgnore *>(c);
|
||||
if (current_clip) {
|
||||
if (ci->ignore != reclip) {
|
||||
if (ci->ignore) {
|
||||
RD::get_singleton()->draw_list_disable_scissor(p_draw_list);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
reclip = true;
|
||||
} else {
|
||||
RD::get_singleton()->draw_list_enable_scissor(p_draw_list, current_clip->final_clip_rect);
|
||||
// Scissor area is already set
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
reclip = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
} break;
|
||||
case Item::Command::TYPE_ANIMATION_SLICE: {
|
||||
/*
|
||||
@ -713,10 +877,15 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
|
||||
|
||||
c = c->next;
|
||||
}
|
||||
|
||||
if (current_clip && reclip) {
|
||||
//will make it re-enable clipping if needed afterwards
|
||||
current_clip = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerCanvasGLES3::_render_batch(uint32_t &r_index) {
|
||||
if (state.end_batch && r_index > 0) {
|
||||
if (r_index > 0) {
|
||||
// If the previous operation is not done yet, allocate a new buffer
|
||||
if (state.fences[state.current_buffer] != GLsync()) {
|
||||
GLint syncStatus;
|
||||
@ -748,7 +917,6 @@ void RasterizerCanvasGLES3::_render_batch(uint32_t &r_index) {
|
||||
|
||||
state.fences[state.current_buffer] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
state.current_buffer = (state.current_buffer + 1) % state.canvas_instance_data_buffers.size();
|
||||
state.end_batch = false;
|
||||
//copy the new data into the base of the batch
|
||||
for (int i = 0; i < 4; i++) {
|
||||
state.instance_data_array[0].modulation[i] = state.instance_data_array[r_index].modulation[i];
|
||||
@ -771,27 +939,6 @@ void RasterizerCanvasGLES3::_render_batch(uint32_t &r_index) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO maybe dont use
|
||||
void RasterizerCanvasGLES3::_end_batch(const uint32_t p_index) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
state.instance_data_array[p_index].modulation[i] = 0.0;
|
||||
state.instance_data_array[p_index].ninepatch_margins[i] = 0.0;
|
||||
state.instance_data_array[p_index].src_rect[i] = 0.0;
|
||||
state.instance_data_array[p_index].dst_rect[i] = 0.0;
|
||||
}
|
||||
state.instance_data_array[p_index].flags = uint32_t(0);
|
||||
state.instance_data_array[p_index].color_texture_pixel_size[0] = 0.0;
|
||||
state.instance_data_array[p_index].color_texture_pixel_size[1] = 0.0;
|
||||
|
||||
state.instance_data_array[p_index].pad[0] = 0.0;
|
||||
state.instance_data_array[p_index].pad[1] = 0.0;
|
||||
|
||||
state.instance_data_array[p_index].lights[0] = uint32_t(0);
|
||||
state.instance_data_array[p_index].lights[1] = uint32_t(0);
|
||||
state.instance_data_array[p_index].lights[2] = uint32_t(0);
|
||||
state.instance_data_array[p_index].lights[3] = uint32_t(0);
|
||||
}
|
||||
|
||||
RID RasterizerCanvasGLES3::light_create() {
|
||||
return RID();
|
||||
}
|
||||
@ -831,49 +978,56 @@ bool RasterizerCanvasGLES3::free(RID p_rid) {
|
||||
void RasterizerCanvasGLES3::update() {
|
||||
}
|
||||
|
||||
void RasterizerCanvasGLES3::canvas_begin() {
|
||||
void RasterizerCanvasGLES3::canvas_begin(RID p_to_render_target, bool p_to_backbuffer) {
|
||||
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
|
||||
GLES3::Config *config = GLES3::Config::get_singleton();
|
||||
|
||||
state.using_transparent_rt = false;
|
||||
GLES3::RenderTarget *render_target = texture_storage->get_render_target(p_to_render_target);
|
||||
|
||||
if (texture_storage->frame.current_rt) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, texture_storage->frame.current_rt->fbo);
|
||||
state.using_transparent_rt = texture_storage->frame.current_rt->flags[GLES3::TextureStorage::RENDER_TARGET_TRANSPARENT];
|
||||
if (p_to_backbuffer) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, render_target->backbuffer_fbo);
|
||||
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 4);
|
||||
GLES3::Texture *tex = texture_storage->get_texture(texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE));
|
||||
glBindTexture(GL_TEXTURE_2D, tex->tex_id);
|
||||
} else {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, render_target->fbo);
|
||||
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 4);
|
||||
glBindTexture(GL_TEXTURE_2D, render_target->backbuffer);
|
||||
}
|
||||
|
||||
if (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);
|
||||
|
@ -171,22 +171,11 @@ public:
|
||||
|
||||
InstanceData *instance_data_array = nullptr;
|
||||
bool canvas_texscreen_used;
|
||||
//CanvasShaderGLES3 canvas_shader;
|
||||
RID canvas_shader_current_version;
|
||||
RID canvas_shader_default_version;
|
||||
//CanvasShadowShaderGLES3 canvas_shadow_shader;
|
||||
//LensDistortedShaderGLES3 lens_shader;
|
||||
|
||||
bool using_texture_rect;
|
||||
|
||||
bool using_ninepatch;
|
||||
bool using_skeleton;
|
||||
|
||||
Transform2D skeleton_transform;
|
||||
Transform2D skeleton_transform_inverse;
|
||||
Size2i skeleton_texture_size;
|
||||
|
||||
RID current_tex = RID();
|
||||
Size2 current_pixel_size = Size2();
|
||||
RID current_normal = RID();
|
||||
RID current_specular = RID();
|
||||
GLES3::Texture *current_tex_ptr;
|
||||
@ -195,14 +184,7 @@ public:
|
||||
uint32_t current_primitive_points = 0;
|
||||
Item::Command::Type current_command = Item::Command::TYPE_RECT;
|
||||
|
||||
bool end_batch = false;
|
||||
|
||||
Transform3D vp;
|
||||
Light *using_light = nullptr;
|
||||
bool using_shadow;
|
||||
bool using_transparent_rt;
|
||||
|
||||
// FROM RD Renderer
|
||||
bool transparent_render_target = false;
|
||||
|
||||
double time = 0.0;
|
||||
|
||||
@ -224,16 +206,13 @@ public:
|
||||
|
||||
RasterizerStorageGLES3 *storage = nullptr;
|
||||
|
||||
void _set_uniforms();
|
||||
|
||||
void canvas_begin();
|
||||
void canvas_end();
|
||||
void canvas_begin(RID p_to_render_target, bool p_to_backbuffer);
|
||||
|
||||
//virtual void draw_window_margins(int *black_margin, RID *black_image) override;
|
||||
void draw_lens_distortion_rect(const Rect2 &p_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample);
|
||||
|
||||
virtual void reset_canvas();
|
||||
virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache);
|
||||
void reset_canvas();
|
||||
void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache);
|
||||
|
||||
virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) override;
|
||||
|
||||
@ -252,7 +231,7 @@ public:
|
||||
bool free(RID p_rid) override;
|
||||
void update() override;
|
||||
|
||||
void _bind_canvas_texture(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, uint32_t &r_index, RID &r_last_texture, Size2 &r_texpixel_size);
|
||||
void _bind_canvas_texture(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, uint32_t &r_index);
|
||||
|
||||
struct PolygonBuffers {
|
||||
GLuint vertex_buffer;
|
||||
@ -273,7 +252,6 @@ public:
|
||||
void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer = false);
|
||||
void _render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, uint32_t &r_index);
|
||||
void _render_batch(uint32_t &p_max_index);
|
||||
void _end_batch(const uint32_t p_index);
|
||||
void _allocate_instance_data_buffer();
|
||||
|
||||
void set_time(double p_time);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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() {
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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");
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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
|
@ -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 {}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user