From abeaf8e8d406f79320a0d11f2ecac89717a6efb3 Mon Sep 17 00:00:00 2001 From: korenkonder Date: Sat, 24 May 2025 23:48:30 +0300 Subject: [PATCH] Sprite Draw batching overhaul --- src/AFTModsShared/print_work.cpp | 6 +- src/AFTModsShared/sprite.cpp | 20 +- src/AFTModsShared/sprite.hpp | 21 +- src/DivaGL/data_test/rob_osage_test.cpp | 4 +- src/DivaGL/sprite.cpp | 1099 ++++++++++++----------- 5 files changed, 620 insertions(+), 530 deletions(-) diff --git a/src/AFTModsShared/print_work.cpp b/src/AFTModsShared/print_work.cpp index c6643e0..0937daf 100644 --- a/src/AFTModsShared/print_work.cpp +++ b/src/AFTModsShared/print_work.cpp @@ -141,11 +141,11 @@ void PrintWork::DrawLine(vec2 pos[2]) { } void PrintWork::DrawPolyLine(vec2* points, size_t count) { - spr::put_sprite_line_list(points, count, resolution_mode, prio, color, layer); + spr::put_sprite_poly_line(points, count, resolution_mode, prio, color, layer); } void PrintWork::DrawRectangle(rectangle rect) { - spr::put_sprite_multi(rect, resolution_mode, prio, color, layer); + spr::put_sprite_rect_draw(rect, resolution_mode, prio, color, layer); } void PrintWork::DrawTextMesh(app::text_flags flags, sprite_text_mesh& mesh) { @@ -201,7 +201,7 @@ void PrintWork::FillRectangle(rectangle rect) { rect.size.y = clip_max_pos_y - rect.pos.y; } - spr::put_sprite_rect(rect, resolution_mode, prio, fill_color, layer); + spr::put_sprite_rect_fill(rect, resolution_mode, prio, fill_color, layer); } font_char PrintWork::GetCharData(wchar_t c) { diff --git a/src/AFTModsShared/sprite.cpp b/src/AFTModsShared/sprite.cpp index a439ff3..cfcd659 100644 --- a/src/AFTModsShared/sprite.cpp +++ b/src/AFTModsShared/sprite.cpp @@ -122,7 +122,7 @@ namespace spr { while (args->next) args = args->next; args->next = next; - next->kind = SPR_KIND_LINE; + next->kind = SPR_KIND_CHILD; } vec2 proj_sprite_3d_line(vec3 vec, bool offset) { @@ -159,7 +159,7 @@ namespace spr { args.trans.y = p1.y; args.trans.z = 0.0f; args.layer = layer; - args.kind = SPR_KIND_LINES; + args.kind = SPR_KIND_LINE; args.resolution_mode_screen = mode; args.resolution_mode_sprite = mode; args.prio = prio; @@ -169,10 +169,10 @@ namespace spr { spr::put_sprite(args); } - void put_sprite_line_list(vec2* points, size_t count, resolution_mode mode, + void put_sprite_poly_line(vec2* points, size_t count, resolution_mode mode, spr::SprPrio prio, color4u8 color, int32_t layer) { spr::SprArgs args; - args.kind = SPR_KIND_ARROW_AB; + args.kind = SPR_KIND_POLY_LINE; args.layer = layer; args.resolution_mode_screen = mode; args.resolution_mode_sprite = mode; @@ -192,13 +192,13 @@ namespace spr { spr::put_sprite(args); } - void put_sprite_multi(rectangle rect, resolution_mode mode, spr::SprPrio prio, color4u8 color, int32_t layer) { + void put_sprite_rect_draw(rectangle rect, resolution_mode mode, spr::SprPrio prio, color4u8 color, int32_t layer) { spr::SprArgs args; args.trans.x = rect.pos.x; args.trans.y = rect.pos.y; args.trans.z = 0.0f; args.layer = layer; - args.kind = SPR_KIND_MULTI; + args.kind = SPR_KIND_RECT_DRAW; args.resolution_mode_screen = mode; args.resolution_mode_sprite = mode; args.prio = prio; @@ -208,13 +208,13 @@ namespace spr { spr::put_sprite(args); } - void put_sprite_rect(rectangle rect, resolution_mode mode, spr::SprPrio prio, color4u8 color, int32_t layer) { + void put_sprite_rect_fill(rectangle rect, resolution_mode mode, spr::SprPrio prio, color4u8 color, int32_t layer) { spr::SprArgs args; args.trans.x = rect.pos.x; args.trans.y = rect.pos.y; args.trans.z = 0.0f; args.layer = layer; - args.kind = SPR_KIND_RECT; + args.kind = SPR_KIND_RECT_FILL; args.resolution_mode_screen = mode; args.resolution_mode_sprite = mode; args.prio = prio; @@ -224,11 +224,11 @@ namespace spr { spr::put_sprite(args); } - void put_sprite_triangles(SpriteVertex* vert, size_t num, resolution_mode mode, + void put_sprite_strip(SpriteVertex* vert, size_t num, resolution_mode mode, SprPrio prio, int32_t spr_id, int32_t layer) { spr::SprArgs args; args.layer = layer; - args.kind = SPR_KIND_TRIANGLE; + args.kind = SPR_KIND_STRIP; args.resolution_mode_screen = mode; args.resolution_mode_sprite = mode; args.prio = prio; diff --git a/src/AFTModsShared/sprite.hpp b/src/AFTModsShared/sprite.hpp index 5de9b9e..2cd670e 100644 --- a/src/AFTModsShared/sprite.hpp +++ b/src/AFTModsShared/sprite.hpp @@ -145,15 +145,14 @@ namespace spr { enum SprKind { SPR_KIND_NORMAL = 0, + SPR_KIND_CHILD, SPR_KIND_LINE, + SPR_KIND_RECT_FILL, + SPR_KIND_RECT_DRAW, + SPR_KIND_5, SPR_KIND_LINES, - SPR_KIND_RECT, - SPR_KIND_MULTI, - SPR_KIND_ARROW_A, - SPR_KIND_ARROW_B, - SPR_KIND_ARROW_AB, - SPR_KIND_TRIANGLE, - SPR_KIND_CIRCLE, + SPR_KIND_POLY_LINE, + SPR_KIND_STRIP, }; enum SprPrio { @@ -272,11 +271,11 @@ namespace spr { void put_sprite_3d_line(vec3 p1, vec3 p2, color4u8 color); void put_sprite_line(vec2 p1, vec2 p2, resolution_mode mode, spr::SprPrio prio, color4u8 color, int32_t layer); - void put_sprite_line_list(vec2* points, size_t count, resolution_mode mode, + void put_sprite_poly_line(vec2* points, size_t count, resolution_mode mode, spr::SprPrio prio, color4u8 color, int32_t layer); - void put_sprite_multi(rectangle rect, resolution_mode mode, spr::SprPrio prio, color4u8 color, int32_t layer); - void put_sprite_rect(rectangle rect, resolution_mode mode, spr::SprPrio prio, color4u8 color, int32_t layer); - void put_sprite_triangles(SpriteVertex* vert, size_t num, resolution_mode mode, + void put_sprite_rect_draw(rectangle rect, resolution_mode mode, spr::SprPrio prio, color4u8 color, int32_t layer); + void put_sprite_rect_fill(rectangle rect, resolution_mode mode, spr::SprPrio prio, color4u8 color, int32_t layer); + void put_sprite_strip(SpriteVertex* vert, size_t num, resolution_mode mode, SprPrio prio, int32_t spr_id, int32_t layer); } diff --git a/src/DivaGL/data_test/rob_osage_test.cpp b/src/DivaGL/data_test/rob_osage_test.cpp index 0739a04..fff2abc 100644 --- a/src/DivaGL/data_test/rob_osage_test.cpp +++ b/src/DivaGL/data_test/rob_osage_test.cpp @@ -1205,7 +1205,7 @@ void RobOsageTest::disp_line() { spr::put_sprite_3d_line(j[-1].pos, j[0].pos, line_color); for (const RobOsageNode* j = j_begin; j != j_end; j++) - spr::put_sprite_rect({ spr::proj_sprite_3d_line(j->pos, true) - 2.0f, 4.0f }, + spr::put_sprite_rect_fill({ spr::proj_sprite_3d_line(j->pos, true) - 2.0f, 4.0f }, RESOLUTION_MODE_MAX, spr::SPR_PRIO_DEBUG, rect_color, 0); mat4_transpose(i->rob.end_node.bone_node_mat, &mat); @@ -1293,7 +1293,7 @@ void RobOsageTest::disp_line_cls_param(const mat4& transform, const vec3& pos) { mat4_get_translation(&transform, &p_node); spr::put_sprite_3d_line(p, p_node, color_grey); - spr::put_sprite_rect({ spr::proj_sprite_3d_line(p, true) - 1.0f, 2.0f }, + spr::put_sprite_rect_fill({ spr::proj_sprite_3d_line(p, true) - 1.0f, 2.0f }, RESOLUTION_MODE_MAX, spr::SPR_PRIO_DEBUG, color_yellow, 0); } diff --git a/src/DivaGL/sprite.cpp b/src/DivaGL/sprite.cpp index 382f65c..f05ef2e 100644 --- a/src/DivaGL/sprite.cpp +++ b/src/DivaGL/sprite.cpp @@ -9,17 +9,29 @@ #include "shader_ft.hpp" #include -struct sprite_draw_vertex { +struct sprite_vertex_data_uv0 { vec3 pos; - vec2 uv[2]; color4u8 color; }; +struct sprite_vertex_data_uv1 { + vec3 pos; + color4u8 color; + vec2 uv; +}; + +struct sprite_vertex_data_uv2 { + vec3 pos; + color4u8 color; + vec2 uv[2]; +}; + struct sprite_draw_param_attrib_member { uint32_t primitive : 4; uint32_t enable_blend : 1; uint32_t blend : 3; uint32_t sampler : 2; + uint32_t vao : 2; }; union sprite_draw_param_attrib { @@ -44,7 +56,7 @@ struct sprite_draw_param { }; namespace spr { - struct SprArgsInner { + struct SprArgsDraw { int32_t num_texture; int32_t blend; const texture* textures[4]; @@ -60,6 +72,10 @@ namespace spr { inline UV() : u(), v() { } + + inline operator vec2() const { + return { u, v }; + } }; UV uv[4]; @@ -82,9 +98,9 @@ namespace spr { struct SpriteManager { struct RenderData { std::vector draw_param_buffer; - std::vector vertex_buffer; + std::vector vertex_buffer; std::vector index_buffer; - GLuint vao; + GLuint vao[3]; GL::ArrayBuffer vbo; size_t vbo_vertex_count; GL::ElementArrayBuffer ebo; @@ -93,6 +109,8 @@ namespace spr { RenderData(); ~RenderData(); + template + size_t AddData(T*& data, size_t num_vertex); void Clear(); void Update(); }; @@ -119,17 +137,17 @@ namespace spr { static_assert(sizeof(spr::SpriteManager) == 0x10C8, "\"spr::SpriteManager\" struct should have a size of 0x10C8"); - 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 calc_sprite_vertex(spr::SprArgs* args, vec3 vtx[4], mat4* mat, bool font); + static int32_t calc_sprite_texture_param(SprArgs* args, spr::TexParam* param, vec3 vtx[4], bool font); + static int32_t calc_sprite_vertex_texture_param(SprArgs& args, vec3 vtx[4], spr::TexParam* param, bool font); - 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 add_draw_sprite(SprArgs* args_array[0x100], const int32_t args_count, bool font, + SprArgsDraw& args_draw, SpriteManager::RenderData& render_data); static void draw_sprite(render_data_context& rend_data_ctx, 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_data_context& rend_data_ctx); static void draw_sprite_copy_overlay_texture( - render_data_context& rend_data_ctx, const SprArgs& args, const mat4& mat, const vec3* vtx, + render_data_context& rend_data_ctx, const SprArgs& args, const mat4& mat, const vec3 vtx[4], 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(render_data_context& rend_data_ctx); static void draw_sprite_scale(spr::SprArgs* args); @@ -154,31 +172,56 @@ static const GLenum spr_blend_param[6][4] = { namespace spr { SpriteManager::RenderData::RenderData() : vao() { - glGenVertexArrays(1, &vao); - gl_state.bind_vertex_array(vao); - vbo_vertex_count = 4096; - - static const GLsizei buffer_size = sizeof(sprite_draw_vertex); - - vbo.Create(gl_state, buffer_size * vbo_vertex_count); - gl_state.bind_array_buffer(vbo, true); - - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, buffer_size, - (void*)offsetof(sprite_draw_vertex, pos)); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, buffer_size, - (void*)offsetof(sprite_draw_vertex, color)); - glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, buffer_size, - (void*)offsetof(sprite_draw_vertex, uv)); - ebo_index_count = 4096; + static const GLsizei buffer_size_uv0 = sizeof(sprite_vertex_data_uv0); + static const GLsizei buffer_size_uv1 = sizeof(sprite_vertex_data_uv1); + static const GLsizei buffer_size_uv2 = sizeof(sprite_vertex_data_uv2); + + vbo.Create(gl_state, buffer_size_uv2 * vbo_vertex_count); ebo.Create(gl_state, sizeof(uint32_t) * ebo_index_count); + + glGenVertexArrays(3, vao); + gl_state.bind_vertex_array(vao[0]); + gl_state.bind_array_buffer(vbo, true); gl_state.bind_element_array_buffer(ebo, true); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, buffer_size_uv0, + (void*)offsetof(sprite_vertex_data_uv0, pos)); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, buffer_size_uv0, + (void*)offsetof(sprite_vertex_data_uv0, color)); + + gl_state.bind_vertex_array(vao[1]); + gl_state.bind_array_buffer(vbo, true); + gl_state.bind_element_array_buffer(ebo, true); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, buffer_size_uv1, + (void*)offsetof(sprite_vertex_data_uv1, pos)); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, buffer_size_uv1, + (void*)offsetof(sprite_vertex_data_uv1, color)); + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, buffer_size_uv1, + (void*)offsetof(sprite_vertex_data_uv1, uv)); + + gl_state.bind_vertex_array(vao[2]); + gl_state.bind_array_buffer(vbo, true); + gl_state.bind_element_array_buffer(ebo, true); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, buffer_size_uv2, + (void*)offsetof(sprite_vertex_data_uv2, pos)); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, buffer_size_uv2, + (void*)offsetof(sprite_vertex_data_uv2, color)); + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, buffer_size_uv2, + (void*)offsetof(sprite_vertex_data_uv2, uv)); + gl_state.bind_array_buffer(0); gl_state.bind_vertex_array(0); gl_state.bind_element_array_buffer(0); @@ -188,12 +231,24 @@ namespace spr { ebo.Destroy(); vbo.Destroy(); - if (vao) { - glDeleteVertexArrays(1, &vao); - vao = 0; + if (vao[0]) { + glDeleteVertexArrays(3, vao); + vao[0] = 0; } } + template + size_t SpriteManager::RenderData::AddData(T*& data, size_t num_vertex) { + size_t size = vertex_buffer.size(); + size_t align_offset = (sizeof(T) - size % sizeof(T)) % sizeof(T); + size_t vertex_array_size = sizeof(T) * num_vertex; + + vertex_buffer.resize(size + align_offset + vertex_array_size); + T* vtx_data = (T*)(vertex_buffer.data() + size + align_offset); + data = vtx_data; + return (uint32_t)((size + align_offset) / sizeof(T)); + } + void SpriteManager::RenderData::Clear() { draw_param_buffer.clear(); vertex_buffer.clear(); @@ -201,73 +256,96 @@ namespace spr { } void SpriteManager::RenderData::Update() { - static const GLsizei buffer_size = sizeof(sprite_draw_vertex); + static const GLsizei buffer_size_uv0 = sizeof(sprite_vertex_data_uv0); + static const GLsizei buffer_size_uv1 = sizeof(sprite_vertex_data_uv1); + static const GLsizei buffer_size_uv2 = sizeof(sprite_vertex_data_uv2); - if (vbo_vertex_count < vertex_buffer.size()) { + if (vbo_vertex_count < vertex_buffer.size() / sizeof(sprite_vertex_data_uv2)) { while (vbo_vertex_count < vertex_buffer.size()) vbo_vertex_count *= 2; - gl_state.bind_vertex_array(vao); if (DIVA_GL_VERSION_4_4) { vbo.Destroy(); - vbo.Create(gl_state, buffer_size * vbo_vertex_count); + vbo.Create(gl_state, buffer_size_uv2 * vbo_vertex_count); gl_state.bind_array_buffer(vbo, true); - - glBufferSubData(GL_ARRAY_BUFFER, 0, (GLsizeiptr)(buffer_size - * vertex_buffer.size()), vertex_buffer.data()); } else { gl_state.bind_array_buffer(vbo, true); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(buffer_size - * vbo_vertex_count), 0, GL_DYNAMIC_DRAW); - glBufferSubData(GL_ARRAY_BUFFER, 0, (GLsizeiptr)(buffer_size - * vertex_buffer.size()), vertex_buffer.data()); + glBufferData(GL_ARRAY_BUFFER, + (GLsizeiptr)vbo_vertex_count, 0, GL_DYNAMIC_DRAW); } + gl_state.bind_vertex_array(vao[0]); + gl_state.bind_array_buffer(vbo, true); + glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, buffer_size, - (void*)offsetof(sprite_draw_vertex, pos)); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, buffer_size_uv0, + (void*)offsetof(sprite_vertex_data_uv0, pos)); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, buffer_size, - (void*)offsetof(sprite_draw_vertex, color)); + glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, buffer_size_uv0, + (void*)offsetof(sprite_vertex_data_uv0, color)); + + gl_state.bind_vertex_array(vao[1]); + gl_state.bind_array_buffer(vbo, true); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, buffer_size_uv1, + (void*)offsetof(sprite_vertex_data_uv1, pos)); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, buffer_size_uv1, + (void*)offsetof(sprite_vertex_data_uv1, color)); glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, buffer_size, - (void*)offsetof(sprite_draw_vertex, uv)); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, buffer_size_uv1, + (void*)offsetof(sprite_vertex_data_uv1, uv)); + + gl_state.bind_vertex_array(vao[2]); + gl_state.bind_array_buffer(vbo, true); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, buffer_size_uv2, + (void*)offsetof(sprite_vertex_data_uv2, pos)); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, buffer_size_uv2, + (void*)offsetof(sprite_vertex_data_uv2, color)); + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, buffer_size_uv2, + (void*)offsetof(sprite_vertex_data_uv2, uv)); gl_state.bind_array_buffer(0); gl_state.bind_vertex_array(0); } - else - vbo.WriteMemory(gl_state, 0, buffer_size * vertex_buffer.size(), vertex_buffer.data()); + + vbo.WriteMemory(gl_state, 0, vertex_buffer.size(), vertex_buffer.data()); if (ebo_index_count < index_buffer.size()) { while (ebo_index_count < index_buffer.size()) ebo_index_count *= 2; - gl_state.bind_vertex_array(vao); if (DIVA_GL_VERSION_4_4) { ebo.Destroy(); ebo.Create(gl_state, sizeof(uint32_t) * ebo_index_count); gl_state.bind_element_array_buffer(ebo, true); - - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, (GLsizeiptr)(sizeof(uint32_t) - * index_buffer.size()), index_buffer.data()); } else { - gl_state.bind_array_buffer(vbo, true); + gl_state.bind_element_array_buffer(ebo, true); glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(sizeof(uint32_t) * ebo_index_count), 0, GL_DYNAMIC_DRAW); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, (GLsizeiptr)(sizeof(uint32_t) - * index_buffer.size()), index_buffer.data()); } + gl_state.bind_vertex_array(vao[0]); + gl_state.bind_element_array_buffer(ebo, true); + gl_state.bind_vertex_array(vao[1]); + gl_state.bind_element_array_buffer(ebo, true); + gl_state.bind_vertex_array(vao[2]); + gl_state.bind_element_array_buffer(ebo, true); + gl_state.bind_vertex_array(0); gl_state.bind_element_array_buffer(0); } - else - ebo.WriteMemory(gl_state, 0, sizeof(uint32_t) * index_buffer.size(), index_buffer.data()); + + ebo.WriteMemory(gl_state, 0, sizeof(uint32_t) * index_buffer.size(), index_buffer.data()); } void SpriteManager::Draw(render_data_context& rend_data_ctx, @@ -365,7 +443,6 @@ namespace spr { RenderData& render_data = *sprite_manager_render_data; - rend_data_ctx.state.bind_vertex_array(render_data.vao); for (uint32_t j = SPR_PRIO_MAX; j; j--, reqlist++) for (auto& k : *reqlist) if (k.sprite_draw_param_index >= 0) @@ -384,7 +461,7 @@ namespace spr { } void SpriteManager::PreDraw() { - auto check_same = [](const SprArgsInner& left, const SprArgsInner& right) -> bool { + auto check_same = [](const SprArgsDraw& left, const SprArgsDraw& right) -> bool { if (left.num_texture != right.num_texture) return false; @@ -394,61 +471,60 @@ namespace spr { 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; + && left.kind != SPR_KIND_RECT_DRAW && right.kind != SPR_KIND_RECT_DRAW + && left.kind != SPR_KIND_POLY_LINE && right.kind != SPR_KIND_POLY_LINE + && left.kind != SPR_KIND_STRIP && right.kind != SPR_KIND_STRIP; }; - auto get_num_vertex = [](const SprArgs& args, SprArgsInner& args_inner) { + auto get_args_draw = [](const SprArgs& args, SprArgsDraw& args_draw) { int32_t num_texture = 0; if (args.texture) { const spr::SprArgs* _args = &args; while (_args) { - args_inner.textures[num_texture++] = _args->texture; + args_draw.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; + args_draw.num_texture = num_texture; + args_draw.blend = args.blend; + args_draw.shader = args.shader; + args_draw.kind = args.kind; }; RenderData& render_data = *sprite_manager_render_data; - SprArgsInner args_inner[2]; + SprArgsDraw args_draw[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; + int32_t draw_idx = 0; for (SprArgs& args : reqlist[i][j][k]) { if (!args_count) { - get_num_vertex(args, args_inner[inner_idx]); + get_args_draw(args, args_draw[draw_idx]); args_array[args_count++] = &args; - inner_idx = 1 - inner_idx; + draw_idx = 1 - draw_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_draw[1 - draw_idx], render_data); + get_args_draw(args, args_draw[draw_idx]); args_count = 0; args_array[args_count++] = &args; - inner_idx = 1 - inner_idx; + draw_idx = 1 - draw_idx; } else { - get_num_vertex(args, args_inner[inner_idx]); - if (!check_same(args_inner[1 - inner_idx], args_inner[inner_idx])) { + get_args_draw(args, args_draw[draw_idx]); + if (!check_same(args_draw[1 - draw_idx], args_draw[draw_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_draw[1 - draw_idx], render_data); args_count = 0; - inner_idx = 1 - inner_idx; + draw_idx = 1 - draw_idx; } args_array[args_count++] = &args; } @@ -456,14 +532,13 @@ namespace spr { 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); + args_draw[1 - draw_idx], render_data); } render_data.Update(); } - static void calc_sprite_vertex(spr::SprArgs* args, vec3* vtx, mat4* mat, bool font) { + static void calc_sprite_vertex(spr::SprArgs* args, vec3 vtx[4], mat4* mat, bool font) { vtx[0].x = 0.0f; vtx[0].y = 0.0f; vtx[1].x = 0.0f; @@ -580,7 +655,7 @@ namespace spr { *mat = m; } - static int32_t calc_sprite_texture_param(SprArgs* args, spr::TexParam* param, vec3* vtx, bool font) { + static int32_t calc_sprite_texture_param(SprArgs* args, spr::TexParam* param, vec3 vtx[4], bool font) { int32_t tex_param_count = 0; texture* tex = args->texture; while (args) { @@ -597,7 +672,7 @@ namespace spr { vec2 uv01; vec2 uv10; vec2 uv11; - if (args->kind == SPR_KIND_LINE) { + if (args->kind == SPR_KIND_CHILD) { vec3 v42[4]; mat4 mat; calc_sprite_vertex(args, v42, &mat, font); @@ -647,459 +722,474 @@ namespace spr { return tex_param_count; } - 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) { - for (int32_t i = 0; i < count; i++) { - SprArgs& args = *args_array[i]; + static int32_t calc_sprite_vertex_texture_param(SprArgs& args, vec3 vtx[4], spr::TexParam* param, bool font) { + vec3 _vtx[4] = {}; + if (args.flags & SprArgs::SPRITE_SIZE) + calc_sprite_vertex(&args, _vtx, 0, font); - if (args.kind == SPR_KIND_LINE) - continue; + int32_t tex_param_count = 0; + if ((args.flags & SprArgs::TEXTURE_POS_SIZE) && args.texture) + tex_param_count = calc_sprite_texture_param(&args, param, _vtx, font); + vtx[0] = _vtx[0]; + vtx[1] = _vtx[1]; + vtx[2] = _vtx[2]; + vtx[3] = _vtx[3]; + return tex_param_count; + } - const color4u8 color = args.color; + static void add_draw_sprite(SprArgs* args_array[0x100], const int32_t args_count, bool font, + SprArgsDraw& args_draw, SpriteManager::RenderData& render_data) { + SprArgs& args = *args_array[0]; + if (args.kind == SPR_KIND_CHILD) + return; - 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 spr_vtx[4] = {}; + spr::TexParam tex_param[4] = {}; + calc_sprite_vertex_texture_param(args, spr_vtx, tex_param, font); - 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); - } + std::vector& draw_param_buffer = render_data.draw_param_buffer; + std::vector& index_buffer = render_data.index_buffer; - draw_param_buffer.push_back({}); - sprite_draw_param& draw_param = draw_param_buffer.back(); + 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; - } + 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_draw.blend; + } - draw_param.shader = shader_ft_shader_name_map_table[args.shader]; - if (draw_param.shader == SHADER_FT_FFP) - draw_param.shader = SHADER_FT_SPRITE; + draw_param.shader = shader_ft_shader_name_map_table[args_draw.shader]; + if (draw_param.shader == SHADER_FT_FFP) + draw_param.shader = SHADER_FT_SPRITE; - 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(); - continue; - } + switch (args_draw.num_texture) { + case 0: + draw_param.attrib.m.vao = 0; + switch (args_draw.kind) { + case SPR_KIND_LINE: { + sprite_vertex_data_uv0* vtx_data = 0; + size_t count = 2ULL * args_count; + size_t first = render_data.AddData(vtx_data, count); - sprite_draw_vertex spr_vtx[2] = {}; - spr_vtx[0].pos = vtx[0]; - spr_vtx[0].color = color; + draw_param.attrib.m.primitive = GL_LINES; + draw_param.first = (GLint)first; + draw_param.count = (GLint)count; - spr_vtx[1].pos = vtx[2]; - spr_vtx[1].color = color; + vtx_data[0] = { spr_vtx[0], color }; + vtx_data[1] = { spr_vtx[2], color }; + vtx_data += 2; + + for (int32_t i = 1; i < args_count; i++) { + SprArgs& args = *args_array[i]; + + const color4u8 color = args.color; + + if (font) + draw_sprite_scale(&args); + + calc_sprite_vertex_texture_param(args, spr_vtx, tex_param, font); + + vtx_data[0] = { spr_vtx[0], color }; + vtx_data[1] = { spr_vtx[2], color }; + vtx_data += 2; + } + } break; + case SPR_KIND_RECT_FILL: { + sprite_vertex_data_uv0* vtx_data = 0; + size_t vtx_count = 4ULL * args_count; + size_t idx_count = 6ULL * args_count; + size_t start = render_data.AddData(vtx_data, vtx_count); + index_buffer.reserve(idx_count); + + draw_param.attrib.m.primitive = GL_TRIANGLES; + draw_param.start = (GLuint)start; + draw_param.end = (GLuint)(start + vtx_count - 1); + draw_param.count = (GLsizei)idx_count; + draw_param.offset = (GLintptr)(index_buffer.size() * sizeof(uint32_t)); + + vtx_data[0] = { spr_vtx[0], color }; // LB + vtx_data[1] = { spr_vtx[1], color }; // LT + vtx_data[2] = { spr_vtx[2], color }; // RT + vtx_data[3] = { spr_vtx[3], color }; // RB + vtx_data += 4; + + index_buffer.push_back((uint32_t)(start + 0)); // LB + index_buffer.push_back((uint32_t)(start + 1)); // LT + index_buffer.push_back((uint32_t)(start + 3)); // RB + index_buffer.push_back((uint32_t)(start + 1)); // LT + index_buffer.push_back((uint32_t)(start + 2)); // RT + index_buffer.push_back((uint32_t)(start + 3)); // RB + start += 4; + + for (int32_t i = 1; i < args_count; i++) { + SprArgs& args = *args_array[i]; + + const color4u8 color = args.color; + + if (font) + draw_sprite_scale(&args); + + calc_sprite_vertex_texture_param(args, spr_vtx, tex_param, font); + + vtx_data[0] = { spr_vtx[0], color }; // LB + vtx_data[1] = { spr_vtx[1], color }; // LT + vtx_data[2] = { spr_vtx[2], color }; // RT + vtx_data[3] = { spr_vtx[3], color }; // RB + vtx_data += 4; + + index_buffer.push_back((uint32_t)(start + 0)); // LB + index_buffer.push_back((uint32_t)(start + 1)); // LT + index_buffer.push_back((uint32_t)(start + 3)); // RB + index_buffer.push_back((uint32_t)(start + 1)); // LT + index_buffer.push_back((uint32_t)(start + 2)); // RT + index_buffer.push_back((uint32_t)(start + 3)); // RB + start += 4; + } + } break; + case SPR_KIND_RECT_DRAW: { + sprite_vertex_data_uv0* vtx_data = 0; + size_t count = 5; + size_t first = render_data.AddData(vtx_data, count); + + draw_param.attrib.m.primitive = GL_LINE_STRIP; + draw_param.first = (GLint)first; + draw_param.count = (GLsizei)count; + + vtx_data[0] = { spr_vtx[0], color }; + vtx_data[1] = { spr_vtx[1], color }; + vtx_data[2] = { spr_vtx[2], color }; + vtx_data[3] = { spr_vtx[3], color }; + vtx_data[4] = { spr_vtx[0], color }; + + } break; + case SPR_KIND_LINES: { + if (args.num_vertex) { + sprite_vertex_data_uv0* vtx_data = 0; + size_t count = args.num_vertex & ~0x01; + size_t first = render_data.AddData(vtx_data, count); 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_RECT: { - 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_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_STRIP; - draw_param.first = (GLint)vertex_buffer.size(); - draw_param.count = 5; - - vertex_buffer.reserve(5); - 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]); - vertex_buffer.push_back(spr_vtx[0]); - } 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); - - SpriteVertex* vtx = args.GetVertexArray(); - 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(); - continue; - } - } - else { - if (vtx[0] == 0.0f && vtx[2] == 0.0f) { - draw_param_buffer.pop_back(); - continue; - } - - spr_vtx[0].pos = vtx[0]; - spr_vtx[1].pos = vtx[2]; - - 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(); - continue; - } - - 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; + draw_param.first = (GLint)first; + draw_param.count = (GLsizei)count; SpriteVertex* vtx = args.GetVertexArray(); - 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(); - continue; - } - - 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 = {}; - - SpriteVertex* vtx = args.GetVertexArray(); - for (size_t i = args.num_vertex; i; i--, vtx++) { - spr_vtx.pos = vtx->pos; - spr_vtx.color = vtx->color; - 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 (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 = {}; - - SpriteVertex* vtx = args.GetVertexArray(); - 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] = {}; - - SpriteVertex* vtx = args.GetVertexArray(); - 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; - } + for (size_t i = args.num_vertex / 2; i; i--, vtx += 2, vtx_data += 2) { + vtx_data[0] = { vtx[0].pos, color }; + vtx_data[1] = { vtx[1].pos, color }; } } 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_vertex_data_uv0* vtx_data = 0; + size_t count = 2; + size_t first = render_data.AddData(vtx_data, count); + + draw_param.attrib.m.primitive = GL_LINES; + draw_param.first = (GLint)first; + draw_param.count = (GLsizei)count; + + vtx_data[0] = { spr_vtx[0], color }; + vtx_data[1] = { spr_vtx[2], color }; + } + + for (int32_t i = 1; i < args_count; i++) { + SprArgs& args = *args_array[i]; + + const color4u8 color = args.color; + + if (font) + draw_sprite_scale(&args); + + calc_sprite_vertex_texture_param(args, spr_vtx, tex_param, font); + + if (args.num_vertex) { + sprite_vertex_data_uv0* vtx_data = 0; + size_t count = args.num_vertex & ~0x01; + render_data.AddData(vtx_data, count); + + draw_param.count += (GLsizei)count; + + SpriteVertex* vtx = args.GetVertexArray(); + for (size_t i = args.num_vertex / 2; i; i--, vtx += 2, vtx_data += 2) { + vtx_data[0] = { vtx[0].pos, color }; + vtx_data[1] = { vtx[1].pos, color }; + } } + else { + sprite_vertex_data_uv0* vtx_data = 0; + size_t count = 2; + render_data.AddData(vtx_data, count); - 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; + draw_param.count += (GLsizei)count; - 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; + vtx_data[0] = { spr_vtx[0], color }; + vtx_data[1] = { spr_vtx[2], 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(); - continue; + } } + } break; + case SPR_KIND_POLY_LINE: { + sprite_vertex_data_uv0* vtx_data = 0; + size_t count = args.num_vertex; + size_t first = render_data.AddData(vtx_data, count); - draw_param.textures[0] = tex_param[0].texture; - draw_param.textures[1] = tex_param[1].texture; - draw_param.attrib.m.sampler = 2; + draw_param.attrib.m.primitive = GL_LINE_STRIP; + draw_param.first = (GLint)first; + draw_param.count = (GLsizei)count; - 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; + SpriteVertex* vtx = args.GetVertexArray(); + for (size_t i = args.num_vertex; i; i--, vtx++, vtx_data++) + *vtx_data = { vtx->pos, color }; + } break; + case SPR_KIND_STRIP: { + sprite_vertex_data_uv0* vtx_data = 0; + size_t count = args.num_vertex; + size_t first = render_data.AddData(vtx_data, count); - 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; + draw_param.attrib.m.primitive = GL_TRIANGLE_STRIP; + draw_param.first = (GLint)first; + draw_param.count = (GLsizei)count; - 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; + SpriteVertex* vtx = args.GetVertexArray(); + for (size_t i = args.num_vertex; i; i--, vtx++, vtx_data++) + *vtx_data = { vtx->pos, vtx->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.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; } + break; + case 1: + draw_param.textures[0] = tex_param[0].texture; + draw_param.attrib.m.sampler = 0; + draw_param.attrib.m.vao = 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]; + if (args.num_vertex) { + if (args_draw.kind == SPR_KIND_STRIP) { + draw_param.attrib.m.sampler = 1; - 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(); + sprite_vertex_data_uv1* vtx_data = 0; + size_t count = args.num_vertex; + size_t first = render_data.AddData(vtx_data, count); + + draw_param.attrib.m.primitive = GL_TRIANGLE_STRIP; + draw_param.first = (GLint)first; + draw_param.count = (GLsizei)count; + + SpriteVertex* vtx = args.GetVertexArray(); + for (size_t i = args.num_vertex; i; i--, vtx++, vtx_data++) + *vtx_data = { vtx->pos, vtx->color, vtx->uv }; } - else if (draw_param_1.attrib.m.primitive == GL_LINES - && 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.first + draw_param_2.count == draw_param_1.first) { - draw_param_2.count += draw_param_1.count; - draw_param_buffer.pop_back(); + else { + sprite_vertex_data_uv1* vtx_data = 0; + size_t vtx_count = args.num_vertex; + size_t idx_count = args.num_vertex / 4 * 6; + size_t start = render_data.AddData(vtx_data, vtx_count); + index_buffer.reserve(idx_count); + + draw_param.attrib.m.primitive = GL_TRIANGLES; + draw_param.start = (GLuint)start; + draw_param.end = (GLuint)(start + vtx_count - 1); + draw_param.count = (GLsizei)idx_count; + draw_param.offset = (GLintptr)(index_buffer.size() * sizeof(uint32_t)); + + SpriteVertex* vtx = args.GetVertexArray(); + for (size_t i = args.num_vertex / 4, j = 0; i; i--, j += 4, vtx += 4) { + vtx_data[0] = { vtx[0].pos, vtx[0].color, vtx[0].uv }; // LB + vtx_data[1] = { vtx[1].pos, vtx[1].color, vtx[1].uv }; // LT + vtx_data[2] = { vtx[2].pos, vtx[2].color, vtx[2].uv }; // RT + vtx_data[3] = { vtx[3].pos, vtx[3].color, vtx[3].uv }; // RB + vtx_data += 4; + + index_buffer.push_back((uint32_t)(start + j + 0)); // LB + index_buffer.push_back((uint32_t)(start + j + 1)); // LT + index_buffer.push_back((uint32_t)(start + j + 3)); // RB + index_buffer.push_back((uint32_t)(start + j + 1)); // LT + index_buffer.push_back((uint32_t)(start + j + 2)); // RT + index_buffer.push_back((uint32_t)(start + j + 3)); // RB + } + start += args.num_vertex; + + for (int32_t i = 1; i < args_count; i++) { + SprArgs& args = *args_array[i]; + + size_t vtx_count = args.num_vertex; + size_t idx_count = args.num_vertex / 4 * 6; + + draw_param.end += (GLuint)vtx_count; + draw_param.count += (GLsizei)idx_count; + + render_data.AddData(vtx_data, vtx_count); + index_buffer.reserve(idx_count); + + if (font) + draw_sprite_scale(&args); + + calc_sprite_vertex_texture_param(args, spr_vtx, tex_param, font); + + SpriteVertex* vtx = args.GetVertexArray(); + for (size_t i = args.num_vertex / 4, j = 0; i; i--, j += 4, vtx += 4) { + + vtx_data[0] = { vtx[0].pos, vtx[0].color, vtx[0].uv }; // LB + vtx_data[1] = { vtx[1].pos, vtx[1].color, vtx[1].uv }; // LT + vtx_data[2] = { vtx[2].pos, vtx[2].color, vtx[2].uv }; // RT + vtx_data[3] = { vtx[3].pos, vtx[3].color, vtx[3].uv }; // RB + vtx_data += 4; + + index_buffer.push_back((uint32_t)(start + j + 0)); // LB + index_buffer.push_back((uint32_t)(start + j + 1)); // LT + index_buffer.push_back((uint32_t)(start + j + 3)); // RB + index_buffer.push_back((uint32_t)(start + j + 1)); // LT + index_buffer.push_back((uint32_t)(start + j + 2)); // RT + index_buffer.push_back((uint32_t)(start + j + 3)); // RB + } + start += args.num_vertex; + } } } + else { + sprite_vertex_data_uv1* vtx_data = 0; + size_t vtx_count = 4ULL * args_count; + size_t idx_count = 6ULL * args_count; + size_t start = render_data.AddData(vtx_data, vtx_count); + index_buffer.reserve(idx_count); + + draw_param.attrib.m.primitive = GL_TRIANGLES; + draw_param.start = (GLuint)start; + draw_param.end = (GLuint)(start + vtx_count - 1); + draw_param.count = (GLsizei)idx_count; + draw_param.offset = (GLintptr)(index_buffer.size() * sizeof(uint32_t)); + + vtx_data[0] = { spr_vtx[0], color, tex_param[0].texcoord.uv[0] }; // LB + vtx_data[1] = { spr_vtx[1], color, tex_param[0].texcoord.uv[1] }; // LT + vtx_data[2] = { spr_vtx[2], color, tex_param[0].texcoord.uv[2] }; // RT + vtx_data[3] = { spr_vtx[3], color, tex_param[0].texcoord.uv[3] }; // RB + vtx_data += 4; + + index_buffer.push_back((uint32_t)(start + 0)); // LB + index_buffer.push_back((uint32_t)(start + 1)); // LT + index_buffer.push_back((uint32_t)(start + 3)); // RB + index_buffer.push_back((uint32_t)(start + 1)); // LT + index_buffer.push_back((uint32_t)(start + 2)); // RT + index_buffer.push_back((uint32_t)(start + 3)); // RB + start += 4; + + for (int32_t i = 1; i < args_count; i++) { + SprArgs& args = *args_array[i]; + + const color4u8 color = args.color; + + if (font) + draw_sprite_scale(&args); + + calc_sprite_vertex_texture_param(args, spr_vtx, tex_param, font); + + vtx_data[0] = { spr_vtx[0], color, tex_param[0].texcoord.uv[0] }; // LB + vtx_data[1] = { spr_vtx[1], color, tex_param[0].texcoord.uv[1] }; // LT + vtx_data[2] = { spr_vtx[2], color, tex_param[0].texcoord.uv[2] }; // RT + vtx_data[3] = { spr_vtx[3], color, tex_param[0].texcoord.uv[3] }; // RB + vtx_data += 4; + + index_buffer.push_back((uint32_t)(start + 0)); // LB + index_buffer.push_back((uint32_t)(start + 1)); // LT + index_buffer.push_back((uint32_t)(start + 3)); // RB + index_buffer.push_back((uint32_t)(start + 1)); // LT + index_buffer.push_back((uint32_t)(start + 2)); // RT + index_buffer.push_back((uint32_t)(start + 3)); // RB + start += 4; + } + } + break; + case 2: { + draw_param.textures[0] = tex_param[0].texture; + draw_param.textures[1] = tex_param[1].texture; + draw_param.attrib.m.sampler = 2; + draw_param.attrib.m.vao = 2; + + sprite_vertex_data_uv2* vtx_data = 0; + size_t vtx_count = 4ULL * args_count; + size_t idx_count = 6ULL * args_count; + size_t start = render_data.AddData(vtx_data, vtx_count); + index_buffer.reserve(idx_count); + + draw_param.attrib.m.primitive = GL_TRIANGLES; + draw_param.start = (GLuint)start; + draw_param.end = (GLuint)(start + vtx_count - 1); + draw_param.count = (GLsizei)idx_count; + draw_param.offset = (GLintptr)(index_buffer.size() * sizeof(uint32_t)); + + vtx_data[0] = { spr_vtx[0], color, + tex_param[0].texcoord.uv[0], tex_param[1].texcoord.uv[0] }; // LB + vtx_data[1] = { spr_vtx[1], color, + tex_param[0].texcoord.uv[1], tex_param[1].texcoord.uv[1] }; // LT + vtx_data[2] = { spr_vtx[2], color, + tex_param[0].texcoord.uv[2], tex_param[1].texcoord.uv[2] }; // RT + vtx_data[3] = { spr_vtx[3], color, + tex_param[0].texcoord.uv[3], tex_param[1].texcoord.uv[3] }; // RB + vtx_data += 4; + + index_buffer.push_back((uint32_t)(start + 0)); // LB + index_buffer.push_back((uint32_t)(start + 1)); // LT + index_buffer.push_back((uint32_t)(start + 3)); // RB + index_buffer.push_back((uint32_t)(start + 1)); // LT + index_buffer.push_back((uint32_t)(start + 2)); // RT + index_buffer.push_back((uint32_t)(start + 3)); // RB + start += 4; + + for (int32_t i = 1; i < args_count; i++) { + SprArgs& args = *args_array[i]; + + const color4u8 color = args.color; + + if (font) + draw_sprite_scale(&args); + + calc_sprite_vertex_texture_param(args, spr_vtx, tex_param, font); + + vtx_data[0] = { spr_vtx[0], color, + tex_param[0].texcoord.uv[0], tex_param[1].texcoord.uv[0] }; // LB + vtx_data[1] = { spr_vtx[1], color, + tex_param[0].texcoord.uv[1], tex_param[1].texcoord.uv[1] }; // LT + vtx_data[2] = { spr_vtx[2], color, + tex_param[0].texcoord.uv[2], tex_param[1].texcoord.uv[2] }; // RT + vtx_data[3] = { spr_vtx[3], color, + tex_param[0].texcoord.uv[3], tex_param[1].texcoord.uv[3] }; // RB + vtx_data += 4; + + index_buffer.push_back((uint32_t)(start + 0)); // LB + index_buffer.push_back((uint32_t)(start + 1)); // LT + index_buffer.push_back((uint32_t)(start + 3)); // RB + index_buffer.push_back((uint32_t)(start + 1)); // LT + index_buffer.push_back((uint32_t)(start + 2)); // RT + index_buffer.push_back((uint32_t)(start + 3)); // RB + start += 4; + } + } break; + } + + if (!draw_param.count) { + draw_param_buffer.pop_back(); + + args.sprite_draw_param_index = -1; + } + else { + if (args_draw.blend == 5) { + draw_param.vtx[0] = spr_vtx[0]; + draw_param.vtx[1] = spr_vtx[1]; + draw_param.vtx[2] = spr_vtx[2]; + draw_param.vtx[3] = spr_vtx[3]; + } args.sprite_draw_param_index = (int32_t)(draw_param_buffer.size() - 1); } - for (int32_t i = 1; i < count; i++) + for (int32_t i = 1; i < args_count; i++) args_array[i]->sprite_draw_param_index = -1; } @@ -1153,6 +1243,7 @@ namespace spr { rend_data_ctx.shader_flags.arr[U_COMBINER] = combiner; } + shaders_ft.set(rend_data_ctx.state, rend_data_ctx.shader_flags, draw_param.shader); if (draw_param.textures[0]) { rend_data_ctx.state.active_bind_texture_2d(0, draw_param.textures[0]->glid); rend_data_ctx.state.bind_sampler(0, rctx->sprite_samplers[draw_param.attrib.m.sampler]); @@ -1169,7 +1260,7 @@ namespace spr { rend_data_ctx.state.active_bind_texture_2d(1, rctx->empty_texture_2d->glid); } - shaders_ft.set(rend_data_ctx.state, rend_data_ctx.shader_flags, draw_param.shader); + rend_data_ctx.state.bind_vertex_array(sprite_manager_render_data->vao[draw_param.attrib.m.vao]); if (draw_param.attrib.m.primitive != GL_TRIANGLES) rend_data_ctx.state.draw_arrays( draw_param.attrib.m.primitive, draw_param.first, draw_param.count); @@ -1190,7 +1281,7 @@ namespace spr { } static void draw_sprite_copy_overlay_texture( - render_data_context& rend_data_ctx, const SprArgs& args, const mat4& mat, const vec3* vtx, + render_data_context& rend_data_ctx, const SprArgs& args, const mat4& mat, const vec3 vtx[4], 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;