summaryrefslogtreecommitdiff
path: root/drivers/gles3/rasterizer_canvas_gles3.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gles3/rasterizer_canvas_gles3.cpp')
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp693
1 files changed, 439 insertions, 254 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index e14018c562..28802f571c 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -34,12 +34,12 @@
#include "core/os/os.h"
#include "rasterizer_scene_gles3.h"
-#include "rasterizer_storage_gles3.h"
#include "core/config/project_settings.h"
#include "servers/rendering/rendering_server_default.h"
#include "storage/config.h"
#include "storage/material_storage.h"
+#include "storage/mesh_storage.h"
#include "storage/texture_storage.h"
#ifndef GLES_OVER_GL
@@ -57,57 +57,57 @@
//};
void RasterizerCanvasGLES3::_update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4) {
- p_mat4[0] = p_transform.elements[0][0];
- p_mat4[1] = p_transform.elements[0][1];
+ p_mat4[0] = p_transform.columns[0][0];
+ p_mat4[1] = p_transform.columns[0][1];
p_mat4[2] = 0;
p_mat4[3] = 0;
- p_mat4[4] = p_transform.elements[1][0];
- p_mat4[5] = p_transform.elements[1][1];
+ p_mat4[4] = p_transform.columns[1][0];
+ p_mat4[5] = p_transform.columns[1][1];
p_mat4[6] = 0;
p_mat4[7] = 0;
p_mat4[8] = 0;
p_mat4[9] = 0;
p_mat4[10] = 1;
p_mat4[11] = 0;
- p_mat4[12] = p_transform.elements[2][0];
- p_mat4[13] = p_transform.elements[2][1];
+ p_mat4[12] = p_transform.columns[2][0];
+ p_mat4[13] = p_transform.columns[2][1];
p_mat4[14] = 0;
p_mat4[15] = 1;
}
void RasterizerCanvasGLES3::_update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4) {
- p_mat2x4[0] = p_transform.elements[0][0];
- p_mat2x4[1] = p_transform.elements[1][0];
+ p_mat2x4[0] = p_transform.columns[0][0];
+ p_mat2x4[1] = p_transform.columns[1][0];
p_mat2x4[2] = 0;
- p_mat2x4[3] = p_transform.elements[2][0];
+ p_mat2x4[3] = p_transform.columns[2][0];
- p_mat2x4[4] = p_transform.elements[0][1];
- p_mat2x4[5] = p_transform.elements[1][1];
+ p_mat2x4[4] = p_transform.columns[0][1];
+ p_mat2x4[5] = p_transform.columns[1][1];
p_mat2x4[6] = 0;
- p_mat2x4[7] = p_transform.elements[2][1];
+ p_mat2x4[7] = p_transform.columns[2][1];
}
void RasterizerCanvasGLES3::_update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3) {
- p_mat2x3[0] = p_transform.elements[0][0];
- p_mat2x3[1] = p_transform.elements[0][1];
- p_mat2x3[2] = p_transform.elements[1][0];
- p_mat2x3[3] = p_transform.elements[1][1];
- p_mat2x3[4] = p_transform.elements[2][0];
- p_mat2x3[5] = p_transform.elements[2][1];
+ p_mat2x3[0] = p_transform.columns[0][0];
+ p_mat2x3[1] = p_transform.columns[0][1];
+ p_mat2x3[2] = p_transform.columns[1][0];
+ p_mat2x3[3] = p_transform.columns[1][1];
+ p_mat2x3[4] = p_transform.columns[2][0];
+ p_mat2x3[5] = p_transform.columns[2][1];
}
void RasterizerCanvasGLES3::_update_transform_to_mat4(const Transform3D &p_transform, float *p_mat4) {
- p_mat4[0] = p_transform.basis.elements[0][0];
- p_mat4[1] = p_transform.basis.elements[1][0];
- p_mat4[2] = p_transform.basis.elements[2][0];
+ p_mat4[0] = p_transform.basis.rows[0][0];
+ p_mat4[1] = p_transform.basis.rows[1][0];
+ p_mat4[2] = p_transform.basis.rows[2][0];
p_mat4[3] = 0;
- p_mat4[4] = p_transform.basis.elements[0][1];
- p_mat4[5] = p_transform.basis.elements[1][1];
- p_mat4[6] = p_transform.basis.elements[2][1];
+ p_mat4[4] = p_transform.basis.rows[0][1];
+ p_mat4[5] = p_transform.basis.rows[1][1];
+ p_mat4[6] = p_transform.basis.rows[2][1];
p_mat4[7] = 0;
- p_mat4[8] = p_transform.basis.elements[0][2];
- p_mat4[9] = p_transform.basis.elements[1][2];
- p_mat4[10] = p_transform.basis.elements[2][2];
+ p_mat4[8] = p_transform.basis.rows[0][2];
+ p_mat4[9] = p_transform.basis.rows[1][2];
+ p_mat4[10] = p_transform.basis.rows[2][2];
p_mat4[11] = 0;
p_mat4[12] = p_transform.origin.x;
p_mat4[13] = p_transform.origin.y;
@@ -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
@@ -136,15 +135,15 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
Size2i ssize = texture_storage->render_target_get_size(p_to_render_target);
Transform3D screen_transform;
- screen_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
+ screen_transform.translate_local(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
screen_transform.scale(Vector3(2.0f / ssize.width, 2.0f / ssize.height, 1.0f));
_update_transform_to_mat4(screen_transform, state_buffer.screen_transform);
_update_transform_2d_to_mat4(p_canvas_transform, state_buffer.canvas_transform);
Transform2D normal_transform = p_canvas_transform;
- normal_transform.elements[0].normalize();
- normal_transform.elements[1].normalize();
- normal_transform.elements[2] = Vector2();
+ normal_transform.columns[0].normalize();
+ normal_transform.columns[1].normalize();
+ normal_transform.columns[2] = Vector2();
_update_transform_2d_to_mat4(normal_transform, state_buffer.canvas_normal_transform);
state_buffer.canvas_modulate[0] = p_modulate.r;
@@ -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,14 +179,13 @@ 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_BUFFER_OBJECT, state.canvas_state_buffer);
+ glBindBufferBase(GL_UNIFORM_BUFFER, BASE_UNIFORM_LOCATION, state.canvas_state_buffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(StateBuffer), &state_buffer, GL_STREAM_DRAW);
- GLuint global_buffer = material_storage->global_variables_get_uniform_buffer();
+ GLuint global_buffer = material_storage->global_shader_uniforms_get_uniform_buffer();
- glBindBufferBase(GL_UNIFORM_BUFFER, GLOBAL_UNIFORM_BUFFER_OBJECT, global_buffer);
+ glBindBufferBase(GL_UNIFORM_BUFFER, GLOBAL_UNIFORM_LOCATION, global_buffer);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
@@ -193,17 +194,102 @@ 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;
+ bool backbuffer_gen_mipmaps = 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();
+ backbuffer_gen_mipmaps = md->shader_data->uses_screen_texture_mipmaps;
+ }
+ }
+
+ 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, backbuffer_gen_mipmaps);
+
+ 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 +301,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 +354,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,25 +364,92 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
// Bind uniform buffer and textures
material_data->bind_uniforms();
state.current_shader_version = material_data->shader_data->version;
+ shader_data_cache = material_data->shader_data;
} else {
state.current_shader_version = state.canvas_shader_default_version;
+ shader_data_cache = nullptr;
}
} else {
state.current_shader_version = state.canvas_shader_default_version;
+ shader_data_cache = nullptr;
}
prev_material = material;
}
+ GLES3::CanvasShaderData::BlendMode blend_mode = shader_data_cache ? shader_data_cache->blend_mode : GLES3::CanvasShaderData::BLEND_MODE_MIX;
+
+ if (last_blend_mode != blend_mode) {
+ if (last_blend_mode == GLES3::CanvasShaderData::BLEND_MODE_DISABLED) {
+ // re-enable it
+ glEnable(GL_BLEND);
+ } else if (blend_mode == GLES3::CanvasShaderData::BLEND_MODE_DISABLED) {
+ // disable it
+ glDisable(GL_BLEND);
+ }
+
+ switch (blend_mode) {
+ case GLES3::CanvasShaderData::BLEND_MODE_DISABLED: {
+ // Nothing to do here.
+
+ } break;
+ case GLES3::CanvasShaderData::BLEND_MODE_MIX: {
+ glBlendEquation(GL_FUNC_ADD);
+ if (state.transparent_render_target) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ } else {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
+ }
+
+ } break;
+ case GLES3::CanvasShaderData::BLEND_MODE_ADD: {
+ glBlendEquation(GL_FUNC_ADD);
+ if (state.transparent_render_target) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_SRC_ALPHA, GL_ONE);
+ } else {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
+ }
+
+ } break;
+ case GLES3::CanvasShaderData::BLEND_MODE_SUB: {
+ glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
+ if (state.transparent_render_target) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_SRC_ALPHA, GL_ONE);
+ } else {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
+ }
+ } break;
+ case GLES3::CanvasShaderData::BLEND_MODE_MUL: {
+ glBlendEquation(GL_FUNC_ADD);
+ if (state.transparent_render_target) {
+ glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_DST_ALPHA, GL_ZERO);
+ } else {
+ glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ZERO, GL_ONE);
+ }
+
+ } break;
+ case GLES3::CanvasShaderData::BLEND_MODE_PMALPHA: {
+ glBlendEquation(GL_FUNC_ADD);
+ if (state.transparent_render_target) {
+ glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ } else {
+ glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
+ }
+
+ } break;
+ }
+ last_blend_mode = blend_mode;
+ }
+
_render_item(p_to_render_target, ci, canvas_transform_inverse, current_clip, p_lights, index);
}
// Render last command
- state.end_batch = true;
_render_batch(index);
-
- canvas_end();
}
void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, uint32_t &r_index) {
+ // Used by Polygon and Mesh.
+ static const GLenum prim[5] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP };
+
RS::CanvasItemTextureFilter current_filter = state.default_filter;
RS::CanvasItemTextureRepeat current_repeat = state.default_repeat;
@@ -289,8 +468,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;
@@ -301,7 +479,10 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
continue;
}
- _update_transform_2d_to_mat2x3(base_transform * draw_transform, state.instance_data_array[r_index].world);
+ if (c->type != Item::Command::TYPE_MESH) {
+ // For Meshes, this gets updated below.
+ _update_transform_2d_to_mat2x3(base_transform * draw_transform, state.instance_data_array[r_index].world);
+ }
for (int i = 0; i < 4; i++) {
state.instance_data_array[r_index].modulation[i] = 0.0;
@@ -326,21 +507,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) {
@@ -405,39 +585,37 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
state.instance_data_array[r_index].dst_rect[1] = dst_rect.position.y;
state.instance_data_array[r_index].dst_rect[2] = dst_rect.size.width;
state.instance_data_array[r_index].dst_rect[3] = dst_rect.size.height;
- //_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;
case Item::Command::TYPE_NINEPATCH: {
- /*
const Item::CommandNinePatch *np = static_cast<const Item::CommandNinePatch *>(c);
- //bind pipeline
- {
- RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_NINEPATCH].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format);
- RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline);
+ if (np->texture != state.current_tex || state.current_primitive_points != 0 || state.current_command != Item::Command::TYPE_NINEPATCH) {
+ _render_batch(r_index);
+
+ state.current_primitive_points = 0;
+ state.current_command = Item::Command::TYPE_NINEPATCH;
}
//bind textures
-
- _bind_canvas_texture(p_draw_list, np->texture, current_filter, current_repeat, index, last_texture, texpixel_size);
+ _bind_canvas_texture(np->texture, current_filter, current_repeat, r_index);
+ GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_NINEPATCH);
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;
@@ -473,14 +651,14 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
state.instance_data_array[r_index].ninepatch_margins[2] = np->margin[SIDE_RIGHT];
state.instance_data_array[r_index].ninepatch_margins[3] = np->margin[SIDE_BOTTOM];
- RD::get_singleton()->draw_list_set_state.instance_data_array[r_index](p_draw_list, &state.instance_data_array[r_index], sizeof(PushConstant));
- RD::get_singleton()->draw_list_bind_index_array(p_draw_list, shader.quad_index_array);
- RD::get_singleton()->draw_list_draw(p_draw_list, true);
+ r_index++;
+ if (r_index >= state.max_instances_per_batch - 1) {
+ _render_batch(r_index);
+ }
// 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;
case Item::Command::TYPE_POLYGON: {
@@ -489,14 +667,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;
@@ -511,29 +688,12 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
state.instance_data_array[r_index].ninepatch_margins[j] = 0;
}
- // If the previous operation is not done yet, allocate a new buffer
- if (state.fences[state.current_buffer] != GLsync()) {
- GLint syncStatus;
- glGetSynciv(state.fences[state.current_buffer], GL_SYNC_STATUS, sizeof(GLint), nullptr, &syncStatus);
- if (syncStatus == GL_UNSIGNALED) {
- _allocate_instance_data_buffer();
- } else {
- glDeleteSync(state.fences[state.current_buffer]);
- }
- }
-
- glBindBufferBase(GL_UNIFORM_BUFFER, INSTANCE_UNIFORM_BUFFER_OBJECT, state.canvas_instance_data_buffers[state.current_buffer]);
-#ifdef JAVASCRIPT_ENABLED
- //WebGL 2.0 does not support mapping buffers, so use slow glBufferData instead
- glBufferData(GL_UNIFORM_BUFFER, sizeof(InstanceData), &state.instance_data_array[0], GL_DYNAMIC_DRAW);
-#else
- void *ubo = glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(InstanceData), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
- memcpy(ubo, &state.instance_data_array[0], sizeof(InstanceData));
- glUnmapBuffer(GL_UNIFORM_BUFFER);
-#endif
+ _bind_instance_data_buffer(1);
glBindVertexArray(pb->vertex_array);
- static const GLenum prim[5] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP };
+ if (pb->color_disabled) {
+ glVertexAttrib4f(RS::ARRAY_COLOR, pb->color.r, pb->color.g, pb->color.b, pb->color.a);
+ }
if (pb->index_buffer != 0) {
glDrawElements(prim[polygon->primitive], pb->count, GL_UNSIGNED_INT, nullptr);
@@ -544,18 +704,22 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
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();
+
+ if (pb->color_disabled) {
+ // Reset so this doesn't pollute other draw calls.
+ glVertexAttrib4f(RS::ARRAY_COLOR, 1.0, 1.0, 1.0, 1.0);
+ }
} break;
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 +753,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;
@@ -598,12 +760,17 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
case Item::Command::TYPE_MESH:
case Item::Command::TYPE_MULTIMESH:
case Item::Command::TYPE_PARTICLES: {
- /*
+ GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton();
RID mesh;
RID mesh_instance;
RID texture;
Color modulate(1, 1, 1, 1);
- int instance_count = 1;
+ uint32_t instance_count = 1;
+ GLuint multimesh_buffer = 0;
+ uint32_t multimesh_stride = 0;
+ uint32_t multimesh_color_offset = 0;
+ bool multimesh_uses_color = false;
+ bool multimesh_uses_custom_data = false;
if (c->type == Item::Command::TYPE_MESH) {
const Item::CommandMesh *m = static_cast<const Item::CommandMesh *>(c);
@@ -615,26 +782,24 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
} else if (c->type == Item::Command::TYPE_MULTIMESH) {
const Item::CommandMultiMesh *mm = static_cast<const Item::CommandMultiMesh *>(c);
RID multimesh = mm->multimesh;
- mesh = storage->multimesh_get_mesh(multimesh);
+ mesh = mesh_storage->multimesh_get_mesh(multimesh);
texture = mm->texture;
- if (storage->multimesh_get_transform_format(multimesh) != RS::MULTIMESH_TRANSFORM_2D) {
+ if (mesh_storage->multimesh_get_transform_format(multimesh) != RS::MULTIMESH_TRANSFORM_2D) {
break;
}
- instance_count = storage->multimesh_get_instances_to_draw(multimesh);
+ instance_count = mesh_storage->multimesh_get_instances_to_draw(multimesh);
if (instance_count == 0) {
break;
}
- state.instance_data_array[r_index].flags |= 1; //multimesh, trails disabled
- if (storage->multimesh_uses_colors(multimesh)) {
- state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_COLORS;
- }
- if (storage->multimesh_uses_custom_data(multimesh)) {
- state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA;
- }
+ multimesh_buffer = mesh_storage->multimesh_get_gl_buffer(multimesh);
+ multimesh_stride = mesh_storage->multimesh_get_stride(multimesh);
+ multimesh_color_offset = mesh_storage->multimesh_get_color_offset(multimesh);
+ multimesh_uses_color = mesh_storage->multimesh_uses_colors(multimesh);
+ multimesh_uses_custom_data = mesh_storage->multimesh_uses_custom_data(multimesh);
}
// TODO: implement particles here
@@ -643,16 +808,20 @@ 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);
+ if (instance_count == 1) {
+ GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_ATTRIBUTES);
+ } else {
+ GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_INSTANCED);
+ }
- uint32_t surf_count = storage->mesh_get_surface_count(mesh);
+ uint32_t surf_count = mesh_storage->mesh_get_surface_count(mesh);
state.instance_data_array[r_index].modulation[0] = base_color.r * modulate.r;
state.instance_data_array[r_index].modulation[1] = base_color.g * modulate.g;
@@ -664,19 +833,74 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
state.instance_data_array[r_index].dst_rect[j] = 0;
state.instance_data_array[r_index].ninepatch_margins[j] = 0;
}
-
+ _bind_instance_data_buffer(1);
for (uint32_t j = 0; j < surf_count; j++) {
- RS::SurfaceData *surface = storage->mesh_get_surface(mesh, j);
+ void *surface = mesh_storage->mesh_get_surface(mesh, j);
- RS::PrimitiveType primitive = storage->mesh_surface_get_primitive(surface);
+ RS::PrimitiveType primitive = mesh_storage->mesh_surface_get_primitive(surface);
ERR_CONTINUE(primitive < 0 || primitive >= RS::PRIMITIVE_MAX);
- glBindVertexArray(surface->vertex_array);
- static const GLenum prim[5] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP };
+ GLuint vertex_array_gl = 0;
+ GLuint index_array_gl = 0;
+
+ uint32_t input_mask = 0; // 2D meshes always use the same vertex format
+ if (mesh_instance.is_valid()) {
+ mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(mesh_instance, j, input_mask, vertex_array_gl);
+ } else {
+ mesh_storage->mesh_surface_get_vertex_arrays_and_format(surface, input_mask, vertex_array_gl);
+ }
+
+ index_array_gl = mesh_storage->mesh_surface_get_index_buffer(surface, 0);
+ bool use_index_buffer = false;
+ glBindVertexArray(vertex_array_gl);
+ if (index_array_gl != 0) {
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_array_gl);
+ use_index_buffer = true;
+ }
+
+ if (instance_count > 1) {
+ // Bind instance buffers.
+ glBindBuffer(GL_ARRAY_BUFFER, multimesh_buffer);
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(0));
+ glVertexAttribDivisor(1, 1);
+ glEnableVertexAttribArray(2);
+ glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 4));
+ glVertexAttribDivisor(2, 1);
+
+ if (multimesh_uses_color || multimesh_uses_custom_data) {
+ glEnableVertexAttribArray(5);
+ glVertexAttribIPointer(5, 4, GL_UNSIGNED_INT, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(multimesh_color_offset * sizeof(float)));
+ glVertexAttribDivisor(5, 1);
+ }
+ }
- // Draw directly, no need to batch
+ GLenum primitive_gl = prim[int(primitive)];
+ if (instance_count == 1) {
+ if (use_index_buffer) {
+ glDrawElements(primitive_gl, mesh_storage->mesh_surface_get_vertices_drawn_count(surface), mesh_storage->mesh_surface_get_index_type(surface), 0);
+ } else {
+ glDrawArrays(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(surface));
+ }
+ } else {
+ if (use_index_buffer) {
+ glDrawElementsInstanced(primitive_gl, mesh_storage->mesh_surface_get_vertices_drawn_count(surface), mesh_storage->mesh_surface_get_index_type(surface), 0, instance_count);
+ } else {
+ glDrawArraysInstanced(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(surface), instance_count);
+ }
+ }
+
+ 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();
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ if (instance_count > 1) {
+ glDisableVertexAttribArray(5);
+ glDisableVertexAttribArray(6);
+ glDisableVertexAttribArray(7);
+ glDisableVertexAttribArray(8);
+ }
}
- */
} break;
case Item::Command::TYPE_TRANSFORM: {
const Item::CommandTransform *transform = static_cast<const Item::CommandTransform *>(c);
@@ -684,20 +908,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,30 +936,16 @@ 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 the previous operation is not done yet, allocate a new buffer
- if (state.fences[state.current_buffer] != GLsync()) {
- GLint syncStatus;
- glGetSynciv(state.fences[state.current_buffer], GL_SYNC_STATUS, sizeof(GLint), nullptr, &syncStatus);
- if (syncStatus == GL_UNSIGNALED) {
- _allocate_instance_data_buffer();
- } else {
- glDeleteSync(state.fences[state.current_buffer]);
- }
- }
-
- glBindBufferBase(GL_UNIFORM_BUFFER, INSTANCE_UNIFORM_BUFFER_OBJECT, state.canvas_instance_data_buffers[state.current_buffer]);
-#ifdef JAVASCRIPT_ENABLED
- //WebGL 2.0 does not support mapping buffers, so use slow glBufferData instead
- glBufferData(GL_UNIFORM_BUFFER, sizeof(InstanceData) * r_index, state.instance_data_array, GL_DYNAMIC_DRAW);
-#else
- void *ubo = glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(InstanceData) * r_index, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
- memcpy(ubo, state.instance_data_array, sizeof(InstanceData) * r_index);
- glUnmapBuffer(GL_UNIFORM_BUFFER);
-#endif
+ if (r_index > 0) {
+ _bind_instance_data_buffer(r_index);
glBindVertexArray(data.canvas_quad_array);
if (state.current_primitive_points == 0) {
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, r_index);
@@ -748,7 +957,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,25 +979,30 @@ 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;
+void RasterizerCanvasGLES3::_bind_instance_data_buffer(uint32_t p_max_index) {
+ if (p_max_index == 0) {
+ return;
+ }
+ // If the previous operation is not done yet, allocate a new buffer
+ if (state.fences[state.current_buffer] != GLsync()) {
+ GLint syncStatus;
+ glGetSynciv(state.fences[state.current_buffer], GL_SYNC_STATUS, sizeof(GLint), nullptr, &syncStatus);
+ if (syncStatus == GL_UNSIGNALED) {
+ _allocate_instance_data_buffer();
+ } else {
+ glDeleteSync(state.fences[state.current_buffer]);
+ }
}
- 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);
+ glBindBufferBase(GL_UNIFORM_BUFFER, INSTANCE_UNIFORM_LOCATION, state.canvas_instance_data_buffers[state.current_buffer]);
+#ifdef JAVASCRIPT_ENABLED
+ //WebGL 2.0 does not support mapping buffers, so use slow glBufferData instead
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(InstanceData) * p_max_index, state.instance_data_array, GL_DYNAMIC_DRAW);
+#else
+ void *ubo = glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(InstanceData) * p_max_index, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
+ memcpy(ubo, state.instance_data_array, sizeof(InstanceData) * p_max_index);
+ glUnmapBuffer(GL_UNIFORM_BUFFER);
+#endif
}
RID RasterizerCanvasGLES3::light_create() {
@@ -831,49 +1044,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 +1108,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 +1126,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 +1154,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 +1167,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 +1196,19 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
state.instance_data_array[r_index].specular_shininess |= uint32_t(CLAMP(ct->specular_color.g * 255.0, 0, 255)) << 8;
state.instance_data_array[r_index].specular_shininess |= uint32_t(CLAMP(ct->specular_color.r * 255.0, 0, 255));
- r_texpixel_size.x = 1.0 / float(ct->size_cache.x);
- r_texpixel_size.y = 1.0 / float(ct->size_cache.y);
-
- state.instance_data_array[r_index].color_texture_pixel_size[0] = r_texpixel_size.x;
- state.instance_data_array[r_index].color_texture_pixel_size[1] = r_texpixel_size.y;
+ state.current_pixel_size.x = 1.0 / float(ct->size_cache.x);
+ state.current_pixel_size.y = 1.0 / float(ct->size_cache.y);
- r_last_texture = p_texture;
-}
-
-void RasterizerCanvasGLES3::_set_uniforms() {
+ state.instance_data_array[r_index].color_texture_pixel_size[0] = state.current_pixel_size.x;
+ state.instance_data_array[r_index].color_texture_pixel_size[1] = state.current_pixel_size.y;
}
void RasterizerCanvasGLES3::reset_canvas() {
- GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
-
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
- glDisable(GL_DITHER);
glEnable(GL_BLEND);
-
- // Default to Mix.
- glBlendEquation(GL_FUNC_ADD);
- if (texture_storage->frame.current_rt && texture_storage->frame.current_rt->flags[GLES3::TextureStorage::RENDER_TARGET_TRANSPARENT]) {
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- } else {
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
- }
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
@@ -1013,7 +1217,7 @@ void RasterizerCanvasGLES3::reset_canvas() {
void RasterizerCanvasGLES3::canvas_debug_viewport_shadows(Light *p_lights_with_shadow) {
}
-void RasterizerCanvasGLES3::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 RasterizerCanvasGLES3::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, Projection *p_xform_cache) {
}
void RasterizerCanvasGLES3::draw_lens_distortion_rect(const Rect2 &p_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample) {
@@ -1066,11 +1270,7 @@ RendererCanvasRender::PolygonID RasterizerCanvasGLES3::request_polygon(const Vec
}
// Next add colors
- if (p_colors.size() == 1) {
- glDisableVertexAttribArray(RS::ARRAY_COLOR);
- Color m = p_colors[0];
- glVertexAttrib4f(RS::ARRAY_COLOR, m.r, m.g, m.b, m.a);
- } else if ((uint32_t)p_colors.size() == vertex_count) {
+ if ((uint32_t)p_colors.size() == vertex_count) {
glEnableVertexAttribArray(RS::ARRAY_COLOR);
glVertexAttribPointer(RS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(base_offset * sizeof(float)));
@@ -1085,7 +1285,8 @@ RendererCanvasRender::PolygonID RasterizerCanvasGLES3::request_polygon(const Vec
base_offset += 4;
} else {
glDisableVertexAttribArray(RS::ARRAY_COLOR);
- glVertexAttrib4f(RS::ARRAY_COLOR, 1.0, 1.0, 1.0, 1.0);
+ pb.color_disabled = true;
+ pb.color = p_colors.size() == 1 ? p_colors[0] : Color(1.0, 1.0, 1.0, 1.0);
}
if ((uint32_t)p_uvs.size() == vertex_count) {
@@ -1215,11 +1416,10 @@ RasterizerCanvasGLES3 *RasterizerCanvasGLES3::get_singleton() {
return singleton;
}
-RasterizerCanvasGLES3::RasterizerCanvasGLES3(RasterizerStorageGLES3 *p_storage) {
+RasterizerCanvasGLES3::RasterizerCanvasGLES3() {
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 +1542,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;
@@ -1371,7 +1570,7 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3(RasterizerStorageGLES3 *p_storage)
glBindBuffer(GL_UNIFORM_BUFFER, 0);
String global_defines;
- global_defines += "#define MAX_GLOBAL_VARIABLES 256\n"; // TODO: this is arbitrary for now
+ global_defines += "#define MAX_GLOBAL_SHADER_UNIFORMS 256\n"; // TODO: this is arbitrary for now
global_defines += "#define MAX_LIGHTS " + itos(state.max_instances_per_batch) + "\n";
global_defines += "#define MAX_DRAW_DATA_INSTANCES " + itos(state.max_instances_per_batch) + "\n";
@@ -1379,14 +1578,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 +1603,18 @@ 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();
+ memdelete_arr(state.instance_data_array);
+
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);