From e38311b226437e928fdc1f35d4e22b9526b6b14d Mon Sep 17 00:00:00 2001 From: korenkonder Date: Tue, 22 Apr 2025 21:52:02 +0300 Subject: [PATCH] Moved sprite vertex buffer preparation before draw --- src/CRE/render_context.cpp | 2 + src/CRE/render_context.hpp | 1 + src/CRE/render_manager.cpp | 5 +- src/CRE/sprite.cpp | 1171 +++++++++++++++++++----------------- src/CRE/sprite.hpp | 5 +- 5 files changed, 641 insertions(+), 543 deletions(-) diff --git a/src/CRE/render_context.cpp b/src/CRE/render_context.cpp index bdcf7973..26a610cf 100644 --- a/src/CRE/render_context.cpp +++ b/src/CRE/render_context.cpp @@ -891,6 +891,7 @@ void render_context::disp() { void render_context::free() { shadow_buffer.Free(); + screen_overlay_buffer.Free(); screen_buffer.Free(); render_buffer.Free(); reflect_buffer.Free(); @@ -937,6 +938,7 @@ void render_context::init() { init_copy_buffer(shadow_buffer, this->shadow_buffer); screen_buffer.Init(sprite_width, sprite_height, 0, GL_RGBA8, 0); + screen_overlay_buffer.Init(sprite_width, sprite_height, 0, GL_RGBA8, 0); } void render_context::resize(int32_t render_width, int32_t render_height, diff --git a/src/CRE/render_context.hpp b/src/CRE/render_context.hpp index 74d3ce14..67ed19e0 100644 --- a/src/CRE/render_context.hpp +++ b/src/CRE/render_context.hpp @@ -487,6 +487,7 @@ struct render_context { RenderTexture reflect_buffer; RenderTexture render_buffer; RenderTexture screen_buffer; + RenderTexture screen_overlay_buffer; RenderTexture shadow_buffer; GL::UniformBuffer camera_blur_ubo; diff --git a/src/CRE/render_manager.cpp b/src/CRE/render_manager.cpp index 72090516..861c35ec 100644 --- a/src/CRE/render_manager.cpp +++ b/src/CRE/render_manager.cpp @@ -284,6 +284,7 @@ namespace rndr { void RenderManager::render_all() { light_param_data_storage_data_set_ibl(); + sprite_manager_pre_draw(); static const vec4 color_clear = 0.0f; @@ -314,6 +315,8 @@ namespace rndr { gl_state_end_event(); rctx_ptr->disp_manager->check_vertex_arrays(); + sprite_manager_post_draw(); + gl_state_bind_vertex_array(0); gl_state_disable_primitive_restart(); gl_state_bind_uniform_buffer(0); @@ -1199,7 +1202,7 @@ namespace rndr { gl_state_enable_blend(); gl_state_disable_cull_face(); sprite_manager_draw(0, true, - rend->temp_buffer.color_texture, + rctx->screen_overlay_buffer.color_texture, rctx->camera->view_projection_aet_2d); gl_state_enable_cull_face(); gl_state_disable_blend(); diff --git a/src/CRE/sprite.cpp b/src/CRE/sprite.cpp index a743836d..6b7eaeba 100644 --- a/src/CRE/sprite.cpp +++ b/src/CRE/sprite.cpp @@ -57,28 +57,19 @@ struct sprite_draw_vertex { color4u8 color; }; +struct sprite_draw_param_attrib_member { + uint32_t primitive : 4; + uint32_t enable_blend : 1; + uint32_t blend : 3; + uint32_t sampler : 2; +}; + +union sprite_draw_param_attrib { + sprite_draw_param_attrib_member m; + uint32_t w; +}; + struct sprite_draw_param { - bool blend; - GLenum blend_src_rgb; - GLenum blend_src_alpha; - GLenum blend_dst_rgb; - GLenum blend_dst_alpha; - - bool copy_texture; - GLint copy_texture_x; - GLint copy_texture_y; - GLint copy_texture_width; - GLint copy_texture_height; - - int32_t shader; - int32_t tex_0_type; - int32_t tex_1_type; - int32_t combiner; - - GLuint texture[2]; - GLuint sampler; - - GLenum mode; union { GLint first; struct { @@ -88,9 +79,21 @@ struct sprite_draw_param { }; GLsizei count; GLintptr offset; + const texture* textures[2]; + int32_t shader; + sprite_draw_param_attrib attrib; + vec3 vtx[4]; }; namespace spr { + struct SprArgsInner { + int32_t num_texture; + int32_t blend; + const texture* textures[4]; + int32_t shader; + spr::SprKind kind; + }; + struct TexCoord { struct UV { float_t u; @@ -155,7 +158,7 @@ namespace spr { uint32_t AddSetModern(); void AddSprSets(const sprite_database* spr_db); void Clear(); - void Draw(int32_t index, bool font, texture* tex, const mat4& vp); + void Draw(int32_t index, bool font, texture* overlay_tex, const mat4& vp); SprSet* GetSet(uint32_t index); bool GetSetReady(uint32_t index); uint32_t GetSetSpriteNum(uint32_t index); @@ -172,6 +175,8 @@ namespace spr { void ResetIndex(); void ResetReqList(); void ResetResData(); + void PostDraw(); + void PreDraw(); void UnloadSet(uint32_t index); void UnloadSetModern(uint32_t index, sprite_database* spr_db); }; @@ -179,11 +184,14 @@ namespace spr { static void calc_sprite_vertex(spr::SprArgs* args, vec3* vtx, mat4* mat, bool font); static int32_t calc_sprite_texture_param(SprArgs* args, spr::TexParam* param, vec3* vtx, bool font); - static void draw_sprite(render_context* rctx, SprArgs& args, bool font, - const mat4& mat, int32_t x_min, int32_t y_min, int32_t x_max, int32_t y_max, - std::vector& draw_param_buffer, + static void add_draw_sprite(spr::SprArgs** args_array, int32_t count, bool font, + spr::SprArgsInner& args_inner, std::vector& draw_param_buffer, std::vector& vertex_buffer, std::vector& index_buffer); + static void draw_sprite(spr::SpriteManager* sprite_manager, render_context* rctx, const SprArgs& args, + const mat4& mat, int32_t x_min, int32_t y_min, int32_t x_max, int32_t y_max, texture* overlay_tex); static void draw_sprite_begin(render_context* rctx); + static void draw_sprite_copy_overlay_texture(render_context* rctx, const SprArgs& args, const mat4& mat, + const vec3* vtx, int32_t overlay_x_min, int32_t overlay_y_min, int32_t overlay_x_max, int32_t overlay_y_max); static void draw_sprite_end(); static void draw_sprite_scale(spr::SprArgs* args); } @@ -213,9 +221,9 @@ static const GLenum spr_blend_param[6][4] = { }; namespace spr { - SprArgs::SprArgs() : kind(), attr(), blend(), index(), layer(), - prio(), resolution_mode_screen(), resolution_mode_sprite(), texture(), - shader(), vertex_array(), num_vertex(), flags(), field_CC(), next() { + SprArgs::SprArgs() : kind(), attr(), blend(), index(), layer(), prio(), + resolution_mode_screen(), resolution_mode_sprite(), texture(), shader(), + sprite_draw_param_index(), vertex_array(), num_vertex(), flags(), field_CC(), next() { Reset(); } @@ -238,6 +246,7 @@ namespace spr { mat = mat4_identity; texture = 0; shader = SHADER_FT_FFP; + sprite_draw_param_index = -1; #if BREAK_SPRITE_VERTEX_LIMIT vertex_array = -1; #else @@ -467,8 +476,8 @@ void sprite_manager_clear() { sprite_manager->Clear(); } -void sprite_manager_draw(int32_t index, bool font, texture* tex, const mat4& vp) { - sprite_manager->Draw(index, font, tex, vp); +void sprite_manager_draw(int32_t index, bool font, texture* overlay_tex, const mat4& vp) { + sprite_manager->Draw(index, font, overlay_tex, vp); } int32_t sprite_manager_get_index() { @@ -522,6 +531,14 @@ bool sprite_manager_load_file_modern(uint32_t set_hash, sprite_database* spr_db) return sprite_manager->LoadFileModern(spr_db->get_spr_set_by_id(set_hash)->index, spr_db); } +void sprite_manager_post_draw() { + sprite_manager->PostDraw(); +} + +void sprite_manager_pre_draw() { + sprite_manager->PreDraw(); +} + void sprite_manager_read_file(uint32_t set_id, std::string& mdata_dir, void* data, const sprite_database* spr_db) { const spr_db_spr_set* spr_set = spr_db->get_spr_set_by_id(set_id); @@ -590,14 +607,14 @@ void sprite_manager_free() { namespace spr { SpriteManager::RenderData::RenderData() : vao() { glGenVertexArrays(1, &vao); - gl_state_bind_vertex_array(vao, true); + glBindVertexArray(vao); vbo_vertex_count = 4096; static const GLsizei buffer_size = sizeof(sprite_draw_vertex); vbo.Create(buffer_size * vbo_vertex_count); - vbo.Bind(); + glBindBuffer(GL_ARRAY_BUFFER, vbo); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, buffer_size, @@ -612,11 +629,11 @@ namespace spr { ebo_index_count = 4096; ebo.Create(sizeof(uint32_t) * ebo_index_count); - ebo.Bind(); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); - gl_state_bind_array_buffer(0); - gl_state_bind_vertex_array(0); - gl_state_bind_element_array_buffer(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } SpriteManager::RenderData::~RenderData() { @@ -644,10 +661,10 @@ namespace spr { vbo.Destroy(); - gl_state_bind_vertex_array(vao, true); + glBindVertexArray(vao); vbo.Create(buffer_size * vbo_vertex_count); - vbo.Bind(); + glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferSubData(GL_ARRAY_BUFFER, 0, (GLsizeiptr)(buffer_size * vertex_buffer.size()), vertex_buffer.data()); @@ -662,8 +679,8 @@ namespace spr { glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, buffer_size, (void*)offsetof(sprite_draw_vertex, uv)); - gl_state_bind_array_buffer(0); - gl_state_bind_vertex_array(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); } else vbo.WriteMemory(0, buffer_size * vertex_buffer.size(), vertex_buffer.data()); @@ -674,16 +691,16 @@ namespace spr { ebo.Destroy(); - gl_state_bind_vertex_array(vao, true); + glBindVertexArray(vao); ebo.Create(sizeof(uint32_t) * ebo_index_count); - ebo.Bind(); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, (GLsizeiptr)(sizeof(uint32_t) * index_buffer.size()), index_buffer.data()); - gl_state_bind_vertex_array(0); - gl_state_bind_element_array_buffer(0); + glBindVertexArray(0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } else ebo.WriteMemory(0, sizeof(uint32_t) * index_buffer.size(), index_buffer.data()); @@ -760,7 +777,7 @@ namespace spr { render_data.Clear(); } - void SpriteManager::Draw(int32_t index, bool font, texture* tex, const mat4& vp) { + void SpriteManager::Draw(int32_t index, bool font, texture* overlay_tex, const mat4& vp) { render_context* rctx = rctx_ptr; draw_sprite_begin(rctx); @@ -772,6 +789,7 @@ namespace spr { for (int32_t i = 0; i < 2; i++) { auto reqlist = this->reqlist[index][i]; + int32_t x_min; int32_t y_min; int32_t x_max; @@ -836,74 +854,18 @@ namespace spr { sprite_scene_shader_data shader_data = {}; shader_data.g_framebuffer_size = { - 1.0f / (float_t)tex->width, - 1.0f / (float_t)tex->height, 0.0f, 0.0f + 1.0f / (float_t)overlay_tex->width, + 1.0f / (float_t)overlay_tex->height, 0.0f, 0.0f }; mat4_transpose(&view_projection, &shader_data.g_transform); rctx->sprite_scene_ubo.WriteMemory(shader_data); - - render_data.Clear(); - - for (uint32_t j = SPR_PRIO_MAX; j; j--, reqlist++) - for (auto& k : *reqlist) - draw_sprite(rctx, k, font, mat, x_min, y_min, x_max, y_max, - render_data.draw_param_buffer, - render_data.vertex_buffer, render_data.index_buffer); - - render_data.Update(); - rctx->sprite_scene_ubo.Bind(0); - gl_state_active_bind_texture_2d(7, tex->glid); - gl_state_bind_vertex_array(render_data.vao); - for (sprite_draw_param& j : render_data.draw_param_buffer) { - if (j.blend) { - gl_state_enable_blend(); - gl_state_set_blend_func_separate( - j.blend_src_rgb, j.blend_dst_rgb, - j.blend_src_alpha, j.blend_dst_alpha); - - if (j.copy_texture) { - gl_state_active_texture(7); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, j.copy_texture_x, j.copy_texture_y, - j.copy_texture_x, j.copy_texture_y, j.copy_texture_width, j.copy_texture_height); - } - } - else - gl_state_disable_blend(); - - if (j.shader == SHADER_FT_SPRITE) { - uniform_value[U_TEX_0_TYPE] = j.tex_0_type; - uniform_value[U_TEX_1_TYPE] = j.tex_1_type; - uniform_value[U_COMBINER] = j.combiner; - } - - if (j.texture[0]) { - gl_state_active_bind_texture_2d(0, j.texture[0]); - gl_state_bind_sampler(0, j.sampler); - - if (j.texture[1]) { - gl_state_active_bind_texture_2d(1, j.texture[1]); - gl_state_bind_sampler(1, j.sampler); - } - else if (!gl_state.texture_binding_2d[1]) - gl_state_active_bind_texture_2d(1, rctx->empty_texture_2d->glid); - } - else { - if (!gl_state.texture_binding_2d[0]) - gl_state_active_bind_texture_2d(0, rctx->empty_texture_2d->glid); - if (!gl_state.texture_binding_2d[1]) - gl_state_active_bind_texture_2d(1, rctx->empty_texture_2d->glid); - } - - shaders_ft.set(j.shader); - if (j.mode != GL_TRIANGLES) - shaders_ft.draw_arrays(j.mode, j.first, j.count); - else - shaders_ft.draw_range_elements(j.mode, j.start, j.end, - j.count, GL_UNSIGNED_INT, (void*)j.offset); - } + for (uint32_t j = SPR_PRIO_MAX; j; j--, reqlist++) + for (SprArgs& k : *reqlist) + if (k.sprite_draw_param_index >= 0) + draw_sprite(this, rctx, k, mat, x_min, y_min, x_max, y_max, overlay_tex); gl_state_bind_vertex_array(0); } @@ -1074,6 +1036,88 @@ namespace spr { mat = mat4_identity; } + void SpriteManager::PostDraw() { + render_data.Clear(); + } + + void SpriteManager::PreDraw() { + auto check_same = [](const SprArgsInner& left, const SprArgsInner& right) -> bool { + if (left.num_texture != right.num_texture) + return false; + + for (int32_t i = 0; i < left.num_texture; i++) + if (left.textures[i] != right.textures[i]) + return false; + + return left.blend == right.blend && left.blend != 5 && right.blend != 5 + && left.shader == right.shader && left.kind == right.kind + && left.kind != SPR_KIND_ARROW_AB && right.kind != SPR_KIND_ARROW_AB + && left.kind != SPR_KIND_TRIANGLE && right.kind != SPR_KIND_TRIANGLE; + }; + + auto get_num_vertex = [](const SprArgs& args, SprArgsInner& args_inner) { + int32_t num_texture = 0; + if (args.texture) { + const spr::SprArgs* _args = &args; + while (_args) { + args_inner.textures[num_texture++] = _args->texture; + _args = _args->next; + } + } + + args_inner.num_texture = num_texture; + args_inner.blend = args.blend; + args_inner.shader = args.shader; + args_inner.kind = args.kind; + }; + + SprArgsInner args_inner[2]; + SprArgs* args_array[256]; + for (int32_t i = 0; i < 4; i++) + for (int32_t j = 0; j < 2; j++) + for (int32_t k = 0; k < SPR_PRIO_MAX; k++) { + int32_t args_count = 0; + int32_t inner_idx = 0; + for (SprArgs& args : reqlist[i][j][k]) { + if (!args_count) { + get_num_vertex(args, args_inner[inner_idx]); + + args_array[args_count++] = &args; + inner_idx = 1 - inner_idx; + } + else if (args_count >= 0x100) { + add_draw_sprite(args_array, args_count, true, + args_inner[1 - inner_idx], render_data.draw_param_buffer, + render_data.vertex_buffer, render_data.index_buffer); + get_num_vertex(args, args_inner[inner_idx]); + + args_count = 0; + args_array[args_count++] = &args; + inner_idx = 1 - inner_idx; + } + else { + get_num_vertex(args, args_inner[inner_idx]); + if (!check_same(args_inner[1 - inner_idx], args_inner[inner_idx])) { + add_draw_sprite(args_array, args_count, true, + args_inner[1 - inner_idx], render_data.draw_param_buffer, + render_data.vertex_buffer, render_data.index_buffer); + + args_count = 0; + inner_idx = 1 - inner_idx; + } + args_array[args_count++] = &args; + } + } + + if (args_count) + add_draw_sprite(args_array, args_count, true, + args_inner[1 - inner_idx], render_data.draw_param_buffer, + render_data.vertex_buffer, render_data.index_buffer); + } + + render_data.Update(); + } + void SpriteManager::UnloadSet(uint32_t index) { SprSet* set = GetSet(index); if (set) @@ -1278,351 +1322,207 @@ namespace spr { return tex_param_count; } - static void draw_sprite(render_context* rctx, SprArgs& args, bool font, - const mat4& mat, int32_t x_min, int32_t y_min, int32_t x_max, int32_t y_max, - std::vector& draw_param_buffer, + static void add_draw_sprite(spr::SprArgs** args_array, int32_t count, bool font, + spr::SprArgsInner& args_inner, std::vector& draw_param_buffer, std::vector& vertex_buffer, std::vector& index_buffer) { - if (args.kind == SPR_KIND_LINE) - return; + for (int32_t i = 0; i < count; i++) { + SprArgs& args = *args_array[i]; - const color4u8 color = args.color; + if (args.kind == SPR_KIND_LINE) + continue; - if (font) - draw_sprite_scale(&args); + const color4u8 color = args.color; - vec3 vtx[4] = {}; - spr::TexParam tex_param[4] = {}; + if (font) + draw_sprite_scale(&args); - if (args.flags & SprArgs::SPRITE_SIZE) - calc_sprite_vertex(&args, vtx, 0, font); + vec3 vtx[4] = {}; + spr::TexParam tex_param[4] = {}; - int32_t tex_param_count = 0; - if ((args.flags & SprArgs::TEXTURE_POS_SIZE) && args.texture) { - tex_param_count = calc_sprite_texture_param(&args, tex_param, vtx, font); - tex_param_count = min_def(tex_param_count, 2); - } + if (args.flags & SprArgs::SPRITE_SIZE) + calc_sprite_vertex(&args, vtx, 0, font); - mat4 mat_t; - mat4_transpose(&mat, &mat_t); - - draw_param_buffer.push_back({}); - sprite_draw_param& draw_param = draw_param_buffer.back(); - - if (!(args.attr & SPR_ATTR_NOBLEND)) { - const GLenum* blend = spr_blend_param[args.blend]; - draw_param.blend = true; - draw_param.blend_src_rgb = blend[0]; - draw_param.blend_dst_rgb = blend[1]; - draw_param.blend_src_alpha = blend[2]; - draw_param.blend_dst_alpha = blend[3]; - - if (args.blend == 5 && !args.num_vertex && args.kind == SPR_KIND_NORMAL) { - float_t v25 = 0.0f; - float_t v26 = 0.0f; - float_t v27 = 0.0f; - float_t v28 = 0.0f; - for (int32_t i = 0, j = 0; i < 4; i++) { - vec4 v; - *(vec3*)&v = vtx[i]; - v.w = 1.0f; - - float_t v31 = vec4::dot(mat_t.row3, v); - if (v31 * v31 <= 0.0001f) - continue; - - float_t v33 = vec4::dot(mat_t.row0, v) * (1.0f / v31); - float_t v34 = vec4::dot(mat_t.row1, v) * (1.0f / v31); - if (j) { - if (v25 > v33) - v25 = v33; - else if (v27 < v33) - v27 = v33; - - if (v26 > v34) - v26 = v34; - else if (v28 < v34) - v28 = v34; - } - else { - v25 = v33; - v27 = v33; - v26 = v34; - v28 = v34; - } - j++; - } - - int32_t v36 = (int32_t)v27 + 1; - int32_t v37 = (int32_t)v28 + 1; - int32_t v38 = (int32_t)v25 - 1; - int32_t v39 = (int32_t)v26 - 1; - - v36 = clamp_def(v36, x_min, x_min + x_max - 1); - v37 = clamp_def(v37, y_min, y_min + y_max - 1); - v38 = clamp_def(v38, x_min, x_min + x_max - 1); - v39 = clamp_def(v39, y_min, y_min + y_max - 1); - - int32_t v42 = v36 - v38 + 1; - int32_t v43 = v37 - v39 + 1; - if (v42 * v43 > 0) { - draw_param.copy_texture = true; - draw_param.copy_texture_x = v38; - draw_param.copy_texture_y = v39; - draw_param.copy_texture_width = v42; - draw_param.copy_texture_height = v43; - } - } - } - - draw_param.shader = args.shader; - if (draw_param.shader == SHADER_FT_FFP) { - draw_param.shader = SHADER_FT_SPRITE; - draw_param.tex_0_type = 0; - draw_param.tex_1_type = 0; - - if (tex_param_count == 1 || tex_param_count == 2) { - if (tex_param[0].texture->internal_format == GL_COMPRESSED_RED_RGTC1_EXT) - draw_param.tex_0_type = 3; - else if (tex_param[0].texture->internal_format == GL_COMPRESSED_RED_GREEN_RGTC2_EXT) - draw_param.tex_0_type = 2; - else - draw_param.tex_0_type = 1; - - if (tex_param_count == 2) { - if (tex_param[1].texture->internal_format == GL_COMPRESSED_RED_RGTC1_EXT) - draw_param.tex_1_type = 3; - else if (tex_param[1].texture->internal_format == GL_COMPRESSED_RED_GREEN_RGTC2_EXT) - draw_param.tex_1_type = 2; - else - draw_param.tex_1_type = 1; - } + int32_t tex_param_count = 0; + if ((args.flags & SprArgs::TEXTURE_POS_SIZE) && args.texture) { + tex_param_count = calc_sprite_texture_param(&args, tex_param, vtx, font); + tex_param_count = min_def(tex_param_count, 2); } - if (args.attr & SPR_ATTR_NOBLEND) - draw_param.combiner = 0; - else if (args.blend != 5) - draw_param.combiner = args.blend == 3 ? 1 : 0; - else - draw_param.combiner = 2; + draw_param_buffer.push_back({}); + sprite_draw_param& draw_param = draw_param_buffer.back(); - } + if (args.attr & SPR_ATTR_NOBLEND) { + draw_param.attrib.m.enable_blend = 0; + draw_param.attrib.m.blend = 0; + } + else { + draw_param.attrib.m.enable_blend = 1; + draw_param.attrib.m.blend = args.blend; + } - switch (tex_param_count) { - case 0: - switch (args.kind) { - case SPR_KIND_LINES: { - if (vtx[0] == 0.0f && vtx[2] == 0.0f) { - draw_param_buffer.pop_back(); - return; - } + draw_param.shader = args.shader; + if (draw_param.shader == SHADER_FT_FFP) + draw_param.shader = SHADER_FT_SPRITE; - sprite_draw_vertex spr_vtx[2] = {}; - spr_vtx[0].pos = vtx[0]; - spr_vtx[0].color = color; - - spr_vtx[1].pos = vtx[2]; - spr_vtx[1].color = color; - - draw_param.mode = GL_LINES; - draw_param.first = (GLint)vertex_buffer.size(); - draw_param.count = 2; - - vertex_buffer.reserve(2); - vertex_buffer.push_back(spr_vtx[0]); - vertex_buffer.push_back(spr_vtx[1]); - } break; - case SPR_KIND_RECT: { - if (vtx[0] == 0.0f && vtx[1] == 0.0f && vtx[2] == 0.0f && vtx[3] == 0.0f) { - draw_param_buffer.pop_back(); - return; - } - - sprite_draw_vertex spr_vtx[4] = {}; - spr_vtx[0].pos = vtx[0]; - spr_vtx[0].color = color; - - spr_vtx[1].pos = vtx[1]; - spr_vtx[1].color = color; - - spr_vtx[2].pos = vtx[2]; - spr_vtx[2].color = color; - - spr_vtx[3].pos = vtx[3]; - spr_vtx[3].color = color; - - draw_param.mode = GL_TRIANGLES; - draw_param.start = (GLuint)vertex_buffer.size(); - draw_param.end = draw_param.start + 3; - draw_param.count = 6; - draw_param.offset = (GLintptr)(index_buffer.size() * sizeof(uint32_t)); - - uint32_t start_vertex_index = (uint32_t)vertex_buffer.size(); - - vertex_buffer.reserve(4); - vertex_buffer.push_back(spr_vtx[0]); // LB - vertex_buffer.push_back(spr_vtx[3]); // RB - vertex_buffer.push_back(spr_vtx[2]); // RT - vertex_buffer.push_back(spr_vtx[1]); // LT - - index_buffer.reserve(6); - index_buffer.push_back(start_vertex_index + 0); // LB - index_buffer.push_back(start_vertex_index + 3); // LT - index_buffer.push_back(start_vertex_index + 1); // RB - index_buffer.push_back(start_vertex_index + 1); // RB - index_buffer.push_back(start_vertex_index + 3); // LT - index_buffer.push_back(start_vertex_index + 2); // RT - } break; - case SPR_KIND_MULTI: { - if (vtx[0] == 0.0f && vtx[1] == 0.0f && vtx[2] == 0.0f && vtx[3] == 0.0f) { - draw_param_buffer.pop_back(); - return; - } - - sprite_draw_vertex spr_vtx[4] = {}; - spr_vtx[0].pos = vtx[0]; - spr_vtx[0].color = color; - - spr_vtx[1].pos = vtx[1]; - spr_vtx[1].color = color; - - spr_vtx[2].pos = vtx[2]; - spr_vtx[2].color = color; - - spr_vtx[3].pos = vtx[3]; - spr_vtx[3].color = color; - - draw_param.mode = GL_LINE_LOOP; - draw_param.first = (GLint)vertex_buffer.size(); - draw_param.count = 4; - - vertex_buffer.reserve(4); - vertex_buffer.push_back(spr_vtx[0]); - vertex_buffer.push_back(spr_vtx[1]); - vertex_buffer.push_back(spr_vtx[2]); - vertex_buffer.push_back(spr_vtx[3]); - } break; - case SPR_KIND_ARROW_B: { - sprite_draw_vertex spr_vtx[2] = {}; - spr_vtx[0].color = color; - spr_vtx[1].color = color; - - if (args.num_vertex) { - draw_param.mode = GL_LINES; - draw_param.first = (GLint)vertex_buffer.size(); - draw_param.count = (uint32_t)(args.num_vertex / 2 * 2); - - size_t vertex_buffer_size = vertex_buffer.size(); - vertex_buffer.reserve(args.num_vertex / 2 * 2); - -#if BREAK_SPRITE_VERTEX_LIMIT - SpriteVertex* vtx = sprite_vertex_array + args.vertex_array; -#else - SpriteVertex* vtx = args.vertex_array; -#endif - for (size_t i = args.num_vertex / 2; i; i--, vtx += 2) { - if (vtx[0].pos == 0.0f && vtx[1].pos == 0.0f) - continue; - - spr_vtx[0].pos = vtx[0].pos; - spr_vtx[1].pos = vtx[1].pos; - vertex_buffer.push_back(spr_vtx[0]); - vertex_buffer.push_back(spr_vtx[1]); - } - - if (vertex_buffer_size == vertex_buffer.size()) { - draw_param_buffer.pop_back(); - return; - } - } - else { + switch (tex_param_count) { + case 0: + switch (args.kind) { + case SPR_KIND_LINES: { if (vtx[0] == 0.0f && vtx[2] == 0.0f) { draw_param_buffer.pop_back(); - return; + continue; } + sprite_draw_vertex spr_vtx[2] = {}; spr_vtx[0].pos = vtx[0]; - spr_vtx[1].pos = vtx[2]; + spr_vtx[0].color = color; - draw_param.mode = GL_LINES; + spr_vtx[1].pos = vtx[2]; + spr_vtx[1].color = color; + + draw_param.attrib.m.primitive = GL_LINES; draw_param.first = (GLint)vertex_buffer.size(); draw_param.count = 2; vertex_buffer.reserve(2); vertex_buffer.push_back(spr_vtx[0]); vertex_buffer.push_back(spr_vtx[1]); - } - } break; - case SPR_KIND_ARROW_AB: { - if (!args.num_vertex) { - draw_param_buffer.pop_back(); - return; - } + } break; + case SPR_KIND_RECT: { + if (vtx[0] == 0.0f && vtx[1] == 0.0f && vtx[2] == 0.0f && vtx[3] == 0.0f) { + draw_param_buffer.pop_back(); + continue; + } - draw_param.mode = GL_LINE_STRIP; - draw_param.first = (GLint)vertex_buffer.size(); - draw_param.count = (GLsizei)args.num_vertex; + sprite_draw_vertex spr_vtx[4] = {}; + spr_vtx[0].pos = vtx[0]; + spr_vtx[0].color = color; - vertex_buffer.reserve(args.num_vertex); + spr_vtx[1].pos = vtx[1]; + spr_vtx[1].color = color; - sprite_draw_vertex spr_vtx = {}; - spr_vtx.color = color; + spr_vtx[2].pos = vtx[2]; + spr_vtx[2].color = color; + + spr_vtx[3].pos = vtx[3]; + spr_vtx[3].color = color; + + draw_param.attrib.m.primitive = GL_TRIANGLES; + draw_param.start = (GLuint)vertex_buffer.size(); + draw_param.end = draw_param.start + 3; + draw_param.count = 6; + draw_param.offset = (GLintptr)(index_buffer.size() * sizeof(uint32_t)); + + uint32_t start_vertex_index = (uint32_t)vertex_buffer.size(); + + vertex_buffer.reserve(4); + vertex_buffer.push_back(spr_vtx[0]); // LB + vertex_buffer.push_back(spr_vtx[3]); // RB + vertex_buffer.push_back(spr_vtx[2]); // RT + vertex_buffer.push_back(spr_vtx[1]); // LT + + index_buffer.reserve(6); + index_buffer.push_back(start_vertex_index + 0); // LB + index_buffer.push_back(start_vertex_index + 3); // LT + index_buffer.push_back(start_vertex_index + 1); // RB + index_buffer.push_back(start_vertex_index + 1); // RB + index_buffer.push_back(start_vertex_index + 3); // LT + index_buffer.push_back(start_vertex_index + 2); // RT + } break; + case SPR_KIND_MULTI: { + if (vtx[0] == 0.0f && vtx[1] == 0.0f && vtx[2] == 0.0f && vtx[3] == 0.0f) { + draw_param_buffer.pop_back(); + continue; + } + + sprite_draw_vertex spr_vtx[4] = {}; + spr_vtx[0].pos = vtx[0]; + spr_vtx[0].color = color; + + spr_vtx[1].pos = vtx[1]; + spr_vtx[1].color = color; + + spr_vtx[2].pos = vtx[2]; + spr_vtx[2].color = color; + + spr_vtx[3].pos = vtx[3]; + spr_vtx[3].color = color; + + draw_param.attrib.m.primitive = GL_LINE_LOOP; + draw_param.first = (GLint)vertex_buffer.size(); + draw_param.count = 4; + + vertex_buffer.reserve(4); + vertex_buffer.push_back(spr_vtx[0]); + vertex_buffer.push_back(spr_vtx[1]); + vertex_buffer.push_back(spr_vtx[2]); + vertex_buffer.push_back(spr_vtx[3]); + } break; + case SPR_KIND_ARROW_B: { + sprite_draw_vertex spr_vtx[2] = {}; + spr_vtx[0].color = color; + spr_vtx[1].color = color; + + if (args.num_vertex) { + draw_param.attrib.m.primitive = GL_LINES; + draw_param.first = (GLint)vertex_buffer.size(); + draw_param.count = (uint32_t)(args.num_vertex / 2 * 2); + + size_t vertex_buffer_size = vertex_buffer.size(); + vertex_buffer.reserve(args.num_vertex / 2 * 2); #if BREAK_SPRITE_VERTEX_LIMIT - SpriteVertex* vtx = sprite_vertex_array + args.vertex_array; + SpriteVertex* vtx = sprite_vertex_array + args.vertex_array; #else - SpriteVertex* vtx = args.vertex_array; + SpriteVertex* vtx = args.vertex_array; #endif - for (size_t i = args.num_vertex; i; i--, vtx++) { - spr_vtx.pos = vtx->pos; - vertex_buffer.push_back(spr_vtx); - } - } break; - case SPR_KIND_TRIANGLE: { - if (!args.num_vertex) { - draw_param_buffer.pop_back(); - return; - } + for (size_t i = args.num_vertex / 2; i; i--, vtx += 2) { + if (vtx[0].pos == 0.0f && vtx[1].pos == 0.0f) + continue; - draw_param.mode = GL_TRIANGLE_STRIP; - draw_param.first = (GLint)vertex_buffer.size(); - draw_param.count = (GLsizei)args.num_vertex; + spr_vtx[0].pos = vtx[0].pos; + spr_vtx[1].pos = vtx[1].pos; + vertex_buffer.push_back(spr_vtx[0]); + vertex_buffer.push_back(spr_vtx[1]); + } - vertex_buffer.reserve(args.num_vertex); + if (vertex_buffer_size == vertex_buffer.size()) { + draw_param_buffer.pop_back(); + continue; + } + } + else { + if (vtx[0] == 0.0f && vtx[2] == 0.0f) { + draw_param_buffer.pop_back(); + continue; + } - sprite_draw_vertex spr_vtx = {}; - spr_vtx.color = color; + spr_vtx[0].pos = vtx[0]; + spr_vtx[1].pos = vtx[2]; -#if BREAK_SPRITE_VERTEX_LIMIT - SpriteVertex* vtx = sprite_vertex_array + args.vertex_array; -#else - SpriteVertex* vtx = args.vertex_array; -#endif - for (size_t i = args.num_vertex; i; i--, vtx++) { - spr_vtx.pos = vtx->pos; - vertex_buffer.push_back(spr_vtx); - } - } break; - default: - draw_param_buffer.pop_back(); - return; - } - break; - case 1: - draw_param.texture[0] = tex_param[0].texture ? tex_param[0].texture->glid : 0; - draw_param.sampler = rctx->sprite_samplers[0]; + draw_param.attrib.m.primitive = GL_LINES; + draw_param.first = (GLint)vertex_buffer.size(); + draw_param.count = 2; - if (args.num_vertex) { - if (args.kind == SPR_KIND_TRIANGLE) - draw_param.sampler = rctx->sprite_samplers[1]; + vertex_buffer.reserve(2); + vertex_buffer.push_back(spr_vtx[0]); + vertex_buffer.push_back(spr_vtx[1]); + } + } break; + case SPR_KIND_ARROW_AB: { + if (!args.num_vertex) { + draw_param_buffer.pop_back(); + continue; + } - if (args.kind == SPR_KIND_TRIANGLE) { - draw_param.mode = GL_TRIANGLE_STRIP; + draw_param.attrib.m.primitive = GL_LINE_STRIP; draw_param.first = (GLint)vertex_buffer.size(); draw_param.count = (GLsizei)args.num_vertex; vertex_buffer.reserve(args.num_vertex); sprite_draw_vertex spr_vtx = {}; + spr_vtx.color = color; #if BREAK_SPRITE_VERTEX_LIMIT SpriteVertex* vtx = sprite_vertex_array + args.vertex_array; @@ -1631,98 +1531,217 @@ namespace spr { #endif for (size_t i = args.num_vertex; i; i--, vtx++) { spr_vtx.pos = vtx->pos; - spr_vtx.uv[0] = vtx->uv; - spr_vtx.color = vtx->color; vertex_buffer.push_back(spr_vtx); } - } - else { - size_t num_vertex = args.num_vertex / 4 * 6; + } break; + case SPR_KIND_TRIANGLE: { + if (!args.num_vertex) { + draw_param_buffer.pop_back(); + continue; + } - draw_param.mode = GL_TRIANGLES; - draw_param.start = (GLuint)vertex_buffer.size(); - draw_param.end = draw_param.start + (GLuint)(args.num_vertex - 1); - draw_param.count = (GLsizei)num_vertex; - draw_param.offset = (GLintptr)(index_buffer.size() * sizeof(uint32_t)); + draw_param.attrib.m.primitive = GL_TRIANGLE_STRIP; + draw_param.first = (GLint)vertex_buffer.size(); + draw_param.count = (GLsizei)args.num_vertex; - uint32_t start_vertex_index = (uint32_t)vertex_buffer.size(); - - size_t vertex_buffer_size = vertex_buffer.size(); vertex_buffer.reserve(args.num_vertex); - index_buffer.reserve(num_vertex); - sprite_draw_vertex spr_vtx[4] = {}; + sprite_draw_vertex spr_vtx = {}; + spr_vtx.color = color; #if BREAK_SPRITE_VERTEX_LIMIT SpriteVertex* vtx = sprite_vertex_array + args.vertex_array; #else SpriteVertex* vtx = args.vertex_array; #endif - for (size_t i = num_vertex / 6, j = 0; i; i--, j += 4, vtx += 4) { - if (vtx[0].pos == 0.0f && vtx[1].pos == 0.0f - && vtx[2].pos == 0.0f && vtx[3].pos == 0.0f) - continue; - - spr_vtx[0].pos = vtx[0].pos; - spr_vtx[0].uv[0] = vtx[0].uv; - spr_vtx[0].color = vtx[0].color; - spr_vtx[1].pos = vtx[1].pos; - spr_vtx[1].uv[0] = vtx[1].uv; - spr_vtx[1].color = vtx[1].color; - spr_vtx[2].pos = vtx[2].pos; - spr_vtx[2].uv[0] = vtx[2].uv; - spr_vtx[2].color = vtx[2].color; - spr_vtx[3].pos = vtx[3].pos; - spr_vtx[3].uv[0] = vtx[3].uv; - spr_vtx[3].color = vtx[3].color; - - vertex_buffer.push_back(spr_vtx[0]); // LB - vertex_buffer.push_back(spr_vtx[3]); // RB - vertex_buffer.push_back(spr_vtx[2]); // RT - vertex_buffer.push_back(spr_vtx[1]); // LT - - index_buffer.push_back(start_vertex_index + (uint32_t)j + 0); // LB - index_buffer.push_back(start_vertex_index + (uint32_t)j + 3); // LT - index_buffer.push_back(start_vertex_index + (uint32_t)j + 1); // RB - index_buffer.push_back(start_vertex_index + (uint32_t)j + 1); // RB - index_buffer.push_back(start_vertex_index + (uint32_t)j + 3); // LT - index_buffer.push_back(start_vertex_index + (uint32_t)j + 2); // RT + for (size_t i = args.num_vertex; i; i--, vtx++) { + spr_vtx.pos = vtx->pos; + vertex_buffer.push_back(spr_vtx); } + } break; + default: + draw_param_buffer.pop_back(); + continue; + } + break; + case 1: + draw_param.textures[0] = tex_param[0].texture; + draw_param.attrib.m.sampler = 0; - if (vertex_buffer_size == vertex_buffer.size()) { - draw_param_buffer.pop_back(); - return; + if (args.num_vertex) { + if (args.kind == SPR_KIND_TRIANGLE) + draw_param.attrib.m.sampler = 1; + + if (args.kind == SPR_KIND_TRIANGLE) { + draw_param.attrib.m.primitive = GL_TRIANGLE_STRIP; + draw_param.first = (GLint)vertex_buffer.size(); + draw_param.count = (GLsizei)args.num_vertex; + + vertex_buffer.reserve(args.num_vertex); + + sprite_draw_vertex spr_vtx = {}; + +#if BREAK_SPRITE_VERTEX_LIMIT + SpriteVertex* vtx = sprite_vertex_array + args.vertex_array; +#else + SpriteVertex* vtx = args.vertex_array; +#endif + for (size_t i = args.num_vertex; i; i--, vtx++) { + spr_vtx.pos = vtx->pos; + spr_vtx.uv[0] = vtx->uv; + spr_vtx.color = vtx->color; + vertex_buffer.push_back(spr_vtx); + } + } + else { + size_t num_vertex = args.num_vertex / 4 * 6; + + draw_param.attrib.m.primitive = GL_TRIANGLES; + draw_param.start = (GLuint)vertex_buffer.size(); + draw_param.end = draw_param.start + (GLuint)(args.num_vertex - 1); + draw_param.count = (GLsizei)num_vertex; + draw_param.offset = (GLintptr)(index_buffer.size() * sizeof(uint32_t)); + + uint32_t start_vertex_index = (uint32_t)vertex_buffer.size(); + + size_t vertex_buffer_size = vertex_buffer.size(); + vertex_buffer.reserve(args.num_vertex); + index_buffer.reserve(num_vertex); + + sprite_draw_vertex spr_vtx[4] = {}; + +#if BREAK_SPRITE_VERTEX_LIMIT + SpriteVertex* vtx = sprite_vertex_array + args.vertex_array; +#else + SpriteVertex* vtx = args.vertex_array; +#endif + for (size_t i = num_vertex / 6, j = 0; i; i--, j += 4, vtx += 4) { + if (vtx[0].pos == 0.0f && vtx[1].pos == 0.0f + && vtx[2].pos == 0.0f && vtx[3].pos == 0.0f) + continue; + + spr_vtx[0].pos = vtx[0].pos; + spr_vtx[0].uv[0] = vtx[0].uv; + spr_vtx[0].color = vtx[0].color; + spr_vtx[1].pos = vtx[1].pos; + spr_vtx[1].uv[0] = vtx[1].uv; + spr_vtx[1].color = vtx[1].color; + spr_vtx[2].pos = vtx[2].pos; + spr_vtx[2].uv[0] = vtx[2].uv; + spr_vtx[2].color = vtx[2].color; + spr_vtx[3].pos = vtx[3].pos; + spr_vtx[3].uv[0] = vtx[3].uv; + spr_vtx[3].color = vtx[3].color; + + vertex_buffer.push_back(spr_vtx[0]); // LB + vertex_buffer.push_back(spr_vtx[3]); // RB + vertex_buffer.push_back(spr_vtx[2]); // RT + vertex_buffer.push_back(spr_vtx[1]); // LT + + index_buffer.push_back(start_vertex_index + (uint32_t)j + 0); // LB + index_buffer.push_back(start_vertex_index + (uint32_t)j + 3); // LT + index_buffer.push_back(start_vertex_index + (uint32_t)j + 1); // RB + index_buffer.push_back(start_vertex_index + (uint32_t)j + 1); // RB + index_buffer.push_back(start_vertex_index + (uint32_t)j + 3); // LT + index_buffer.push_back(start_vertex_index + (uint32_t)j + 2); // RT + } + + if (vertex_buffer_size == vertex_buffer.size()) { + draw_param_buffer.pop_back(); + continue; + } } } - } - else { + else { + if (vtx[0] == 0.0f && vtx[1] == 0.0f && vtx[2] == 0.0f && vtx[3] == 0.0f) { + draw_param_buffer.pop_back(); + continue; + } + + sprite_draw_vertex spr_vtx[4] = {}; + spr_vtx[0].pos = vtx[0]; + spr_vtx[0].uv[0].x = tex_param[0].texcoord.uv[0].u; + spr_vtx[0].uv[0].y = tex_param[0].texcoord.uv[0].v; + spr_vtx[0].color = color; + + spr_vtx[1].pos = vtx[1]; + spr_vtx[1].uv[0].x = tex_param[0].texcoord.uv[1].u; + spr_vtx[1].uv[0].y = tex_param[0].texcoord.uv[1].v; + spr_vtx[1].color = color; + + spr_vtx[2].pos = vtx[2]; + spr_vtx[2].uv[0].x = tex_param[0].texcoord.uv[2].u; + spr_vtx[2].uv[0].y = tex_param[0].texcoord.uv[2].v; + spr_vtx[2].color = color; + + spr_vtx[3].pos = vtx[3]; + spr_vtx[3].uv[0].x = tex_param[0].texcoord.uv[3].u; + spr_vtx[3].uv[0].y = tex_param[0].texcoord.uv[3].v; + spr_vtx[3].color = color; + + draw_param.attrib.m.primitive = GL_TRIANGLES; + draw_param.start = (GLuint)vertex_buffer.size(); + draw_param.end = draw_param.start + 3; + draw_param.count = 6; + draw_param.offset = (GLintptr)(index_buffer.size() * sizeof(uint32_t)); + + uint32_t start_vertex_index = (uint32_t)vertex_buffer.size(); + + vertex_buffer.reserve(4); + vertex_buffer.push_back(spr_vtx[0]); // LB + vertex_buffer.push_back(spr_vtx[3]); // RB + vertex_buffer.push_back(spr_vtx[2]); // RT + vertex_buffer.push_back(spr_vtx[1]); // LT + + index_buffer.reserve(6); + index_buffer.push_back(start_vertex_index + 0); // LB + index_buffer.push_back(start_vertex_index + 3); // LT + index_buffer.push_back(start_vertex_index + 1); // RB + index_buffer.push_back(start_vertex_index + 1); // RB + index_buffer.push_back(start_vertex_index + 3); // LT + index_buffer.push_back(start_vertex_index + 2); // RT + } + break; + case 2: { if (vtx[0] == 0.0f && vtx[1] == 0.0f && vtx[2] == 0.0f && vtx[3] == 0.0f) { draw_param_buffer.pop_back(); - return; + continue; } + draw_param.textures[0] = tex_param[0].texture; + draw_param.textures[1] = tex_param[1].texture; + draw_param.attrib.m.sampler = 2; + sprite_draw_vertex spr_vtx[4] = {}; spr_vtx[0].pos = vtx[0]; spr_vtx[0].uv[0].x = tex_param[0].texcoord.uv[0].u; spr_vtx[0].uv[0].y = tex_param[0].texcoord.uv[0].v; + spr_vtx[0].uv[1].x = tex_param[1].texcoord.uv[0].u; + spr_vtx[0].uv[1].y = tex_param[1].texcoord.uv[0].v; spr_vtx[0].color = color; spr_vtx[1].pos = vtx[1]; spr_vtx[1].uv[0].x = tex_param[0].texcoord.uv[1].u; spr_vtx[1].uv[0].y = tex_param[0].texcoord.uv[1].v; + spr_vtx[1].uv[1].x = tex_param[1].texcoord.uv[1].u; + spr_vtx[1].uv[1].y = tex_param[1].texcoord.uv[1].v; spr_vtx[1].color = color; spr_vtx[2].pos = vtx[2]; spr_vtx[2].uv[0].x = tex_param[0].texcoord.uv[2].u; spr_vtx[2].uv[0].y = tex_param[0].texcoord.uv[2].v; + spr_vtx[2].uv[1].x = tex_param[1].texcoord.uv[2].u; + spr_vtx[2].uv[1].y = tex_param[1].texcoord.uv[2].v; spr_vtx[2].color = color; spr_vtx[3].pos = vtx[3]; spr_vtx[3].uv[0].x = tex_param[0].texcoord.uv[3].u; spr_vtx[3].uv[0].y = tex_param[0].texcoord.uv[3].v; + spr_vtx[3].uv[1].x = tex_param[1].texcoord.uv[3].u; + spr_vtx[3].uv[1].y = tex_param[1].texcoord.uv[3].v; spr_vtx[3].color = color; - draw_param.mode = GL_TRIANGLES; + draw_param.attrib.m.primitive = GL_TRIANGLES; draw_param.start = (GLuint)vertex_buffer.size(); draw_param.end = draw_param.start + 3; draw_param.count = 6; @@ -1743,96 +1762,105 @@ namespace spr { index_buffer.push_back(start_vertex_index + 1); // RB index_buffer.push_back(start_vertex_index + 3); // LT index_buffer.push_back(start_vertex_index + 2); // RT - } - break; - case 2: { - if (vtx[0] == 0.0f && vtx[1] == 0.0f && vtx[2] == 0.0f && vtx[3] == 0.0f) { - draw_param_buffer.pop_back(); - return; + } break; } - draw_param.texture[0] = tex_param[0].texture ? tex_param[0].texture->glid : 0; - draw_param.texture[1] = tex_param[1].texture ? tex_param[1].texture->glid : 0; - draw_param.sampler = rctx->sprite_samplers[2]; + if (draw_param_buffer.size() >= 2) { + sprite_draw_param& draw_param_2 = draw_param_buffer.data()[draw_param_buffer.size() - 2]; + sprite_draw_param& draw_param_1 = draw_param_buffer.data()[draw_param_buffer.size() - 1]; - sprite_draw_vertex spr_vtx[4] = {}; - spr_vtx[0].pos = vtx[0]; - spr_vtx[0].uv[0].x = tex_param[0].texcoord.uv[0].u; - spr_vtx[0].uv[0].y = tex_param[0].texcoord.uv[0].v; - spr_vtx[0].uv[1].x = tex_param[1].texcoord.uv[0].u; - spr_vtx[0].uv[1].y = tex_param[1].texcoord.uv[0].v; - spr_vtx[0].color = color; + if (draw_param_1.attrib.m.primitive == GL_TRIANGLES + && draw_param_2.attrib.w == draw_param_1.attrib.w + && draw_param_2.shader == draw_param_1.shader + && draw_param_2.textures[0] == draw_param_1.textures[0] + && draw_param_2.textures[1] == draw_param_1.textures[1] + && draw_param_2.end + 1 == draw_param_1.start) { + draw_param_2.end = draw_param_1.end; + draw_param_2.count += draw_param_1.count; + draw_param_buffer.pop_back(); + } + } - spr_vtx[1].pos = vtx[1]; - spr_vtx[1].uv[0].x = tex_param[0].texcoord.uv[1].u; - spr_vtx[1].uv[0].y = tex_param[0].texcoord.uv[1].v; - spr_vtx[1].uv[1].x = tex_param[1].texcoord.uv[1].u; - spr_vtx[1].uv[1].y = tex_param[1].texcoord.uv[1].v; - spr_vtx[1].color = color; - - spr_vtx[2].pos = vtx[2]; - spr_vtx[2].uv[0].x = tex_param[0].texcoord.uv[2].u; - spr_vtx[2].uv[0].y = tex_param[0].texcoord.uv[2].v; - spr_vtx[2].uv[1].x = tex_param[1].texcoord.uv[2].u; - spr_vtx[2].uv[1].y = tex_param[1].texcoord.uv[2].v; - spr_vtx[2].color = color; - - spr_vtx[3].pos = vtx[3]; - spr_vtx[3].uv[0].x = tex_param[0].texcoord.uv[3].u; - spr_vtx[3].uv[0].y = tex_param[0].texcoord.uv[3].v; - spr_vtx[3].uv[1].x = tex_param[1].texcoord.uv[3].u; - spr_vtx[3].uv[1].y = tex_param[1].texcoord.uv[3].v; - spr_vtx[3].color = color; - - draw_param.mode = GL_TRIANGLES; - draw_param.start = (GLuint)vertex_buffer.size(); - draw_param.end = draw_param.start + 3; - draw_param.count = 6; - draw_param.offset = (GLintptr)(index_buffer.size() * sizeof(uint32_t)); - - uint32_t start_vertex_index = (uint32_t)vertex_buffer.size(); - - vertex_buffer.reserve(4); - vertex_buffer.push_back(spr_vtx[0]); // LB - vertex_buffer.push_back(spr_vtx[3]); // RB - vertex_buffer.push_back(spr_vtx[2]); // RT - vertex_buffer.push_back(spr_vtx[1]); // LT - - index_buffer.reserve(6); - index_buffer.push_back(start_vertex_index + 0); // LB - index_buffer.push_back(start_vertex_index + 3); // LT - index_buffer.push_back(start_vertex_index + 1); // RB - index_buffer.push_back(start_vertex_index + 1); // RB - index_buffer.push_back(start_vertex_index + 3); // LT - index_buffer.push_back(start_vertex_index + 2); // RT - } break; + args.sprite_draw_param_index = (int32_t)(draw_param_buffer.size() - 1); } - if (draw_param_buffer.size() >= 2) { - sprite_draw_param& draw_param_2 = draw_param_buffer.data()[draw_param_buffer.size() - 2]; - sprite_draw_param& draw_param_1 = draw_param_buffer.data()[draw_param_buffer.size() - 1]; + for (int32_t i = 1; i < count; i++) + args_array[i]->sprite_draw_param_index = -1; + } - if (draw_param_1.mode == GL_TRIANGLES - && draw_param_2.mode == draw_param_1.mode - && draw_param_2.blend == draw_param_1.blend - && draw_param_2.blend_src_rgb == draw_param_1.blend_src_rgb - && draw_param_2.blend_src_alpha == draw_param_1.blend_src_alpha - && draw_param_2.blend_dst_rgb == draw_param_1.blend_dst_rgb - && draw_param_2.blend_dst_alpha == draw_param_1.blend_dst_alpha - && !draw_param_2.copy_texture && !draw_param_1.copy_texture - && draw_param_2.shader == draw_param_1.shader - && draw_param_2.tex_0_type == draw_param_1.tex_0_type - && draw_param_2.tex_1_type == draw_param_1.tex_1_type - && draw_param_2.combiner == draw_param_1.combiner - && draw_param_2.texture[0] == draw_param_1.texture[0] - && draw_param_2.texture[1] == draw_param_1.texture[1] - && draw_param_2.sampler == draw_param_1.sampler - && draw_param_2.end + 1 == draw_param_1.start) { - draw_param_2.end = draw_param_1.end; - draw_param_2.count += draw_param_1.count; - draw_param_buffer.pop_back(); + static void draw_sprite(spr::SpriteManager* sprite_manager, render_context* rctx, const SprArgs& args, + const mat4& mat, int32_t x_min, int32_t y_min, int32_t x_max, int32_t y_max, texture* overlay_tex) { + sprite_draw_param& draw_param + = sprite_manager->render_data.draw_param_buffer.data()[args.sprite_draw_param_index]; + + int32_t combiner = 0; + if (draw_param.attrib.m.enable_blend) { + if (draw_param.attrib.m.blend == 5) { + gl_state_active_bind_texture_2d(7, overlay_tex->glid); + draw_sprite_copy_overlay_texture(rctx, args, mat, draw_param.vtx, x_min, y_min, x_max, y_max); + combiner = 2; } + else + combiner = draw_param.attrib.m.blend == 3 ? 1 : 0; + + const GLenum* blend = spr_blend_param[draw_param.attrib.m.blend]; + + gl_state_enable_blend(); + gl_state_set_blend_func_separate(blend[0], blend[1], blend[2], blend[3]); } + else + gl_state_disable_blend(); + + if (draw_param.shader == SHADER_FT_SPRITE) { + int32_t tex_0_type = 0; + int32_t tex_1_type = 0; + if (draw_param.textures[0]) { + if (draw_param.textures[0]->internal_format == GL_COMPRESSED_RED_RGTC1_EXT) + tex_0_type = 3; + else if (draw_param.textures[0]->internal_format == GL_COMPRESSED_RED_GREEN_RGTC2_EXT) + tex_0_type = 2; + else + tex_0_type = 1; + + if (draw_param.textures[1]) { + if (draw_param.textures[1]->internal_format == GL_COMPRESSED_RED_RGTC1_EXT) + tex_1_type = 3; + else if (draw_param.textures[1]->internal_format == GL_COMPRESSED_RED_GREEN_RGTC2_EXT) + tex_1_type = 2; + else + tex_1_type = 1; + } + } + + uniform_value[U_TEX_0_TYPE] = tex_0_type; + uniform_value[U_TEX_1_TYPE] = tex_1_type; + uniform_value[U_COMBINER] = combiner; + } + + if (draw_param.textures[0]) { + gl_state_active_bind_texture_2d(0, draw_param.textures[0]->glid); + gl_state_bind_sampler(0, rctx->sprite_samplers[draw_param.attrib.m.sampler]); + + if (draw_param.textures[1]) { + gl_state_active_bind_texture_2d(1, draw_param.textures[1]->glid); + gl_state_bind_sampler(1, rctx->sprite_samplers[draw_param.attrib.m.sampler]); + } + else if (!gl_state.texture_binding_2d[1]) + gl_state_active_bind_texture_2d(1, rctx->empty_texture_2d->glid); + } + else { + if (!gl_state.texture_binding_2d[0]) + gl_state_active_bind_texture_2d(0, rctx->empty_texture_2d->glid); + if (!gl_state.texture_binding_2d[1]) + gl_state_active_bind_texture_2d(1, rctx->empty_texture_2d->glid); + } + + shaders_ft.set(draw_param.shader); + if (draw_param.attrib.m.primitive != GL_TRIANGLES) + shaders_ft.draw_arrays(draw_param.attrib.m.primitive, draw_param.first, draw_param.count); + else + shaders_ft.draw_range_elements(draw_param.attrib.m.primitive, draw_param.start, draw_param.end, + draw_param.count, GL_UNSIGNED_INT, (void*)draw_param.offset); } static void draw_sprite_begin(render_context* rctx) { @@ -1845,6 +1873,67 @@ namespace spr { gl_state_set_blend_func_separate(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO); } + static void draw_sprite_copy_overlay_texture(render_context* rctx, const SprArgs& args, const mat4& mat, + const vec3* vtx, int32_t overlay_x_min, int32_t overlay_y_min, int32_t overlay_x_max, int32_t overlay_y_max) { + if (args.num_vertex || args.kind != SPR_KIND_NORMAL) + return; + + mat4 mat_t; + mat4_transpose(&mat, &mat_t); + + float_t x_min_coord = 0.0f; + float_t y_min_coord = 0.0f; + float_t x_max_coord = 0.0f; + float_t y_max_coord = 0.0f; + for (int32_t i = 0, j = 0; i < 4; i++) { + vec4 v; + *(vec3*)&v = vtx[i]; + v.w = 1.0f; + + const float_t w = vec4::dot(mat_t.row3, v); + if (w * w <= 0.0001f) + continue; + + const float_t x_coord = vec4::dot(mat_t.row0, v) * (1.0f / w); + const float_t y_coord = vec4::dot(mat_t.row1, v) * (1.0f / w); + if (j) { + if (x_min_coord > x_coord) + x_min_coord = x_coord; + else if (x_max_coord < x_coord) + x_max_coord = x_coord; + + if (y_min_coord > y_coord) + y_min_coord = y_coord; + else if (y_max_coord < y_coord) + y_max_coord = y_coord; + } + else { + x_min_coord = x_coord; + x_max_coord = x_coord; + y_min_coord = y_coord; + y_max_coord = y_coord; + } + j++; + } + + int32_t x_max = (int32_t)x_max_coord + 1; + int32_t y_max = (int32_t)y_max_coord + 1; + int32_t x_min = (int32_t)x_min_coord - 1; + int32_t y_min = (int32_t)y_min_coord - 1; + + x_max = clamp_def(x_max, overlay_x_min, overlay_x_min + overlay_x_max - 1); + y_max = clamp_def(y_max, overlay_y_min, overlay_y_min + overlay_y_max - 1); + x_min = clamp_def(x_min, overlay_x_min, overlay_x_min + overlay_x_max - 1); + y_min = clamp_def(y_min, overlay_y_min, overlay_y_min + overlay_y_max - 1); + + const int32_t width = x_max - x_min + 1; + const int32_t height = y_max - y_min + 1; + if (width * height > 0) { + gl_state_active_texture(7); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x_min, y_min, x_min, y_min, width, height); + } + } + static void draw_sprite_end() { gl_state_disable_blend(); gl_state_active_bind_texture_2d(0, 0); diff --git a/src/CRE/sprite.hpp b/src/CRE/sprite.hpp index 6893b304..d53981d6 100644 --- a/src/CRE/sprite.hpp +++ b/src/CRE/sprite.hpp @@ -169,6 +169,7 @@ namespace spr { mat4 mat; const texture* texture; int32_t shader; + int32_t sprite_draw_param_index; #if BREAK_SPRITE_VERTEX_LIMIT size_t vertex_array; #else @@ -210,7 +211,7 @@ namespace spr { extern void sprite_manager_init(); extern void sprite_manager_add_spr_sets(const sprite_database* spr_db); extern void sprite_manager_clear(); -extern void sprite_manager_draw(int32_t index, bool font, texture* tex, const mat4& vp); +extern void sprite_manager_draw(int32_t index, bool font, texture* overlay_tex, const mat4& vp); extern int32_t sprite_manager_get_index(); extern size_t sprite_manager_get_reqlist_count(int32_t index); extern ::spr_set* sprite_manager_get_set(uint32_t set_id, const sprite_database* spr_db); @@ -222,6 +223,8 @@ extern rectangle sprite_manager_get_spr_rectangle(uint32_t spr_id, const sprite_ extern texture* sprite_manager_get_spr_texture(uint32_t spr_id, const sprite_database* spr_db); extern bool sprite_manager_load_file(uint32_t set_id, const sprite_database* spr_db); extern bool sprite_manager_load_file_modern(uint32_t set_hash, sprite_database* spr_db); +extern void sprite_manager_post_draw(); +extern void sprite_manager_pre_draw(); extern void sprite_manager_read_file(uint32_t set_id, std::string& mdata_dir, void* data, const sprite_database* spr_db); extern void sprite_manager_read_file(uint32_t set_id,