diff --git a/src/CRE/Glitter/effect_group.cpp b/src/CRE/Glitter/effect_group.cpp index 89762204..9a7d6640 100644 --- a/src/CRE/Glitter/effect_group.cpp +++ b/src/CRE/Glitter/effect_group.cpp @@ -14,9 +14,19 @@ namespace Glitter { emission = 1.0f; version = GLT_VAL == Glitter::X ? 0x0C : 0x09; type = GLT_VAL; +#if SHARED_GLITTER_BUFFER + buffer = 0; +#endif } EffectGroup::~EffectGroup() { +#if SHARED_GLITTER_BUFFER + ebo.Destroy(); + vbo.Destroy(); + + free_def(buffer); +#endif + for (Mesh& i : meshes) if (i.object_set_hash != hash_murmurhash_empty) { objset_info_storage_unload_set(i.object_set_hash); diff --git a/src/CRE/Glitter/file_reader.cpp b/src/CRE/Glitter/file_reader.cpp index 36fbef08..d4b7932f 100644 --- a/src/CRE/Glitter/file_reader.cpp +++ b/src/CRE/Glitter/file_reader.cpp @@ -11,6 +11,9 @@ #include "../../KKdLib/msgpack.hpp" #include "../data.hpp" #include "../object.hpp" +#if SHARED_GLITTER_BUFFER +#include "../gl_state.hpp" +#endif namespace Glitter { static void effect_group_msgpack_read(const char* path, const char* file, EffectGroup* eff_group); @@ -85,6 +88,102 @@ namespace Glitter { } if (!effect_group->buffer_init) { +#if SHARED_GLITTER_BUFFER + size_t max_count = 0; + size_t max_count_quad = 0; + + for (Effect*& i : effect_group->effects) { + if (!i) + continue; + + for (Emitter*& j : i->emitters) { + if (!j) + continue; + + for (Particle*& k : j->particles) { + if (!k || k->data.type == PARTICLE_MESH || k->max_count <= 0) + continue; + + max_count += k->max_count; + if (k->data.type == PARTICLE_QUAD) + max_count_quad = max_def(max_count_quad, (size_t)k->max_count); + } + } + } + + effect_group->buffer = force_malloc(max_count); + + static const GLsizei buffer_size = sizeof(Buffer); + + effect_group->vbo.Create(buffer_size * max_count); + + if (max_count_quad) { + size_t count = max_count_quad / 4 * 5; + uint32_t* ebo_data = force_malloc(count); + for (size_t i = 0, j = 0, k = count; k; i += 5, j += 4, k -= 5) { + ebo_data[i + 0] = (uint32_t)(j + 0); + ebo_data[i + 1] = (uint32_t)(j + 1); + ebo_data[i + 2] = (uint32_t)(j + 3); + ebo_data[i + 3] = (uint32_t)(j + 2); + ebo_data[i + 4] = 0xFFFFFFFF; + } + + effect_group->ebo.Create(sizeof(uint32_t) * count, ebo_data); + free_def(ebo_data); + } + + Buffer* buffer = effect_group->buffer; + GLuint vbo = effect_group->vbo; + GLuint ebo = effect_group->ebo; + size_t vbo_offset = 0; + + for (Effect*& i : effect_group->effects) { + if (!i) + continue; + + for (Emitter*& j : i->emitters) { + if (!j || j->buffer_init) + continue; + + for (Particle*& k : j->particles) { + if (!k || k->buffer) + continue; + else if (k->data.type == PARTICLE_MESH || k->max_count <= 0) + continue; + + k->buffer = buffer; + k->vbo = vbo; + k->ebo = ebo; + k->vbo_offset = vbo_offset; + + glGenVertexArrays(1, &k->vao); + gl_state_bind_vertex_array(k->vao, true); + gl_state_bind_array_buffer(vbo, true); + if (k->data.type == PARTICLE_QUAD) + gl_state_bind_element_array_buffer(ebo, true); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, buffer_size, + (void*)(offsetof(Buffer, position) + vbo_offset)); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, buffer_size, + (void*)(offsetof(Buffer, uv) + vbo_offset)); + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, buffer_size, + (void*)(offsetof(Buffer, color) + vbo_offset)); + + buffer += k->max_count; + vbo_offset += buffer_size * (size_t)k->max_count; + } + + j->buffer_init = true; + } + } + + gl_state_bind_array_buffer(0); + gl_state_bind_vertex_array(0); + gl_state_bind_element_array_buffer(0); +#else int32_t init_buffers = Glitter::glt_particle_manager->init_buffers; if (init_buffers <= 0) return 0; @@ -111,6 +210,7 @@ namespace Glitter { j->buffer_init = true; } } +#endif effect_group->buffer_init = true; } diff --git a/src/CRE/Glitter/glitter.cpp b/src/CRE/Glitter/glitter.cpp index 8604ca4c..58eebdaf 100644 --- a/src/CRE/Glitter/glitter.cpp +++ b/src/CRE/Glitter/glitter.cpp @@ -281,6 +281,7 @@ namespace Glitter { *angle = (float_t)M_PI - *angle; } +#if !SHARED_GLITTER_BUFFER void CreateBuffer(size_t max_count, bool is_quad, Buffer*& buffer, GLuint& vao, GL::ArrayBuffer& vbo, GL::ElementArrayBuffer& ebo) { free_def(buffer); @@ -337,4 +338,5 @@ namespace Glitter { free_def(buffer); } +#endif } diff --git a/src/CRE/Glitter/glitter.hpp b/src/CRE/Glitter/glitter.hpp index 1d55494e..9f77f284 100644 --- a/src/CRE/Glitter/glitter.hpp +++ b/src/CRE/Glitter/glitter.hpp @@ -27,6 +27,8 @@ #include "../task.hpp" #include "../texture.hpp" +#define SHARED_GLITTER_BUFFER (1) + namespace Glitter { enum CurveFlag { CURVE_RANDOM_RANGE = 0x01, @@ -718,6 +720,11 @@ namespace Glitter { uint32_t version; Type type; std::vector meshes; +#if SHARED_GLITTER_BUFFER + Buffer* buffer; + GL::ArrayBuffer vbo; + GL::ElementArrayBuffer ebo; +#endif EffectGroup(GLT); virtual ~EffectGroup(); @@ -793,7 +800,11 @@ namespace Glitter { GL::ArrayBuffer vbo; GL::ElementArrayBuffer ebo; float_t emission; +#if SHARED_GLITTER_BUFFER + size_t vbo_offset; +#else bool use_own_buffer; +#endif prj::vector_pair draw_list; RenderGroup(); @@ -1367,6 +1378,9 @@ namespace Glitter { int32_t max_count; bool buffer_used; int32_t version; +#if SHARED_GLITTER_BUFFER + size_t vbo_offset; +#endif Particle(GLT); virtual ~Particle() override; @@ -1710,9 +1724,11 @@ namespace Glitter { extern void axis_angle_from_vectors(vec3* axis, float_t* angle, const vec3* vec0, const vec3* vec1); +#if !SHARED_GLITTER_BUFFER extern void CreateBuffer(size_t max_count, bool is_quad, Buffer*& buffer, GLuint& vao, GL::ArrayBuffer& vbo, GL::ElementArrayBuffer& ebo); extern void DeleteBuffer(Buffer*& buffer, GLuint& vao, GL::ArrayBuffer& vbo, GL::ElementArrayBuffer& ebo); +#endif extern void glt_particle_manager_init(); extern bool glt_particle_manager_add_task(); diff --git a/src/CRE/Glitter/particle.cpp b/src/CRE/Glitter/particle.cpp index 589002e1..64543e10 100644 --- a/src/CRE/Glitter/particle.cpp +++ b/src/CRE/Glitter/particle.cpp @@ -44,9 +44,18 @@ namespace Glitter { //data.mesh.mesh_name[0] = 0; //data.mesh.sub_mesh_hash = hash_murmurhash_empty; } + +#if SHARED_GLITTER_BUFFER + vbo_offset = 0; +#endif } Particle::~Particle() { +#if SHARED_GLITTER_BUFFER + ebo.Destroy(); + vbo.Destroy(); +#else Glitter::DeleteBuffer(buffer, vao, vbo, ebo); +#endif } } diff --git a/src/CRE/Glitter/render_group.cpp b/src/CRE/Glitter/render_group.cpp index 094fa487..412c62ce 100644 --- a/src/CRE/Glitter/render_group.cpp +++ b/src/CRE/Glitter/render_group.cpp @@ -17,7 +17,11 @@ namespace Glitter { mat_draw = mat4_identity; disp_type = DISP_NORMAL; emission = 1.0f; +#if SHARED_GLITTER_BUFFER + vbo_offset = 0; +#else use_own_buffer = true; +#endif blend_mode = PARTICLE_BLEND_TYPICAL; mask_blend_mode = PARTICLE_BLEND_TYPICAL; } @@ -86,12 +90,18 @@ namespace Glitter { vao = ptcl->vao; vbo = ptcl->vbo; ebo = ptcl->ebo; +#if SHARED_GLITTER_BUFFER + vbo_offset = ptcl->vbo_offset; +#else use_own_buffer = false; +#endif ptcl->buffer_used = true; } +#if !SHARED_GLITTER_BUFFER if (use_own_buffer) CreateBuffer(max_count, is_quad, buffer, vao, vbo, ebo); +#endif if (!is_quad) draw_list.reserve(count); @@ -233,10 +243,15 @@ namespace Glitter { particle = 0; } +#if SHARED_GLITTER_BUFFER + if (ptcl && ptcl->buffer) + ptcl->buffer_used = false; +#else if (use_own_buffer) Glitter::DeleteBuffer(buffer, vao, vbo, ebo); else if (ptcl && ptcl->buffer) ptcl->buffer_used = false; +#endif if (!free && elements) { Free(); @@ -386,12 +401,18 @@ namespace Glitter { vao = ptcl->vao; vbo = ptcl->vbo; ebo = ptcl->ebo; +#if SHARED_GLITTER_BUFFER + vbo_offset = ptcl->vbo_offset; +#else use_own_buffer = false; +#endif ptcl->buffer_used = true; } +#if !SHARED_GLITTER_BUFFER if (use_own_buffer) CreateBuffer(max_count, is_quad, buffer, vao, vbo, ebo); +#endif if (!is_quad) draw_list.reserve(count); @@ -556,10 +577,15 @@ namespace Glitter { particle = 0; } +#if SHARED_GLITTER_BUFFER + if (ptcl && ptcl->buffer) + ptcl->buffer_used = false; +#else if (use_own_buffer) Glitter::DeleteBuffer(buffer, vao, vbo, ebo); else if (ptcl && ptcl->buffer) ptcl->buffer_used = false; +#endif if (!free && elements) { Free(); diff --git a/src/CRE/Glitter/render_scene.cpp b/src/CRE/Glitter/render_scene.cpp index ada042cc..67c9412f 100644 --- a/src/CRE/Glitter/render_scene.cpp +++ b/src/CRE/Glitter/render_scene.cpp @@ -295,7 +295,12 @@ namespace Glitter { } rend_group->disp = disp; +#if SHARED_GLITTER_BUFFER + rend_group->vbo.WriteMemory(rend_group->vbo_offset, + (buf - rend_group->buffer) * sizeof(Buffer), rend_group->buffer); +#else rend_group->vbo.WriteMemory(0, (buf - rend_group->buffer) * sizeof(Buffer), rend_group->buffer); +#endif } void F2RenderScene::CalcDispLocus(GPM, F2RenderGroup* rend_group) { @@ -439,7 +444,12 @@ namespace Glitter { } rend_group->disp = disp; +#if SHARED_GLITTER_BUFFER + rend_group->vbo.WriteMemory(rend_group->vbo_offset, + (buf - rend_group->buffer) * sizeof(Buffer), rend_group->buffer); +#else rend_group->vbo.WriteMemory(0, (buf - rend_group->buffer) * sizeof(Buffer), rend_group->buffer); +#endif } void F2RenderScene::CalcDispQuad(GPM, F2RenderGroup* rend_group) { @@ -626,7 +636,12 @@ namespace Glitter { } rend_group->disp = disp; +#if SHARED_GLITTER_BUFFER + rend_group->vbo.WriteMemory(rend_group->vbo_offset, + (buf - rend_group->buffer) * sizeof(Buffer), rend_group->buffer); +#else rend_group->vbo.WriteMemory(0, (buf - rend_group->buffer) * sizeof(Buffer), rend_group->buffer); +#endif } void F2RenderScene::CalcDispQuadNormal(GPM, @@ -847,7 +862,12 @@ namespace Glitter { } rend_group->disp = disp; +#if SHARED_GLITTER_BUFFER + rend_group->vbo.WriteMemory(rend_group->vbo_offset, + (buf - rend_group->buffer) * sizeof(Buffer), rend_group->buffer); +#else rend_group->vbo.WriteMemory(0, (buf - rend_group->buffer) * sizeof(Buffer), rend_group->buffer); +#endif } void F2RenderScene::Ctrl(GLT, float_t delta_frame) { @@ -1224,7 +1244,12 @@ namespace Glitter { } rend_group->disp = disp; +#if SHARED_GLITTER_BUFFER + rend_group->vbo.WriteMemory(rend_group->vbo_offset, + (buf - rend_group->buffer) * sizeof(Buffer), rend_group->buffer); +#else rend_group->vbo.WriteMemory(0, (buf - rend_group->buffer) * sizeof(Buffer), rend_group->buffer); +#endif } void XRenderScene::CalcDispLocus(GPM, XRenderGroup* rend_group) { @@ -1366,7 +1391,12 @@ namespace Glitter { } rend_group->disp = disp; +#if SHARED_GLITTER_BUFFER + rend_group->vbo.WriteMemory(rend_group->vbo_offset, + (buf - rend_group->buffer) * sizeof(Buffer), rend_group->buffer); +#else rend_group->vbo.WriteMemory(0, (buf - rend_group->buffer) * sizeof(Buffer), rend_group->buffer); +#endif } void XRenderScene::CalcDispMesh(GPM, XRenderGroup* rend_group) { @@ -1736,7 +1766,12 @@ namespace Glitter { } rend_group->disp = disp; +#if SHARED_GLITTER_BUFFER + rend_group->vbo.WriteMemory(rend_group->vbo_offset, + (buf - rend_group->buffer) * sizeof(Buffer), rend_group->buffer); +#else rend_group->vbo.WriteMemory(0, (buf - rend_group->buffer) * sizeof(Buffer), rend_group->buffer); +#endif } void XRenderScene::CalcDispQuadNormal(XRenderGroup* rend_group, mat4* model_mat, mat4* dir_mat) { @@ -1948,7 +1983,12 @@ namespace Glitter { } rend_group->disp = disp; +#if SHARED_GLITTER_BUFFER + rend_group->vbo.WriteMemory(rend_group->vbo_offset, + (buf - rend_group->buffer) * sizeof(Buffer), rend_group->buffer); +#else rend_group->vbo.WriteMemory(0, (buf - rend_group->buffer) * sizeof(Buffer), rend_group->buffer); +#endif } bool XRenderScene::CanDisp(DispType disp_type, bool a3) {