diff --git a/README.md b/README.md index c2aa0be5..761145d1 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,6 @@ make - [ ] Visualization - [x] Particle System - [x] Renderers - - [ ] Rope - [x] Emitters - [ ] Duration - [x] Initializers diff --git a/src/backend_scene/wallpaper/Particle/Particle.h b/src/backend_scene/wallpaper/Particle/Particle.h index 42e96d2b..f3ac2205 100644 --- a/src/backend_scene/wallpaper/Particle/Particle.h +++ b/src/backend_scene/wallpaper/Particle/Particle.h @@ -1,26 +1,29 @@ #pragma once -namespace wallpaper { +namespace wallpaper +{ struct Particle { - float position[3] {0.0f}; + float position[3] { 0.0f }; - float color[3] {1.0f, 1.0f, 1.0f}; - float colorInit[3] {1.0f, 1.0f, 1.0f}; + float color[3] { 1.0f, 1.0f, 1.0f }; + float colorInit[3] { 1.0f, 1.0f, 1.0f }; - float alpha {1.0f}; - float alphaInit {1.0f}; + float alpha { 1.0f }; + float alphaInit { 1.0f }; - float size {20}; - float sizeInit {20}; + float size { 20 }; + float sizeInit { 20 }; - float lifetime {1.0f}; - float lifetimeInit {1.0f}; + float lifetime { 1.0f }; + float lifetimeInit { 1.0f }; - float rotation[3] {0.0f, 0.0f, 0.0f}; // radian z x y - float velocity[3] {0.0f, 0.0f, 0.0f}; - float acceleration[3] {0.0f, 0.0f, 0.0f}; - float angularVelocity[3] {0.0f, 0.0f, 0.0f}; - float angularAcceleration[3] {0.0f, 0.0f, 0.0f}; + float rotation[3] { 0.0f, 0.0f, 0.0f }; // radian z x y + float velocity[3] { 0.0f, 0.0f, 0.0f }; + float acceleration[3] { 0.0f, 0.0f, 0.0f }; + float angularVelocity[3] { 0.0f, 0.0f, 0.0f }; + float angularAcceleration[3] { 0.0f, 0.0f, 0.0f }; + + bool mark_new { true }; }; -} \ No newline at end of file +} // namespace wallpaper \ No newline at end of file diff --git a/src/backend_scene/wallpaper/Particle/ParticleEmitter.cpp b/src/backend_scene/wallpaper/Particle/ParticleEmitter.cpp index 01e1c68e..7874a128 100644 --- a/src/backend_scene/wallpaper/Particle/ParticleEmitter.cpp +++ b/src/backend_scene/wallpaper/Particle/ParticleEmitter.cpp @@ -4,95 +4,136 @@ #include "Utils/Logging.h" #include #include +#include using namespace wallpaper; -static float GetRandomIn(float min, float max, float random) { - return min + (max - min)*random; -} - typedef std::function GenParticleOp; typedef std::function SpwanOp; -int32_t FindLastParticle(const std::vector& ps, int32_t last) { - for(int32_t i=last;i FindLastParticle(Span ps, uint32_t last) { + for (uint32_t i = last; i < ps.size(); i++) { + if (! ParticleModify::LifetimeOk(ps[i])) return { i, true }; + } + return { 0, false }; } -uint32_t GetEmitNum(double& timer, float speed) { - double emitDur = 1.0f / speed; - if(emitDur > timer) return 0; - uint32_t num = timer / emitDur; - while(emitDur < timer) timer -= emitDur; - if(timer < 0) timer = 0; - return num; + +inline uint32_t GetEmitNum(double& timer, float speed) { + double emitDur = 1.0f / speed; + if (emitDur > timer) return 0; + uint32_t num = timer / emitDur; + while (emitDur < timer) timer -= emitDur; + if (timer < 0) timer = 0; + return num; } -uint32_t Emitt(std::vector& particles, uint32_t num, uint32_t maxcount, SpwanOp Spwan) { - int32_t lastPartcle = 0; - uint32_t i = 0; - for(i=0;i& particles, uint32_t num, uint32_t maxcount, bool sort, + SpwanOp Spwan) { + uint32_t lastPartcle = 0; + bool has_dead = true; + uint32_t i = 0; + + for (i = 0; i < num; i++) { + if (has_dead) { + auto [r1, r2] = FindLastParticle(particles, lastPartcle); + lastPartcle = r1; + has_dead = r2; + } + if (has_dead) { + particles[lastPartcle] = Spwan(); + + } else { + if (maxcount == particles.size()) break; + particles.push_back(Spwan()); + } + } + + if (sort) { + // old << new << dead + std::stable_sort(particles.begin(), particles.end(), [](const auto& a, const auto& b) { + bool l_a = ParticleModify::LifetimeOk(a); + bool l_b = ParticleModify::LifetimeOk(b); + + return (l_a && ! l_b) || + (l_a && l_b && ! ParticleModify::IsNew(a) && ParticleModify::IsNew(b)); + }); + } + + return i + 1; } -Particle Spwan(GenParticleOp gen, std::vector& inis, double duration) { - auto particle = gen(); - for(auto& el:inis) el(particle, duration); - return particle; +inline Particle Spwan(GenParticleOp gen, std::vector& inis, double duration) { + auto particle = gen(); + for (auto& el : inis) el(particle, duration); + return particle; } +} // namespace ParticleEmittOp ParticleBoxEmitterArgs::MakeEmittOp(ParticleBoxEmitterArgs a) { - double timer {0.0f}; - return [a, timer](std::vector& ps, std::vector& inis, uint32_t maxcount, double timepass) mutable { - timer += timepass; - auto GenBox = [&]() { - std::array pos; - for(int32_t i=0;i<3;i++) - pos[i] = GetRandomIn(a.minDistance[i], a.maxDistance[i], (a.randomFn()-0.5f)*2.0f); - auto p = Particle(); - ParticleModify::MoveTo(p, pos[0], pos[1], pos[2]); - ParticleModify::MoveMultiply(p, a.directions[0], a.directions[1], a.directions[2]); - ParticleModify::Move(p, a.orgin[0], a.orgin[1], a.orgin[2]); - return p; - }; - Emitt(ps, GetEmitNum(timer, a.emitSpeed), maxcount, [&]() { - return Spwan(GenBox, inis, 1.0f/a.emitSpeed); - }); - }; + double timer { 0.0f }; + return [a, timer](std::vector& ps, + std::vector& inis, + uint32_t maxcount, + double timepass) mutable { + timer += timepass; + auto GenBox = [&]() { + std::array pos; + for (int32_t i = 0; i < 3; i++) + pos[i] = + GetRandomIn(a.minDistance[i], a.maxDistance[i], (a.randomFn() - 0.5f) * 2.0f); + auto p = Particle(); + ParticleModify::MoveTo(p, pos[0], pos[1], pos[2]); + ParticleModify::MoveMultiply(p, a.directions[0], a.directions[1], a.directions[2]); + ParticleModify::Move(p, a.orgin[0], a.orgin[1], a.orgin[2]); + return p; + }; + uint32_t emit_num = GetEmitNum(timer, a.emitSpeed); + emit_num = a.one_per_frame ? 1 : emit_num; + Emitt(ps, emit_num, maxcount, a.sort, [&]() { + return Spwan(GenBox, inis, 1.0f / a.emitSpeed); + }); + }; } ParticleEmittOp ParticleSphereEmitterArgs::MakeEmittOp(ParticleSphereEmitterArgs a) { - using namespace Eigen; - double timer {0.0f}; - return [a, timer](std::vector& ps, std::vector& inis, uint32_t maxcount, double timepass) mutable { - timer += timepass; - auto GenSphere = [&]() { - auto p = Particle(); - float r = GetRandomIn(a.minDistance, a.maxDistance, a.randomFn()); - std::array sp = algorism::GenSphere(a.randomFn); - ParticleModify::MoveTo(p, sp[0], sp[1], sp[2]); - { - ParticleModify::SphereDirectOffset(p, Vector3f::UnitX(), std::asin(p.position[0]) - std::asin(p.position[0]*a.directions[0])); - ParticleModify::SphereDirectOffset(p, Vector3f::UnitY(), std::asin(p.position[1]) - std::asin(p.position[1]*a.directions[1])); - ParticleModify::SphereDirectOffset(p, Vector3f::UnitZ(), std::asin(p.position[2]) - std::asin(p.position[2]*a.directions[2])); - } - ParticleModify::MoveMultiply(p, r, r, r); - ParticleModify::MoveApplySign(p, a.sign[0], a.sign[1], a.sign[2]); - ParticleModify::Move(p, a.orgin[0], a.orgin[1], a.orgin[2]); - return p; - }; - Emitt(ps, GetEmitNum(timer, a.emitSpeed), maxcount, [&]() { - return Spwan(GenSphere, inis, 1.0f/a.emitSpeed); - }); - }; + using namespace Eigen; + double timer { 0.0f }; + return [a, timer](std::vector& ps, + std::vector& inis, + uint32_t maxcount, + double timepass) mutable { + timer += timepass; + auto GenSphere = [&]() { + auto p = Particle(); + float r = GetRandomIn(a.minDistance, a.maxDistance, a.randomFn()); + std::array sp = algorism::GenSphere(a.randomFn); + ParticleModify::MoveTo(p, sp[0], sp[1], sp[2]); + { + ParticleModify::SphereDirectOffset(p, + Vector3f::UnitX(), + std::asin(p.position[0]) - + std::asin(p.position[0] * a.directions[0])); + ParticleModify::SphereDirectOffset(p, + Vector3f::UnitY(), + std::asin(p.position[1]) - + std::asin(p.position[1] * a.directions[1])); + ParticleModify::SphereDirectOffset(p, + Vector3f::UnitZ(), + std::asin(p.position[2]) - + std::asin(p.position[2] * a.directions[2])); + } + ParticleModify::MoveMultiply(p, r, r, r); + ParticleModify::MoveApplySign(p, a.sign[0], a.sign[1], a.sign[2]); + ParticleModify::Move(p, a.orgin[0], a.orgin[1], a.orgin[2]); + return p; + }; + uint32_t emit_num = GetEmitNum(timer, a.emitSpeed); + emit_num = a.one_per_frame ? 1 : emit_num; + Emitt(ps, emit_num, maxcount, a.sort, [&]() { + return Spwan(GenSphere, inis, 1.0f / a.emitSpeed); + }); + }; } \ No newline at end of file diff --git a/src/backend_scene/wallpaper/Particle/ParticleEmitter.h b/src/backend_scene/wallpaper/Particle/ParticleEmitter.h index 6bbb1ca9..42036222 100644 --- a/src/backend_scene/wallpaper/Particle/ParticleEmitter.h +++ b/src/backend_scene/wallpaper/Particle/ParticleEmitter.h @@ -33,6 +33,8 @@ struct ParticleBoxEmitterArgs { float emitSpeed; std::array orgin; std::function randomFn; + bool one_per_frame; + bool sort; static ParticleEmittOp MakeEmittOp(ParticleBoxEmitterArgs); }; @@ -45,6 +47,8 @@ struct ParticleSphereEmitterArgs { std::array orgin; std::array sign; std::function randomFn; + bool one_per_frame; + bool sort; static ParticleEmittOp MakeEmittOp(ParticleSphereEmitterArgs); }; diff --git a/src/backend_scene/wallpaper/Particle/ParticleModify.h b/src/backend_scene/wallpaper/Particle/ParticleModify.h index bcdefe21..56857102 100644 --- a/src/backend_scene/wallpaper/Particle/ParticleModify.h +++ b/src/backend_scene/wallpaper/Particle/ParticleModify.h @@ -141,5 +141,8 @@ inline void Reset(Particle& p) { p.size = p.sizeInit; std::memcpy(p.color, p.colorInit, 3 * sizeof(float)); } +inline void MarkOld(Particle& p) { p.mark_new = false; } + +inline bool IsNew(const Particle& p) { return p.mark_new; } }; // namespace ParticleModify } // namespace wallpaper \ No newline at end of file diff --git a/src/backend_scene/wallpaper/Particle/ParticleSystem.cpp b/src/backend_scene/wallpaper/Particle/ParticleSystem.cpp index be3c88d5..798890ac 100644 --- a/src/backend_scene/wallpaper/Particle/ParticleSystem.cpp +++ b/src/backend_scene/wallpaper/Particle/ParticleSystem.cpp @@ -26,6 +26,7 @@ void ParticleSubSystem::Emitt() { .time_pass = particleTime }; for (auto& p : info.particles) { + ParticleModify::MarkOld(p); if (! ParticleModify::LifetimeOk(p)) { i++; continue; diff --git a/src/backend_scene/wallpaper/Particle/WPParticleRawGener.cpp b/src/backend_scene/wallpaper/Particle/WPParticleRawGener.cpp index 2b67882a..bdbc23a0 100644 --- a/src/backend_scene/wallpaper/Particle/WPParticleRawGener.cpp +++ b/src/backend_scene/wallpaper/Particle/WPParticleRawGener.cpp @@ -8,51 +8,184 @@ using namespace wallpaper; using namespace Eigen; + +struct WPGOption { + bool thick_format { false }; + bool geometry_shader { false }; +}; + namespace { -inline void GenSingleGLData(const Particle& p, size_t oneSize, const ParticleRawGenSpecOp& specOp, - float* data, bool hasTexCoordVec4C1) { - float size = p.size / 2.0f; - - std::size_t offset = 0; - - float lifetime = p.lifetime; - specOp(p, { &lifetime }); - - // pos - AssignVertexTimes(data, - std::array { p.position[0], p.position[1], p.position[2] }, - offset, - oneSize, - 4); - offset += 4; - // TexCoordVec4 - float rz = p.rotation[2]; - float t[16] { 0.0f, 1.0f, rz, size, 1.0f, 1.0f, rz, size, - 1.0f, 0.0f, rz, size, 0.0f, 0.0f, rz, size }; - AssignVertex(data, t, 16, offset, oneSize, 4); - offset += 4; - - // color - AssignVertexTimes(data, - std::array { p.color[0], p.color[1], p.color[2], p.alpha }, - offset, - oneSize, - 4); - offset += 4; - - if (hasTexCoordVec4C1) { +inline void AssignVertexTimes(Span dst, Span src, uint num) { + const uint dst_one_size = dst.size() / num; + for (uint i = 0; i < num; i++) { + std::copy(src.begin(), src.end(), dst.begin() + i * dst_one_size); + } +} + +inline void AssignVertex(Span dst, Span src, uint num) { + const uint dst_one_size = dst.size() / num; + const uint src_one_size = src.size() / num; + for (uint i = 0; i < num; i++) { + std::copy_n(src.begin() + i * src_one_size, src_one_size, dst.begin() + i * dst_one_size); + } +} + +inline size_t GenParticleData(Span particles, const ParticleRawGenSpecOp& specOp, + WPGOption opt, SceneVertexArray& sv) { + std::array storage; + + float* data = storage.data(); + + const auto oneSize = sv.OneSize(); + uint i { 0 }; + for (const auto& p : particles) { + float size = p.size / 2.0f; + + std::size_t offset = 0; + + float lifetime = p.lifetime; + specOp(p, { &lifetime }); + + // pos + AssignVertexTimes({ data + offset, oneSize * 4 }, + std::array { p.position[0], p.position[1], p.position[2] }, + 4); + offset += 4; + // TexCoordVec4 + float rz = p.rotation[2]; + std::array t { 0.0f, 1.0f, rz, size, 1.0f, 1.0f, rz, size, + 1.0f, 0.0f, rz, size, 0.0f, 0.0f, rz, size }; + AssignVertex({ data + offset, oneSize * 4 }, t, 4); + offset += 4; + + // color + AssignVertexTimes({ data + offset, oneSize * 4 }, + std::array { p.color[0], p.color[1], p.color[2], p.alpha }, + 4); + offset += 4; + + if (opt.thick_format) { + AssignVertexTimes({ data + offset, oneSize * 4 }, + std::array { p.velocity[0], p.velocity[1], p.velocity[2], lifetime }, + 4); + offset += 4; + } + // TexCoordC2 AssignVertexTimes( - data, - std::array { p.velocity[0], p.velocity[1], p.velocity[2], lifetime }, - offset, - oneSize, + { data + offset, oneSize * 4 }, std::array { p.rotation[0], p.rotation[1] }, 4); + + sv.SetVertexs((i++) * 4, 4, data); + } + return particles.size(); +} + +inline size_t GenRopeParticleData(Span particles, + const ParticleRawGenSpecOp& specOp, WPGOption opt, + SceneVertexArray& sv) { + /* + attribute vec4 a_PositionVec4; + attribute vec4 a_TexCoordVec4; + attribute vec4 a_TexCoordVec4C1; + + #if THICKFORMAT + attribute vec4 a_TexCoordVec4C2; + attribute vec4 a_TexCoordVec4C3; + attribute vec2 a_TexCoordC4; + #else + attribute vec3 a_TexCoordVec3C2; + attribute vec2 a_TexCoordC3; + #endif + + attribute vec4 a_Color; + + #define in_ParticleTrailLength (a_TexCoordVec4.w) + #define in_ParticleTrailPosition (a_TexCoordVec4C1.w) + */ + std::array storage; + + float* data = storage.data(); + + const auto one_size = sv.OneSize(); + uint i { 0 }; + for (const auto& p : particles) { + if (i == 0) { + i++; + continue; + } + if (! ParticleModify::LifetimeOk(p)) break; + + const auto& pre_p = particles[i - 1]; + float size = p.size / 2.0f; + std::size_t offset = 0; + + float lifetime = p.lifetime; + specOp(p, { &lifetime }); + float in_ParticleTrailLength = particles.size(); + float in_ParticleTrailPosition = i - 1; + + Vector3f cp_vec = AngleAxisf(p.rotation[2] + M_PI / 2.0f, Vector3f::UnitZ()) * + Vector3f { 0.0f, size / 2.0f, 0.0f }; + Vector3f pos_vec = Vector3f { p.position } - Vector3f { pre_p.position }; + + cp_vec = pos_vec.normalized().dot(cp_vec) > 0 ? cp_vec : -1.0f * cp_vec; + auto& sp = pre_p; + auto& ep = p; + Vector3f scp = Vector3f { sp.position } + cp_vec; + Vector3f ecp = Vector3f { ep.position } - cp_vec; + + // a_PositionVec4: start pos + AssignVertexTimes({ data + offset, one_size * 4 }, + std::array { sp.position[0], sp.position[1], sp.position[2], size }, + 4); + offset += 4; + // a_TexCoordVec4: end pos + AssignVertexTimes( + { data + offset, one_size * 4 }, + std::array { ep.position[0], ep.position[1], ep.position[2], in_ParticleTrailLength }, 4); offset += 4; + + // a_TexCoordVec4C1: cp start pos + AssignVertexTimes({ data + offset, one_size * 4 }, + std::array { scp[0], scp[1], scp[2], in_ParticleTrailPosition }, + 4); + offset += 4; + + if (opt.thick_format) { + // a_TexCoordVec4C2: cp end pos, size_end + AssignVertexTimes( + { data + offset, one_size * 4 }, std::array { ecp[0], ecp[1], ecp[2], size }, 4); + offset += 4; + // a_TexCoordVec4C3: color_end + AssignVertexTimes({ data + offset, one_size * 4 }, + std::array { p.color[0], p.color[1], p.color[2], p.alpha }, + 4); + offset += 4; + // a_TexCoordC4 + std::array t { 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + AssignVertex({ data + offset, one_size * 4 }, t, 4); + offset += 4; + } else { + // a_TexCoordVec3C2: cp end pos + AssignVertexTimes( + { data + offset, one_size * 4 }, std::array { ecp[0], ecp[1], ecp[2] }, 4); + offset += 4; + + // a_TexCoordC3 + std::array t { 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + AssignVertex({ data + offset, one_size * 4 }, t, 4); + offset += 4; + } + + // a_Color + AssignVertexTimes({ data + offset, one_size * 4 }, + std::array { p.color[0], p.color[1], p.color[2], p.alpha }, + 4); + + sv.SetVertexs((i++) * 4, 4, data); } - // TexCoordC2 - AssignVertexTimes( - data, std::array { p.rotation[0], p.rotation[1] }, offset, oneSize, 4); + return i == 0 ? 0 : i - 1; } inline void updateIndexArray(uint16_t index, size_t count, SceneIndexArray& iarray) { @@ -81,22 +214,21 @@ void WPParticleRawGener::GenGLData(const std::vector& particles, Scene auto& sv = mesh.GetVertexArray(0); auto& si = mesh.GetIndexArray(0); - uint32_t i = 0; + WPGOption opt; - bool hasTexCoordVec4C1 { false }; - for (const auto& el : sv.Attributes()) { - if (el.name == WE_IN_TEXCOORDVEC4C1) hasTexCoordVec4C1 = true; - } - std::array storage; + opt.thick_format = sv.GetOption(WE_CB_THICK_FORMAT); + + size_t particle_num { 0 }; + if (sv.GetOption(WE_PRENDER_ROPE)) + particle_num = GenRopeParticleData(particles, specOp, opt, sv); + else + particle_num = GenParticleData(particles, specOp, opt, sv); - float* pStorage = storage.data(); - auto oneSize = sv.OneSize(); - for (const auto& p : particles) { - GenSingleGLData(p, oneSize, specOp, pStorage, hasTexCoordVec4C1); - sv.SetVertexs((i++) * 4, 4, pStorage); - } uint16_t indexNum = (si.DataCount() * 2) / 6; - if (particles.size() > indexNum) { + if (particle_num > indexNum) { updateIndexArray(indexNum, particles.size(), si); + si.SetRenderDataCount(0); + } else { + si.SetRenderDataCount(particle_num * 6 / 2); } } \ No newline at end of file diff --git a/src/backend_scene/wallpaper/Particle/WPParticleRawGener.h b/src/backend_scene/wallpaper/Particle/WPParticleRawGener.h index dd8c2db1..50cb300b 100644 --- a/src/backend_scene/wallpaper/Particle/WPParticleRawGener.h +++ b/src/backend_scene/wallpaper/Particle/WPParticleRawGener.h @@ -2,30 +2,15 @@ #include "Interface/IParticleRawGener.h" #include -namespace wallpaper { - -template -inline void AssignVertexTimes(float*dst, const std::array& src, uint32_t doffset, uint32_t dsize, uint32_t num) { - for(uint32_t i=0;i&, SceneMesh&, ParticleRawGenSpecOp&); - + WPParticleRawGener() {}; + virtual ~WPParticleRawGener() {}; + virtual void GenGLData(const std::vector&, SceneMesh&, ParticleRawGenSpecOp&); }; -} \ No newline at end of file +} // namespace wallpaper \ No newline at end of file diff --git a/src/backend_scene/wallpaper/Scene/SceneIndexArray.cpp b/src/backend_scene/wallpaper/Scene/SceneIndexArray.cpp index 81329b8b..8e75f58f 100644 --- a/src/backend_scene/wallpaper/Scene/SceneIndexArray.cpp +++ b/src/backend_scene/wallpaper/Scene/SceneIndexArray.cpp @@ -3,12 +3,13 @@ using namespace wallpaper; -SceneIndexArray::SceneIndexArray(std::size_t indexCount): m_capacity(indexCount * 3), m_size(0) { +SceneIndexArray::SceneIndexArray(std::size_t indexCount) + : m_capacity(indexCount * 3), m_size(0), m_render_size(0) { m_pData = new uint32_t[m_capacity]; std::memset(m_pData, 0, m_capacity * sizeof(uint32_t)); } SceneIndexArray::SceneIndexArray(Span data) - : m_size(data.size()), m_capacity(m_size) { + : m_size(data.size()), m_capacity(m_size), m_render_size(0) { auto dataSize = data.size(); uint32_t* newdata = new uint32_t[dataSize]; std::memcpy(newdata, &data[0], DataSizeOf()); diff --git a/src/backend_scene/wallpaper/Scene/SceneIndexArray.h b/src/backend_scene/wallpaper/Scene/SceneIndexArray.h index a7cb0d57..bf84f20b 100644 --- a/src/backend_scene/wallpaper/Scene/SceneIndexArray.h +++ b/src/backend_scene/wallpaper/Scene/SceneIndexArray.h @@ -17,6 +17,7 @@ class SceneIndexArray { : m_pData(other.m_pData), m_size(other.m_size), m_capacity(other.m_capacity), + m_render_size(other.m_render_size), m_id(other.m_id) { other.m_pData = nullptr; } @@ -33,6 +34,11 @@ class SceneIndexArray { std::size_t DataCount() const { return m_size; } std::size_t DataSizeOf() const { return m_size * Unit_Byte_Size; } + std::size_t RenderDataCount() const { + return m_render_size == 0 || m_render_size > m_size ? m_size : m_render_size; + } + void SetRenderDataCount(std::size_t val) { m_render_size = val; } + std::size_t CapacityCount() const { return m_capacity; } std::size_t CapacitySizeof() const { return m_capacity * Unit_Byte_Size; } @@ -53,6 +59,8 @@ class SceneIndexArray { std::size_t m_size; std::size_t m_capacity; + std::size_t m_render_size; + uint32_t m_id; }; } // namespace wallpaper diff --git a/src/backend_scene/wallpaper/Scene/SceneVertexArray.cpp b/src/backend_scene/wallpaper/Scene/SceneVertexArray.cpp index d4ab6167..4af96bb6 100644 --- a/src/backend_scene/wallpaper/Scene/SceneVertexArray.cpp +++ b/src/backend_scene/wallpaper/Scene/SceneVertexArray.cpp @@ -90,4 +90,11 @@ SceneVertexArray::GetAttrOffsetMap() const { offset += SceneVertexArray::RealAttributeSize(attr) * sizeof(float); } return result; -} \ No newline at end of file +} + +bool SceneVertexArray::GetOption(std::string_view name) const { + return exists(m_options, name) && m_options.at(std::string(name)); +} +void SceneVertexArray::SetOption(std::string_view name, bool value) { + m_options[std::string(name)] = value; +} diff --git a/src/backend_scene/wallpaper/Scene/SceneVertexArray.h b/src/backend_scene/wallpaper/Scene/SceneVertexArray.h index f52d7b69..7ba34fcc 100644 --- a/src/backend_scene/wallpaper/Scene/SceneVertexArray.h +++ b/src/backend_scene/wallpaper/Scene/SceneVertexArray.h @@ -40,6 +40,9 @@ class SceneVertexArray { bool SetVertex(std::string_view name, Span data); bool SetVertexs(std::size_t index, std::size_t count, const float* data); + bool GetOption(std::string_view) const; + void SetOption(std::string_view, bool); + const float* Data() const { return m_pData; } std::size_t DataSize() const { return m_size; } std::size_t DataSizeOf() const { return m_size * sizeof(float); } @@ -60,10 +63,12 @@ class SceneVertexArray { private: const std::vector m_attributes; - float* m_pData { nullptr }; - std::size_t m_oneSize { 0 }; - std::size_t m_size { 0 }; - std::size_t m_capacity { 0 }; + + Map m_options; + float* m_pData { nullptr }; + std::size_t m_oneSize { 0 }; + std::size_t m_size { 0 }; + std::size_t m_capacity { 0 }; uint32_t m_id; }; diff --git a/src/backend_scene/wallpaper/SpecTexs.hpp b/src/backend_scene/wallpaper/SpecTexs.hpp index 0a758ae5..1784182e 100644 --- a/src/backend_scene/wallpaper/SpecTexs.hpp +++ b/src/backend_scene/wallpaper/SpecTexs.hpp @@ -7,9 +7,9 @@ namespace wallpaper { -#define BASE_GLTEX_NAMES(ext) \ +#define BASE_GLTEX_NAMES(ext) \ "g_Texture0" #ext, "g_Texture1" #ext, "g_Texture2" #ext, "g_Texture3" #ext, "g_Texture4" #ext, \ - "g_Texture5" #ext, "g_Texture6" #ext, "g_Texture7" #ext, "g_Texture8" #ext, \ + "g_Texture5" #ext, "g_Texture6" #ext, "g_Texture7" #ext, "g_Texture8" #ext, \ "g_Texture9" #ext, "g_Texture10" #ext, "g_Texture11" #ext, "g_Texture12" #ext constexpr std::array WE_GLTEX_NAMES { BASE_GLTEX_NAMES() }; @@ -36,10 +36,19 @@ constexpr std::string_view WE_IN_BLENDINDICES { "a_BlendIndices" }; constexpr std::string_view WE_IN_BLENDWEIGHTS { "a_BlendWeights" }; // particle + +constexpr std::string_view WE_IN_POSITIONVEC4 { "a_PositionVec4" }; constexpr std::string_view WE_IN_COLOR { "a_Color" }; constexpr std::string_view WE_IN_TEXCOORDVEC4 { "a_TexCoordVec4" }; constexpr std::string_view WE_IN_TEXCOORDVEC4C1 { "a_TexCoordVec4C1" }; +constexpr std::string_view WE_IN_TEXCOORDVEC4C2 { "a_TexCoordVec4C2" }; +constexpr std::string_view WE_IN_TEXCOORDVEC4C3 { "a_TexCoordVec4C3" }; +constexpr std::string_view WE_IN_TEXCOORDVEC3C2 { "a_TexCoordVec3C2" }; constexpr std::string_view WE_IN_TEXCOORDC2 { "a_TexCoordC2" }; +constexpr std::string_view WE_IN_TEXCOORDC3 { "a_TexCoordC3" }; +constexpr std::string_view WE_IN_TEXCOORDC4 { "a_TexCoordC4" }; +constexpr std::string_view WE_CB_THICK_FORMAT { "THICKFORMAT" }; +constexpr std::string_view WE_PRENDER_ROPE { "PRENDER_ROPE" }; constexpr std::string_view G_M { "g_ModelMatrix" }; constexpr std::string_view G_VP { "g_ViewProjectionMatrix" }; diff --git a/src/backend_scene/wallpaper/Utils/BitFlags.hpp b/src/backend_scene/wallpaper/Utils/BitFlags.hpp new file mode 100644 index 00000000..d28bc748 --- /dev/null +++ b/src/backend_scene/wallpaper/Utils/BitFlags.hpp @@ -0,0 +1,54 @@ +#pragma once +#include + +namespace wallpaper +{ + +template +class BitFlags { + static_assert(std::is_enum_v, "Flags can only be specialized for enum types"); + + using UnderlyingT = typename std::make_unsigned_t>; + +public: + constexpr BitFlags() noexcept: bits_(0u) {} + constexpr BitFlags(UnderlyingT val) noexcept: bits_(val) {} + + BitFlags& set(EnumT e, bool value = true) noexcept { + bits_.set(underlying(e), value); + return *this; + } + + BitFlags& reset(EnumT e) noexcept { + set(e, false); + return *this; + } + + BitFlags& reset() noexcept { + bits_.reset(); + return *this; + } + + [[nodiscard]] bool all() const noexcept { return bits_.all(); } + + [[nodiscard]] bool any() const noexcept { return bits_.any(); } + + [[nodiscard]] bool none() const noexcept { return bits_.none(); } + + [[nodiscard]] constexpr std::size_t size() const noexcept { return bits_.size(); } + + [[nodiscard]] std::size_t count() const noexcept { return bits_.count(); } + + constexpr bool operator[](EnumT e) const { return bits_[underlying(e)]; } + + constexpr bool operator[](UnderlyingT t) const { return bits_[t]; } + + auto to_string() const { return bits_.to_string(); } + +private: + static constexpr UnderlyingT underlying(EnumT e) { return static_cast(e); } + +private: + std::bitset bits_; +}; +} // namespace wallpaper \ No newline at end of file diff --git a/src/backend_scene/wallpaper/Utils/StringHelper.hpp b/src/backend_scene/wallpaper/Utils/StringHelper.hpp index e7a6963d..599463f4 100644 --- a/src/backend_scene/wallpaper/Utils/StringHelper.hpp +++ b/src/backend_scene/wallpaper/Utils/StringHelper.hpp @@ -5,8 +5,11 @@ namespace wallpaper { constexpr bool sstart_with(std::string_view str, std::string_view start) { - return str.size() >= start.size() && - str.compare(0, start.size(), start, 0, start.size()) == 0; -} + return str.size() >= start.size() && str.compare(0, start.size(), start, 0, start.size()) == 0; +} +constexpr bool send_with(std::string_view str, std::string_view end) { + return str.size() >= end.size() && + str.compare(str.size() - end.size(), end.size(), end, 0, end.size()) == 0; +} -} \ No newline at end of file +} // namespace wallpaper \ No newline at end of file diff --git a/src/backend_scene/wallpaper/VulkanRender/CustomShaderPass_impl.hpp b/src/backend_scene/wallpaper/VulkanRender/CustomShaderPass_impl.hpp index 4b28fdd2..e45d93c9 100644 --- a/src/backend_scene/wallpaper/VulkanRender/CustomShaderPass_impl.hpp +++ b/src/backend_scene/wallpaper/VulkanRender/CustomShaderPass_impl.hpp @@ -287,7 +287,7 @@ void CustomShaderPass::prepare(Scene& scene, const Device& device, RenderingReso } if (mesh.IndexCount() > 0) { auto& indice = mesh.GetIndexArray(0); - size_t count = (indice.DataCount() * 2) / 3; + size_t count = (indice.RenderDataCount() * 2) / 3; draw_count = count * 3; auto& buf = index_buf; if (! dyn_buf->writeToBuf(buf, diff --git a/src/backend_scene/wallpaper/WPParticleParser.cpp b/src/backend_scene/wallpaper/WPParticleParser.cpp index 38861c60..fcce88fe 100644 --- a/src/backend_scene/wallpaper/WPParticleParser.cpp +++ b/src/backend_scene/wallpaper/WPParticleParser.cpp @@ -138,13 +138,15 @@ ParticleInitOp WPParticleParser::genParticleInitOp(const nlohmann::json& wpj, Ra PM::InitSize(p, GetRandomIn(r.min, r.max, rf())); }; } else if (name == "alpharandom") { - SingleRandom r = { 1.0f, 1.0f }; + SingleRandom r = { 0.05f, 1.0f }; SingleRandom::ReadFromJson(wpj, r); return [=](Particle& p, double) { PM::InitAlpha(p, GetRandomIn(r.min, r.max, rf())); }; } else if (name == "velocityrandom") { VecRandom r; + r.min[0] = r.min[1] = -32.0f; + r.max[0] = r.max[1] = 32.0f; VecRandom::ReadFromJson(wpj, r); return [=](Particle& p, double) { auto result = GenRandomVec3(rf, r.min, r.max); @@ -152,6 +154,7 @@ ParticleInitOp WPParticleParser::genParticleInitOp(const nlohmann::json& wpj, Ra }; } else if (name == "rotationrandom") { VecRandom r; + r.max[2] = 2 * M_PI; VecRandom::ReadFromJson(wpj, r); return [=](Particle& p, double) { auto result = GenRandomVec3(rf, r.min, r.max); @@ -159,6 +162,8 @@ ParticleInitOp WPParticleParser::genParticleInitOp(const nlohmann::json& wpj, Ra }; } else if (name == "angularvelocityrandom") { VecRandom r; + r.min[2] = -5.0f; + r.max[2] = 5.0f; VecRandom::ReadFromJson(wpj, r); return [=](Particle& p, double) { auto result = GenRandomVec3(rf, r.min, r.max); @@ -422,7 +427,7 @@ WPParticleParser::genParticleOperatorOp(const nlohmann::json& wpj, RandomFn rf, for (auto& p : info.particles) { auto life = PM::LifetimePos(p); Vector3f result; - for (int32_t i = 0; i < 3; i++) + for (uint i = 0; i < 3; i++) result[i] = FadeValueChange( life, vc.starttime, vc.endtime, vc.startvalue[i], vc.endvalue[i]); PM::MutiplyColor(p, result[0], result[1], result[2]); @@ -488,25 +493,30 @@ WPParticleParser::genParticleOperatorOp(const nlohmann::json& wpj, RandomFn rf, }; } -ParticleEmittOp WPParticleParser::genParticleEmittOp(const wpscene::Emitter& wpe, RandomFn rf) { +ParticleEmittOp WPParticleParser::genParticleEmittOp(const wpscene::Emitter& wpe, RandomFn rf, + bool sort) { if (wpe.name == "boxrandom") { ParticleBoxEmitterArgs box; - box.emitSpeed = wpe.rate; - box.minDistance = wpe.distancemin; - box.maxDistance = wpe.distancemax; - box.directions = wpe.directions; - box.orgin = wpe.origin; - box.randomFn = rf; + box.emitSpeed = wpe.rate; + box.minDistance = wpe.distancemin; + box.maxDistance = wpe.distancemax; + box.directions = wpe.directions; + box.orgin = wpe.origin; + box.randomFn = rf; + box.one_per_frame = wpe.flags[wpscene::Emitter::FlagEnum::one_per_frame]; + box.sort = sort; return ParticleBoxEmitterArgs::MakeEmittOp(box); } else if (wpe.name == "sphererandom") { ParticleSphereEmitterArgs sphere; - sphere.emitSpeed = wpe.rate; - sphere.minDistance = wpe.distancemin[0]; - sphere.maxDistance = wpe.distancemax[0]; - sphere.directions = wpe.directions; - sphere.orgin = wpe.origin; - sphere.sign = wpe.sign; - sphere.randomFn = rf; + sphere.emitSpeed = wpe.rate; + sphere.minDistance = wpe.distancemin[0]; + sphere.maxDistance = wpe.distancemax[0]; + sphere.directions = wpe.directions; + sphere.orgin = wpe.origin; + sphere.sign = wpe.sign; + sphere.randomFn = rf; + sphere.one_per_frame = wpe.flags[wpscene::Emitter::FlagEnum::one_per_frame]; + sphere.sort = sort; return ParticleSphereEmitterArgs::MakeEmittOp(sphere); } else return [](std::vector&, std::vector&, uint32_t, float) { diff --git a/src/backend_scene/wallpaper/WPParticleParser.hpp b/src/backend_scene/wallpaper/WPParticleParser.hpp index 86bddee2..b837c7ba 100644 --- a/src/backend_scene/wallpaper/WPParticleParser.hpp +++ b/src/backend_scene/wallpaper/WPParticleParser.hpp @@ -11,7 +11,7 @@ class WPParticleParser { static ParticleInitOp genParticleInitOp(const nlohmann::json&, RandomFn); static ParticleOperatorOp genParticleOperatorOp(const nlohmann::json&, RandomFn, const wpscene::ParticleInstanceoverride&); - static ParticleEmittOp genParticleEmittOp(const wpscene::Emitter&, RandomFn); - static ParticleInitOp genOverrideInitOp(const wpscene::ParticleInstanceoverride&); + static ParticleEmittOp genParticleEmittOp(const wpscene::Emitter&, RandomFn, bool sort = false); + static ParticleInitOp genOverrideInitOp(const wpscene::ParticleInstanceoverride&); }; } // namespace wallpaper \ No newline at end of file diff --git a/src/backend_scene/wallpaper/WPSceneParser.cpp b/src/backend_scene/wallpaper/WPSceneParser.cpp index 47bd627a..0ccf3180 100644 --- a/src/backend_scene/wallpaper/WPSceneParser.cpp +++ b/src/backend_scene/wallpaper/WPSceneParser.cpp @@ -41,6 +41,26 @@ using namespace Eigen; typedef std::function RandomFn; std::string getAddr(void* p) { return std::to_string(reinterpret_cast(p)); } + +struct ParseContext { + RandomFn randomFn; + std::shared_ptr scene; + WPShaderValueUpdater* shader_updater; + uint16_t ortho_w; + uint16_t ortho_h; + fs::VFS* vfs; + + ShaderValueMap global_base_uniforms; + std::shared_ptr effect_camera_node; + std::shared_ptr global_camera_node; + std::shared_ptr global_perspective_camera_node; +}; + +using WPObjectVar = std::variant; + +namespace +{ // mapRate < 1.0 void GenCardMesh(SceneMesh& mesh, const std::array size, const std::array mapRate = { 1.0f, 1.0f }) { @@ -79,18 +99,41 @@ void GenCardMesh(SceneMesh& mesh, const std::array size, } void SetParticleMesh(SceneMesh& mesh, const wpscene::Particle& particle, uint32_t count, - bool sprite = false) { + bool thick_format) { std::vector attrs { { WE_IN_POSITION.data(), VertexType::FLOAT3 }, { WE_IN_TEXCOORDVEC4.data(), VertexType::FLOAT4 }, { WE_IN_COLOR.data(), VertexType::FLOAT4 }, }; - if (sprite) { + if (thick_format) { attrs.push_back({ WE_IN_TEXCOORDVEC4C1.data(), VertexType::FLOAT4 }); } attrs.push_back({ WE_IN_TEXCOORDC2.data(), VertexType::FLOAT2 }); mesh.AddVertexArray(SceneVertexArray(attrs, count * 4)); mesh.AddIndexArray(SceneIndexArray(count)); + mesh.GetVertexArray(0).SetOption(WE_CB_THICK_FORMAT, thick_format); +} + +void SetRopeParticleMesh(SceneMesh& mesh, const wpscene::Particle& particle, uint32_t count, + bool thick_format) { + std::vector attrs { + { WE_IN_POSITIONVEC4.data(), VertexType::FLOAT4 }, + { WE_IN_TEXCOORDVEC4.data(), VertexType::FLOAT4 }, + { WE_IN_TEXCOORDVEC4C1.data(), VertexType::FLOAT4 }, + }; + if (thick_format) { + attrs.push_back({ WE_IN_TEXCOORDVEC4C2.data(), VertexType::FLOAT4 }); + attrs.push_back({ WE_IN_TEXCOORDVEC4C3.data(), VertexType::FLOAT4 }); + attrs.push_back({ WE_IN_TEXCOORDC4.data(), VertexType::FLOAT4 }); + } else { + attrs.push_back({ WE_IN_TEXCOORDVEC3C2.data(), VertexType::FLOAT4 }); + attrs.push_back({ WE_IN_TEXCOORDC3.data(), VertexType::FLOAT4 }); + } + attrs.push_back({ WE_IN_COLOR.data(), VertexType::FLOAT4 }); + mesh.AddVertexArray(SceneVertexArray(attrs, count * 4)); + mesh.AddIndexArray(SceneIndexArray(count)); + mesh.GetVertexArray(0).SetOption(WE_PRENDER_ROPE, true); + mesh.GetVertexArray(0).SetOption(WE_CB_THICK_FORMAT, thick_format); } ParticleAnimationMode ToAnimMode(const std::string& str) { @@ -117,12 +160,13 @@ void LoadOperator(ParticleSubSystem& pSys, const wpscene::Particle& wp, } } void LoadEmitter(ParticleSubSystem& pSys, const wpscene::Particle& wp, float count, - RandomFn& randomFn) { + RandomFn& randomFn, bool render_rope) { + bool sort = render_rope; for (const auto& em : wp.emitters) { auto newEm = em; newEm.rate *= count; // newEm.origin[2] -= perspectiveZ; - pSys.AddEmitter(WPParticleParser::genParticleEmittOp(newEm, randomFn)); + pSys.AddEmitter(WPParticleParser::genParticleEmittOp(newEm, randomFn, sort)); } } @@ -289,7 +333,7 @@ void LoadMaterial(fs::VFS& vfs, const wpscene::WPMaterial& wpmat, Scene* pScene, if ((pScene->textures.at(name)).isSprite) { material.hasSprite = true; const auto& f1 = texh.spriteAnim.GetCurFrame(); - if (wpmat.shader == "genericparticle") { + if (wpmat.shader == "genericparticle" || wpmat.shader == "genericropeparticle") { pWPShaderInfo->combos["SPRITESHEET"] = 1; pWPShaderInfo->combos["THICKFORMAT"] = 1; if (algorism::IsPowOfTwo(texh.width) && algorism::IsPowOfTwo(texh.height)) { @@ -377,22 +421,7 @@ void LoadConstvalue(SceneMaterial& material, const wpscene::WPMaterial& wpmat, } } -struct ParseContext { - RandomFn randomFn; - std::shared_ptr scene; - WPShaderValueUpdater* shader_updater; - uint16_t ortho_w; - uint16_t ortho_h; - fs::VFS* vfs; - - ShaderValueMap global_base_uniforms; - std::shared_ptr effect_camera_node; - std::shared_ptr global_camera_node; - std::shared_ptr global_perspective_camera_node; -}; - -using WPObjectVar = std::variant; +// parse void ParseCamera(ParseContext& context, wpscene::WPSceneGeneral& general) { auto& scene = *context.scene; @@ -727,10 +756,10 @@ void ParseImageObj(ParseContext& context, wpscene::WPImageObject& img_obj) { el.source.c_str()); continue; } - imgEffect->commands.push_back({ .cmd = SceneImageEffect::CmdType::Copy, - .dst = fboMap[el.target], - .src = fboMap[el.source], - .afterpos = el.afterpos }); + imgEffect->commands.push_back({ .cmd = SceneImageEffect::CmdType::Copy, + .dst = fboMap[el.target], + .src = fboMap[el.source], + .afterpos = el.afterpos }); } } @@ -803,13 +832,20 @@ void ParseImageObj(ParseContext& context, wpscene::WPImageObject& img_obj) { void ParseParticleObj(ParseContext& context, wpscene::WPParticleObject& particle) { auto& wppartobj = particle; auto& vfs = *context.vfs; + if (wppartobj.particleObj.renderers.size() == 0) return; + + auto wppartRenderer = wppartobj.particleObj.renderers.at(0); + bool render_rope = sstart_with(wppartRenderer.name, "rope"); + bool hastrail = send_with(wppartRenderer.name, "trail"); + + if (render_rope) wppartobj.material.shader = "genericropeparticle"; // wppartobj.origin[1] = context.ortho_h - wppartobj.origin[1]; auto spNode = std::make_shared(Vector3f(wppartobj.origin.data()), Vector3f(wppartobj.scale.data()), Vector3f(wppartobj.angles.data())); - if (wppartobj.particleObj.flags.perspective) { + if (wppartobj.particleObj.flags[wpscene::Particle::FlagEnum::perspective]) { spNode->SetCamera("global_perspective"); } @@ -824,18 +860,21 @@ void ParseParticleObj(ParseContext& context, wpscene::WPParticleObject& particle shaderInfo.baseConstSvs["g_ViewUp"] = std::array { 0.0f, 1.0f, 0.0f }; shaderInfo.baseConstSvs["g_ViewRight"] = std::array { 1.0f, 0.0f, 0.0f }; - bool hastrail { false }; - if (wppartobj.particleObj.renderers.size() > 0) { - auto wppartRenderer = wppartobj.particleObj.renderers.at(0); - if (wppartRenderer.name == "spritetrail") { - shaderInfo.baseConstSvs["g_RenderVar0"] = - std::array { wppartRenderer.length, wppartRenderer.maxlength, 0.0f, 0.0f }; - shaderInfo.combos["THICKFORMAT"] = 1; - shaderInfo.combos["TRAILRENDERER"] = 1; - hastrail = true; - } + uint32_t maxcount = wppartobj.particleObj.maxcount; + maxcount = maxcount > 4000 ? 4000 : maxcount; + + if (hastrail) { + float in_SegmentUVTimeOffset = 0.0f; + float in_SegmentMaxCount = maxcount - 1; + shaderInfo.baseConstSvs["g_RenderVar0"] = std::array { wppartRenderer.length, + wppartRenderer.maxlength, + in_SegmentUVTimeOffset, + in_SegmentMaxCount }; + shaderInfo.combos["THICKFORMAT"] = 1; + shaderInfo.combos["TRAILRENDERER"] = 1; } - if (! wppartobj.particleObj.flags.spritenoframeblending) { + + if (! wppartobj.particleObj.flags[wpscene::Particle::FlagEnum::spritenoframeblending]) { shaderInfo.combos["SPRITESHEETBLEND"] = 1; } @@ -847,16 +886,17 @@ void ParseParticleObj(ParseContext& context, wpscene::WPParticleObject& particle &svData, &shaderInfo); LoadConstvalue(material, wppartobj.material, shaderInfo); - auto spMesh = std::make_shared(true); - auto& mesh = *spMesh; - uint32_t maxcount = wppartobj.particleObj.maxcount; - auto animationmode = ToAnimMode(wppartobj.particleObj.animationmode); - auto sequencemultiplier = wppartobj.particleObj.sequencemultiplier; - bool hasSprite = material.hasSprite; - - maxcount = maxcount > 4000 ? 4000 : maxcount; - - SetParticleMesh(mesh, wppartobj.particleObj, maxcount, material.hasSprite || hastrail); + auto spMesh = std::make_shared(true); + auto& mesh = *spMesh; + auto animationmode = ToAnimMode(wppartobj.particleObj.animationmode); + auto sequencemultiplier = wppartobj.particleObj.sequencemultiplier; + bool hasSprite = material.hasSprite; + + bool thick_format = material.hasSprite || hastrail; + if (render_rope) + SetRopeParticleMesh(mesh, wppartobj.particleObj, maxcount, thick_format); + else + SetParticleMesh(mesh, wppartobj.particleObj, maxcount, thick_format); const auto& wpemitter = wppartobj.particleObj.emitters[0]; auto particleSub = std::make_unique( context.scene->paritileSys, @@ -877,8 +917,11 @@ void ParseParticleObj(ParseContext& context, wpscene::WPParticleObject& particle } }); - LoadEmitter( - *particleSub, wppartobj.particleObj, wppartobj.instanceoverride.count, context.randomFn); + LoadEmitter(*particleSub, + wppartobj.particleObj, + wppartobj.instanceoverride.count, + context.randomFn, + render_rope); LoadInitializer( *particleSub, wppartobj.particleObj, wppartobj.instanceoverride, context.randomFn); LoadOperator(*particleSub, wppartobj.particleObj, wppartobj.instanceoverride, context.randomFn); @@ -903,6 +946,7 @@ void ParseLightObj(ParseContext& context, wpscene::WPLightObject& light_obj) { context.scene->sceneGraph->AppendChild(node); } +} // namespace std::shared_ptr WPSceneParser::Parse(const std::string& buf, fs::VFS& vfs, audio::SoundManager& sm) { diff --git a/src/backend_scene/wallpaper/WPShaderParser.cpp b/src/backend_scene/wallpaper/WPShaderParser.cpp index b49fdee4..32a1637b 100644 --- a/src/backend_scene/wallpaper/WPShaderParser.cpp +++ b/src/backend_scene/wallpaper/WPShaderParser.cpp @@ -214,7 +214,10 @@ std::size_t FindIncludeInsertPos(const std::string& src, std::size_t startPos) { return p.find_first_of('\n', pos) + 1; }; - std::size_t mainPos = src.find("void main("); + std::size_t mainPos = src.find("void main("); + bool two_main = src.find("void main(", mainPos + 2) != std::string::npos; + if (two_main) return 0; + std::size_t pos; { const std::regex reAfters(R"(\n(attribute|varying|uniform|struct) )"); diff --git a/src/backend_scene/wallpaper/WPTexImageParser.cpp b/src/backend_scene/wallpaper/WPTexImageParser.cpp index dfdc49e6..d7184776 100644 --- a/src/backend_scene/wallpaper/WPTexImageParser.cpp +++ b/src/backend_scene/wallpaper/WPTexImageParser.cpp @@ -6,6 +6,8 @@ #include "SpriteAnimation.hpp" #include "Algorism.h" #include "Fs/VFS.h" +#include "Utils/BitFlags.hpp" + #define STB_IMAGE_IMPLEMENTATION #include @@ -47,36 +49,20 @@ TextureFormat ToTexFormate(int type) { return TextureFormat::RGBA8; } } -struct WPTexFlag { - static constexpr int Num { 6 }; - static constexpr const std::array Masks { 1u, 1u << 1, 1u << 2, - 1u << 20, 1u << 21, 1u << 22 }; + +enum class WPTexFlagEnum : uint32_t +{ // true for no bilinear - bool noInterpolation { false }; + noInterpolation = 0, // true for no repeat - bool clampUVs { false }; - bool sprite { false }; + clampUVs = 1, + sprite = 2, - bool compo1 { false }; - bool compo2 { false }; - bool compo3 { false }; + compo1 = 20, + compo2 = 21, + compo3 = 22 }; - -WPTexFlag LoadFlags(uint32_t value) { - WPTexFlag flags; - std::array values({ - &flags.noInterpolation, - &flags.clampUVs, - &flags.sprite, - &flags.compo1, - &flags.compo2, - &flags.compo3, - }); - for (int i = 0; i < WPTexFlag::Num; i++) { - *values[i] = (value & WPTexFlag::Masks[i]) > 0u; - } - return flags; -} +using WPTexFlags = BitFlags; void LoadHeader(fs::IBinaryStream& file, ImageHeader& header) { int32_t unkown; @@ -84,16 +70,16 @@ void LoadHeader(fs::IBinaryStream& file, ImageHeader& header) { header.extraHeader["texi"].val = ReadTexVesion(file); header.format = ToTexFormate(file.ReadInt32()); - auto flags = LoadFlags(file.ReadInt32()); + WPTexFlags flags(file.ReadUint32()); { - header.isSprite = flags.sprite; + header.isSprite = flags[WPTexFlagEnum::sprite]; header.sample.wrapS = header.sample.wrapT = - flags.clampUVs ? TextureWrap::CLAMP_TO_EDGE : TextureWrap::REPEAT; + flags[WPTexFlagEnum::clampUVs] ? TextureWrap::CLAMP_TO_EDGE : TextureWrap::REPEAT; header.sample.minFilter = header.sample.magFilter = - flags.noInterpolation ? TextureFilter::NEAREST : TextureFilter::LINEAR; - header.extraHeader["compo1"].val = flags.compo1; - header.extraHeader["compo2"].val = flags.compo2; - header.extraHeader["compo3"].val = flags.compo3; + flags[WPTexFlagEnum::noInterpolation] ? TextureFilter::NEAREST : TextureFilter::LINEAR; + header.extraHeader["compo1"].val = flags[WPTexFlagEnum::compo1]; + header.extraHeader["compo2"].val = flags[WPTexFlagEnum::compo2]; + header.extraHeader["compo3"].val = flags[WPTexFlagEnum::compo3]; } /* diff --git a/src/backend_scene/wallpaper/wpscene/WPParticleObject.cpp b/src/backend_scene/wallpaper/wpscene/WPParticleObject.cpp index 1a8b1945..5a3fbeaa 100644 --- a/src/backend_scene/wallpaper/wpscene/WPParticleObject.cpp +++ b/src/backend_scene/wallpaper/wpscene/WPParticleObject.cpp @@ -2,13 +2,19 @@ #include "Utils/Logging.h" #include "Fs/VFS.h" +#include "Utils/StringHelper.hpp" using namespace wallpaper::wpscene; bool ParticleRender::FromJson(const nlohmann::json& json) { GET_JSON_NAME_VALUE(json, "name", name); + // ropetrail require subdivition, replaced if (name == "ropetrail") name = "spritetrail"; - if (name == "spritetrail") { + + if (sstart_with(name, "rope")) { + GET_JSON_NAME_VALUE_NOWARN(json, "subdivision", subdivision); + } + if (name == "spritetrail" || name == "ropetrail") { GET_JSON_NAME_VALUE_NOWARN(json, "length", length); GET_JSON_NAME_VALUE_NOWARN(json, "maxlength", maxlength); } @@ -25,6 +31,11 @@ bool Emitter::FromJson(const nlohmann::json& json) { GET_JSON_NAME_VALUE_NOWARN(json, "origin", origin); GET_JSON_NAME_VALUE_NOWARN(json, "sign", sign); GET_JSON_NAME_VALUE_NOWARN(json, "audioprocessingmode", audioprocessingmode); + + uint32_t _raw_flag { 0 }; + GET_JSON_NAME_VALUE_NOWARN(json, "flag", _raw_flag); + flags = EFlags(_raw_flag); + std::transform(sign.begin(), sign.end(), sign.begin(), [](int32_t v) { if (v != 0) return v / std::abs(v); @@ -84,13 +95,10 @@ bool Particle::FromJson(const nlohmann::json& json) { GET_JSON_NAME_VALUE(json, "maxcount", maxcount); GET_JSON_NAME_VALUE(json, "starttime", starttime); - int32_t rawflags { 0 }; + uint32_t rawflags { 0 }; GET_JSON_NAME_VALUE_NOWARN(json, "flags", rawflags); - if (rawflags > 0) { - flags.wordspace = rawflags & 1; - flags.spritenoframeblending = rawflags & 2; - flags.perspective = rawflags & 4; - } + flags = EFlags(rawflags); + return true; } diff --git a/src/backend_scene/wallpaper/wpscene/WPParticleObject.h b/src/backend_scene/wallpaper/wpscene/WPParticleObject.h index e41a0d86..6c3ed461 100644 --- a/src/backend_scene/wallpaper/wpscene/WPParticleObject.h +++ b/src/backend_scene/wallpaper/wpscene/WPParticleObject.h @@ -3,6 +3,7 @@ #include "WPMaterial.h" #include #include +#include "Utils/BitFlags.hpp" namespace wallpaper { @@ -19,6 +20,7 @@ class ParticleRender { std::string name; float length { 0.05f }; float maxlength { 10.0f }; + float subdivision { 3.0f }; }; class Initializer { @@ -30,6 +32,13 @@ class Initializer { }; class Emitter { +public: + enum class FlagEnum : uint32_t + { + one_per_frame = 1, + }; + using EFlags = BitFlags; + public: bool FromJson(const nlohmann::json&); std::array directions { 1.0f, 1.0f, 0 }; @@ -39,17 +48,21 @@ class Emitter { std::array sign { 0, 0, 0 }; uint32_t audioprocessingmode { 0 }; int32_t id; + EFlags flags; std::string name; float rate { 5.0f }; }; -struct ParticleFlag { - bool wordspace { false }; // 1 - bool spritenoframeblending { false }; // 2 - bool perspective { false }; // 4 -}; - class Particle { +public: + enum class FlagEnum + { + wordspace = 0, // 1 + spritenoframeblending = 1, // 2 + perspective = 2, // 4 + }; + using EFlags = BitFlags; + public: bool FromJson(const nlohmann::json&); std::vector emitters; @@ -60,7 +73,7 @@ class Particle { float sequencemultiplier; uint32_t maxcount; uint32_t starttime; - ParticleFlag flags; + EFlags flags; }; class ParticleInstanceoverride { @@ -99,8 +112,7 @@ class WPParticleObject { NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Initializer, name, max, min); NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Emitter, name, distancemax, distancemin, rate, directions); -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(ParticleFlag, wordspace, perspective); -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Particle, flags, initializers, operators, emitters); +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Particle, initializers, operators, emitters); NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(WPParticleObject, name, origin, angles, scale, visible, particle, particleObj); } // namespace wpscene