From a08e5388954ef4273f24406cd48f12b0e8e0f940 Mon Sep 17 00:00:00 2001 From: Brandon Mak Date: Thu, 16 Mar 2023 09:34:42 +0800 Subject: [PATCH] Added Texture support for particles --- Assets/Scenes/Scene2.shade | 8 +- Assets/Shaders/ParticleEmit_CS.glsl | 19 +++- Assets/Shaders/ParticleEmit_CS.shshaderb | Bin 9957 -> 10437 bytes Assets/Shaders/ParticleUpdate_CS.glsl | 2 +- Assets/Shaders/ParticleUpdate_CS.shshaderb | Bin 6541 -> 6565 bytes Assets/Shaders/Particle_FS.glsl | 15 ++- Assets/Shaders/Particle_FS.shshaderb | Bin 537 -> 1401 bytes Assets/Shaders/Particle_VS.glsl | 10 +- Assets/Shaders/Particle_VS.shshaderb | Bin 6357 -> 6585 bytes .../Inspector/SHEditorComponentView.hpp | 43 ++++++++ .../Particles/SHParticleEmitterComponent.cpp | 30 ++++++ .../Particles/SHParticleEmitterComponent.h | 16 ++- .../Particles/SHParticleSubSystem.cpp | 96 ++++++++++-------- .../src/Serialization/SHYAMLConverters.h | 20 ++++ 14 files changed, 205 insertions(+), 54 deletions(-) diff --git a/Assets/Scenes/Scene2.shade b/Assets/Scenes/Scene2.shade index 76595523..4b3d5118 100644 --- a/Assets/Scenes/Scene2.shade +++ b/Assets/Scenes/Scene2.shade @@ -157,15 +157,17 @@ Scale: {x: 1, y: 1, z: 1} IsActive: true classSHADE::SHParticleEmitterComponent: - Emission Count: 1 + Emission Count: 7 Is Passive: true - Emission Interval: 0.200000003 + Emission Interval: 0.0939999968 Min Life: 2 Max Life: 3 Minimum Speed: 3 Maximum Speed: 6 Minimum Size: 0 Maximum Size: 0.5 - Angular Ranges And Offset: {x: 0, y: 0, z: 0, w: 0} + Angular Ranges And Offset: {x: 0.699999988, y: 0.469999999, z: 0, w: 0} + Rotation Speed: 0 + Texture Asset ID: 63456868 IsActive: true Scripts: ~ \ No newline at end of file diff --git a/Assets/Shaders/ParticleEmit_CS.glsl b/Assets/Shaders/ParticleEmit_CS.glsl index 1e2a0882..c9e6cc8b 100644 --- a/Assets/Shaders/ParticleEmit_CS.glsl +++ b/Assets/Shaders/ParticleEmit_CS.glsl @@ -1,5 +1,7 @@ #version 450 +#define PI 3.14159265f + layout(local_size_x = 128) in; struct EmitterParameters @@ -7,14 +9,15 @@ struct EmitterParameters vec4 angularRangesAndOffsets; float minSpeed; float maxSpeed; - float padding[2]; + float rotationSpeed; + uint textureIndex; vec4 lifeAndSizeRange; // min life, max life, min size, max size }; struct ParticleData { vec4 position; - vec4 rotation; + vec4 orientationSpeedDecay; vec4 velocity; vec4 acceleration; vec4 scaleAndDecay; @@ -149,8 +152,18 @@ void main() particle.scaleAndDecay.x = particleSize; particle.scaleAndDecay.z = particleSize; - particle.rotation = vec4 (5.0f); + // Set the texture for the particle + particle.textureIndex = emitterParams.data.textureIndex; + + // Set orientation and rotation speed + if (emitterParams.data.rotationSpeed != 0.0f) + particle.orientationSpeedDecay = vec4 (rand(seed) * PI, emitterParams.data.rotationSpeed, 0.0f, 0.0f); + else + particle.orientationSpeedDecay = vec4 (0.0f); + + particle.acceleration = vec4 (0.01f); + inputParticles.data[index] = particle; } \ No newline at end of file diff --git a/Assets/Shaders/ParticleEmit_CS.shshaderb b/Assets/Shaders/ParticleEmit_CS.shshaderb index 125d56214d9838b6209164686b53572e48083b69..6f340a2754899af3f2b9aae9ffd0985b96894bd1 100644 GIT binary patch literal 10437 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 Pg6l_jUE1uW*k1k*2f#)` literal 9957 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 bANXBqJr_tP7q-h%u2(wa!p2;Jnak$@c})kQ diff --git a/Assets/Shaders/ParticleUpdate_CS.glsl b/Assets/Shaders/ParticleUpdate_CS.glsl index 56b0470c..762ff01a 100644 --- a/Assets/Shaders/ParticleUpdate_CS.glsl +++ b/Assets/Shaders/ParticleUpdate_CS.glsl @@ -13,7 +13,7 @@ struct DrawArraysIndirectArgs struct ParticleData { vec4 position; - vec4 rotation; + vec4 orientationSpeedDecay; vec4 velocity; vec4 acceleration; vec4 scaleAndDecay; diff --git a/Assets/Shaders/ParticleUpdate_CS.shshaderb b/Assets/Shaders/ParticleUpdate_CS.shshaderb index 8f0de701474344fe7efab5fe56b8a95f552c3305..d36fa560d123b200e78dbced03f98c10e3627961 100644 GIT binary patch delta 84 zcmeA*UTVywFlQr^Eu%aqgAfA)10xXU7iFgAl_ZvA=H~?$q^730q$Vd;P7Y!`2~;DB LPt9gMrg(7xt#cR8 delta 60 zcmZ2#+-uCF(6W)qmQk3EL5P8Yff0y{@=Fp+GV}8oCdVip` diff --git a/Assets/Shaders/Particle_FS.glsl b/Assets/Shaders/Particle_FS.glsl index d365b110..243baa2e 100644 --- a/Assets/Shaders/Particle_FS.glsl +++ b/Assets/Shaders/Particle_FS.glsl @@ -1,15 +1,26 @@ #version 460 core +#extension GL_EXT_nonuniform_qualifier : require layout (location = 0) out vec4 fragColor; +layout (set = 0, binding = 1) uniform sampler2D textures[]; // for textures (global) + // between shader stages layout(location = 0) in struct { vec2 uv; // location = 0 - } In; +// material stuff +layout(location = 1) flat in struct +{ + uint textureIndex; +} InFlat; + + void main () { - fragColor = vec4 (1.0f); + fragColor = vec4 (texture(textures [nonuniformEXT(InFlat.textureIndex)], In.uv)); + if (fragColor.a < 0.01f) + discard; } diff --git a/Assets/Shaders/Particle_FS.shshaderb b/Assets/Shaders/Particle_FS.shshaderb index 19e503b2eeedd6e8d92ec7b00034a41a3fd84484..edd2dd6b7d9b403787f621ed464e8e07afc8316e 100644 GIT binary patch literal 1401 zcmZ9LYikox5Qa~iO{}TCXm8fqcGGyT#)=mNFCbDwAka!g{kDW;Qx>+HxY?BYzf=VO zg5UiqiYWL#yJti2z+`6LxzB7C2St;xH%NhS-`8V;h znK7-yx8DByH(u8tcH&@=^kXlGy8dYp9hq5EO5^LzRQNGyJoTP#}GUmGi9mUm~Y3ZmRjiR8}kB_|%qjnhd0za0$jJ;kmsxn_-#r)Cyq|;IdL8sxzU-G zw<3K(+(psbQY`n#Fh}2aRuha^boN7CVwc2StM6J}t4bfWSFA11w{C6p#vU$7RC%$MBuy}yDAxMY681vG3Lwtu3L;b4^@F0H$>zl2Qm0O*CzP>u+cBO+!cYb rV`ie4+amC<@?oEMEykXID#tx>-f#J1+Y^DYW8^>T7#ZxZ delta 292 zcmXv}I|{-;6dZSBg7K4B1q*|qV4+xw5YSRQgEp3e+G(p-2v#;;%!_CtII~IKGVH#Y zdA!+g`1D3`Y~ae8VF1(+qK&wq(1js`d^b)4cqE0>{&1GwAfo)$&)>()a;PYup6Y$M z0(DqKls24MQ`1yhdeujdnc3bZeEDQUr`%Ul1Ux{q5&GOY!y#Sf3z=%KZvvvN&o-= diff --git a/Assets/Shaders/Particle_VS.glsl b/Assets/Shaders/Particle_VS.glsl index d74acdd9..211bb4de 100644 --- a/Assets/Shaders/Particle_VS.glsl +++ b/Assets/Shaders/Particle_VS.glsl @@ -19,7 +19,7 @@ struct GenericData struct ParticleData { vec4 position; - vec4 rotation; + vec4 orientationSpeedDecay; vec4 velocity; vec4 acceleration; vec4 scaleAndDecay; @@ -56,9 +56,14 @@ layout (std430, set = 2, binding = 4) coherent restrict buffer IndicesData layout(location = 0) out struct { vec2 uv; // location = 0 - } Out; +// material stuff +layout(location = 1) out struct +{ + uint textureIndex; // location = 1 +} OutFlat; + vec2 CreateQuad (in uint vertexID) { uint b = 1 << vertexID; @@ -90,6 +95,7 @@ void main() vec3 viewUp = normalize(vec3 (cameraData.viewMat[0][1], cameraData.viewMat[1][1], cameraData.viewMat[2][1])); particlePos = particle.position.xyz + (viewRight * particlePos.x * particleScaleData.x) + (viewUp * particlePos.y * particleScaleData.y); + OutFlat.textureIndex = particle.textureIndex; gl_Position = cameraData.vpMat * vec4(particlePos, 1.0f); } \ No newline at end of file diff --git a/Assets/Shaders/Particle_VS.shshaderb b/Assets/Shaders/Particle_VS.shshaderb index d79ee1d1cd5d1d3e5d7635143926837c84ac367b..492a926c869f280ed8059f362d67f99a3df754f2 100644 GIT binary patch delta 1161 zcmaKrOKTHh6o$V^GD%x62x5yw1@zmxhlz zsfpvLT#t-OP!5a1LmOvgx|NAoJ6{T_`Jf(pcH|_?{qyJt%r z<}*O%O7FD(y3Z4hLT~k)XhvL=$a2`W*bO*zxZym;!zG1&EoZotP>@1D^3dDz*ktS) z1CpkY6!jA+f*Tp)Xb!i%$MtuE!x#uhEz5P}4+~g7J`{&$w`tW!)2T*IHM}Qj;h<{X z$}44voIPpzvSrw#}ML9E4OoHq@i!lycbRjzAz)17E1#BS^Yumwj!|a zQQ?%@6O)6!F8@h*ChQXE!F4|i@WfN{UxdfPRn>6auf{aGq|O8Ko6aOUL)`Zs#}2c4 nQQ7^6pazC~^sLZSW3&x{;pA{Zp4m@O zv)))-y>cd%Xkem18RSdxyRfsW!e8_vn!Y};?B#y=fVjjR3FSEvS@J`fC7c}->OtNg zI~?h-|FiH`7#9{L<8>&&Q_m=W5#9)o_0D*Gb)3>U*LNK6?fbqt4*NCz6*%{iz`XkB j4GmSHtHp@N0_I1;LvdXAyTGH|6_#{2>f?N8YB~4^7Kex3 diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 0e1f4fd4..a46d76c4 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -811,6 +811,8 @@ namespace SHADE if (!component) return; + auto gfxSystem = SHSystemManager::GetSystem(); + ImGui::PushID(SHFamilyID::GetID()); const auto componentType = rttr::type::get(*component); @@ -860,6 +862,47 @@ namespace SHADE comp->SetMaxSpeed(val); }); + SHEditorWidgets::DragFloat("Rotation Speed", + [comp = component]() + { + return comp->GetMaxSpeed(); + }, + [comp = component](float val) + { + comp->SetMaxSpeed(val); + }); + + SHEditorWidgets::DragInt("Texture Index", + [comp = component]() + { + return comp->GetTextureAssetID(); + }, + [comp = component](AssetID val) + { + comp->SetTextureAssetID(val); + }); + if (SHDragDrop::BeginTarget()) + { + if (AssetID* payload = SHDragDrop::AcceptPayload(SHDragDrop::DRAG_RESOURCE)) + { + Handle texture = SHResourceManager::LoadOrGet(*payload); + gfxSystem->BuildTextures(); + + if (texture) + { + component->SetTextureIndex(texture->TextureArrayIndex); + component->SetTextureAssetID(*payload); + } + else + { + SHLOG_WARNING("[] Attempted to load invalid texture! Texture for particle not set. "); + } + + SHDragDrop::EndTarget(); + } + } + + SHEditorWidgets::CheckBox("Is Passive", [comp = component]() {return comp->GetPassive(); }, [comp = component](bool flag) {comp->SetPassive(flag); }); } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp index b095f26b..2427ade9 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp @@ -62,6 +62,21 @@ namespace SHADE cpuEmitterData.maxSpeed = speed; } + void SHParticleEmitterComponent::SetRotationSpeed(float speed) noexcept + { + cpuEmitterData.rotationSpeed = speed; + } + + void SHParticleEmitterComponent::SetTextureIndex(uint32_t index) noexcept + { + cpuEmitterData.textureIndex = index; + } + + void SHParticleEmitterComponent::SetTextureAssetID(AssetID id) + { + textureAssetID = id; + } + void SHParticleEmitterComponent::SetMinSize(float size) noexcept { cpuEmitterData.lifeAndSizeRange.z = size; @@ -113,6 +128,21 @@ namespace SHADE return cpuEmitterData.maxSpeed; } + float SHParticleEmitterComponent::GetRotationSpeed(void) const noexcept + { + return cpuEmitterData.rotationSpeed; + } + + uint32_t SHParticleEmitterComponent::GetTextureIndex(void) const noexcept + { + return cpuEmitterData.textureIndex; + } + + AssetID SHParticleEmitterComponent::GetTextureAssetID(void) const noexcept + { + return textureAssetID; + } + float SHParticleEmitterComponent::GetMinSize(void) const noexcept { return cpuEmitterData.lifeAndSizeRange.z; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h index e345c24d..dea510f2 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h @@ -4,6 +4,7 @@ #include "Math/Vector/SHVec4.h" #include "ECS_Base/Components/SHComponent.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" +#include namespace SHADE { @@ -25,7 +26,11 @@ namespace SHADE //! Maximum starting velocity float maxSpeed; - float padding[2]; + //! Rotational speed of the quad + float rotationSpeed; + + //! Texture used by the particle + uint32_t textureIndex; //! Spawn lifetime and size range (min and max) SHVec4 lifeAndSizeRange; @@ -104,6 +109,9 @@ namespace SHADE //! For all the dynamic SSBOs in the descriptor set std::array, SHGraphicsConstants::NUM_FRAME_BUFFERS> dynamicOffsets{}; + //! For the emitter to use to give particles their texture + AssetID textureAssetID; + public: void OnCreate(void) override final; void OnDestroy(void) override final; @@ -118,6 +126,9 @@ namespace SHADE void SetAngularRangesAndOffsets (SHVec4 const& ranges) noexcept; void SetMinSpeed (float speed) noexcept; void SetMaxSpeed (float speed) noexcept; + void SetRotationSpeed (float speed) noexcept; + void SetTextureIndex (uint32_t index) noexcept; + void SetTextureAssetID (AssetID id); void SetMinSize (float size) noexcept; void SetMaxSize (float size) noexcept; @@ -130,6 +141,9 @@ namespace SHADE SHVec4 const& GetAngularRangesAndOffsets (void) const noexcept; float GetMinSpeed (void) const noexcept; float GetMaxSpeed (void) const noexcept; + float GetRotationSpeed (void) const noexcept; + uint32_t GetTextureIndex (void) const noexcept; + AssetID GetTextureAssetID (void) const noexcept; float GetMinSize (void) const noexcept; float GetMaxSize (void) const noexcept; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.cpp index 665f43aa..bd08b48f 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.cpp @@ -200,9 +200,9 @@ namespace SHADE }; // ...copy assign barriers on heap - preUpdateBarriers[EMITTER_INDEX * 3] = inputParticleDataBarrierPreUpdate; - preUpdateBarriers[(EMITTER_INDEX * 3) + 1] = freelistDataBarrierPreUpdate; - preUpdateBarriers[(EMITTER_INDEX * 3) + 2] = indicesDataBarrierPreUpdate; + preUpdateBarriers.push_back(inputParticleDataBarrierPreUpdate); + preUpdateBarriers.push_back(freelistDataBarrierPreUpdate); + preUpdateBarriers.push_back(indicesDataBarrierPreUpdate); // make new barrier on stack... vk::BufferMemoryBarrier outputParticleDataBarrierPostUpdate @@ -235,9 +235,9 @@ namespace SHADE }; // ...copy assign barriers on heap - postUpdateBarriers[EMITTER_INDEX * 3] = outputParticleDataBarrierPostUpdate; - postUpdateBarriers[(EMITTER_INDEX * 3) + 1] = indicesDataBarrierPostUpdate; - postUpdateBarriers[(EMITTER_INDEX * 3) + 2] = drawDataBarrierPostUpdate; + postUpdateBarriers.push_back(outputParticleDataBarrierPostUpdate); + postUpdateBarriers.push_back(indicesDataBarrierPostUpdate); + postUpdateBarriers.push_back(drawDataBarrierPostUpdate); } void SHParticleSubSystem::Init(Handle device, Handle inDescPool, Handle compatibleRenderpass, Handle subpass, Handle VS, Handle FS, Handle emitCS, Handle defaultUpdateCS) noexcept @@ -334,15 +334,15 @@ namespace SHADE // Every emitter will have its own barrier for its particle data and freelist data. Indices data is not needed since // it's mainly used in update and rendering so a barrier for it is NOT needed here. std::vector preUpdateBarriers{}; - preUpdateBarriers.resize(emitters.size() * 3); + preUpdateBarriers.reserve(emitters.size() * 3); // After we invoke the updates for the emitters, we need to make sure all particles and indices data are done updating // before we issue them for rendering. std::vector postUpdateBarriers{}; - postUpdateBarriers.resize(emitters.size() * 3); + postUpdateBarriers.reserve(emitters.size() * 3); std::vector preDrawBarriers{}; - preDrawBarriers.resize(emitters.size()); + preDrawBarriers.reserve(emitters.size()); // If we wanted to be VERY safe, a barrier would be good here to make sure output particles have finish reading input particles in @@ -365,45 +365,51 @@ namespace SHADE for (auto& emitter : emitters) { - if (!emitter.initialized) - InitializeComponent(emitter); - - // Set emitter emit flag to true here if there are ready to be emitted - if (emitter.isPassive) + if (emitter.isActive) { - // decrement emission timer - emitter.timeBeforeEmission -= dt; + if (!emitter.initialized) + InitializeComponent(emitter); - // Check if time to emit - if (emitter.timeBeforeEmission <= 0.0f) + // Set emitter emit flag to true here if there are ready to be emitted + if (emitter.isPassive) { - // reset timer - emitter.timeBeforeEmission = emitter.emissionInterval; + // decrement emission timer + emitter.timeBeforeEmission -= dt; - // Emit later - emitter.toEmit = true; + // Check if time to emit + if (emitter.timeBeforeEmission <= 0.0f) + { + // reset timer + emitter.timeBeforeEmission = emitter.emissionInterval; + + // Emit later + emitter.toEmit = true; + } } + + if (emitter.toEmit) // take note that if emitter is not passive, this can also be set to true outside of this function + { + // Copy data to host visible buffer of emitter + emitter.emitterData->WriteToMemory (&emitter.cpuEmitterData, sizeof (SHParticleEmitterComponent::GPUEmitterStruct), 0, emitterDataOffset); + + // Call emit function here + EmitComponent(cmdBuffer, emitter, frameIndex); + } + + // prepare barriers + PreparePrePostUpdateBarriers(preUpdateBarriers, postUpdateBarriers, emitter, i, frameIndex); + + // Emitter will emit once and stop emitting next frame (unless specified before reaching here to do so). + emitter.toEmit = false; } - if (emitter.toEmit) // take note that if emitter is not passive, this can also be set to true outside of this function - { - // Copy data to host visible buffer of emitter - emitter.emitterData->WriteToMemory (&emitter.cpuEmitterData, sizeof (SHParticleEmitterComponent::GPUEmitterStruct), 0, emitterDataOffset); - - // Call emit function here - EmitComponent(cmdBuffer, emitter, frameIndex); - } - - // prepare barriers - PreparePrePostUpdateBarriers(preUpdateBarriers, postUpdateBarriers, emitter, i, frameIndex); - - // Emitter will emit once and stop emitting next frame (unless specified before reaching here to do so). - emitter.toEmit = false; ++i; } + // issue the barrier to wait - cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eComputeShader | vk::PipelineStageFlagBits::eVertexShader | vk::PipelineStageFlagBits::eDrawIndirect, vk::PipelineStageFlagBits::eComputeShader, {}, {}, preUpdateBarriers, {}); + if (!preUpdateBarriers.empty()) + cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eComputeShader | vk::PipelineStageFlagBits::eVertexShader | vk::PipelineStageFlagBits::eDrawIndirect, vk::PipelineStageFlagBits::eComputeShader, {}, {}, preUpdateBarriers, {}); @@ -417,14 +423,17 @@ namespace SHADE for (auto& emitter : emitters) { - UpdateCompoennt(cmdBuffer, emitter, frameIndex); + if (emitter.isActive) + UpdateCompoennt(cmdBuffer, emitter, frameIndex); } /*-----------------------------------------------------------------------*/ /* AFTER UPDATING, RENDER PARTICLES */ /*-----------------------------------------------------------------------*/ + // issue the barrier to wait for output particles to be done updating and indices data to finish being modified. - cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eComputeShader, vk::PipelineStageFlagBits::eVertexShader | vk::PipelineStageFlagBits::eDrawIndirect | vk::PipelineStageFlagBits::eVertexShader, {}, {}, postUpdateBarriers, {}); + if (!postUpdateBarriers.empty()) + cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eComputeShader, vk::PipelineStageFlagBits::eVertexShader | vk::PipelineStageFlagBits::eDrawIndirect | vk::PipelineStageFlagBits::eVertexShader, {}, {}, postUpdateBarriers, {}); } @@ -457,10 +466,13 @@ namespace SHADE // TODO: Issue barrier for output particle data. Semaphore should also be issued outside in SHGraphicsSystem for (auto& emitter : emitters) { - // bind the descriptor sets required for emitting particles - cmdBuffer->BindDescriptorSet(emitter.particleDescriptorSet, SH_PIPELINE_TYPE::GRAPHICS, mappings.at(SHPredefinedDescriptorTypes::PARTICLES), emitter.dynamicOffsets[frameIndex]); + if (emitter.isActive) + { + // bind the descriptor sets required for emitting particles + cmdBuffer->BindDescriptorSet(emitter.particleDescriptorSet, SH_PIPELINE_TYPE::GRAPHICS, mappings.at(SHPredefinedDescriptorTypes::PARTICLES), emitter.dynamicOffsets[frameIndex]); - RenderComponent(cmdBuffer, emitter, frameIndex); + RenderComponent(cmdBuffer, emitter, frameIndex); + } } } diff --git a/SHADE_Engine/src/Serialization/SHYAMLConverters.h b/SHADE_Engine/src/Serialization/SHYAMLConverters.h index b5f0ffdf..daf3d4ca 100644 --- a/SHADE_Engine/src/Serialization/SHYAMLConverters.h +++ b/SHADE_Engine/src/Serialization/SHYAMLConverters.h @@ -514,6 +514,8 @@ namespace YAML static constexpr std::string_view MAX_SIZE_TAG = "Maximum Size"; static constexpr std::string_view MIN_SPEED_TAG = "Minimum Speed"; static constexpr std::string_view MAX_SPEED_TAG = "Maximum Speed"; + static constexpr std::string_view ROTATION_SPEED_TAG = "Rotation Speed"; + static constexpr std::string_view TEXTURE_ASSET_ID_TAG = "Texture Asset ID"; static YAML::Node encode(SHParticleEmitterComponent const& rhs) { @@ -528,11 +530,15 @@ namespace YAML node[MIN_SIZE_TAG.data()] = rhs.GetMinSize(); node[MAX_SIZE_TAG.data()] = rhs.GetMaxSize(); node[ANGULAR_RANGES_OFFSET_TAG.data()] = rhs.GetAngularRangesAndOffsets(); + node[ROTATION_SPEED_TAG.data()] = rhs.GetRotationSpeed(); + node[TEXTURE_ASSET_ID_TAG.data()] = rhs.GetTextureAssetID(); return node; } static bool decode(YAML::Node const& node, SHParticleEmitterComponent& rhs) { + auto gfxSystem = SHSystemManager::GetSystem(); + if (node[EMISSION_COUNT_TAG.data()].IsDefined()) rhs.SetEmissionCount(node[EMISSION_COUNT_TAG.data()].as()); @@ -560,6 +566,20 @@ namespace YAML if (node[MAX_SIZE_TAG.data()].IsDefined()) rhs.SetMaxSize(node[MAX_SIZE_TAG.data()].as()); + if (node[ROTATION_SPEED_TAG.data()].IsDefined()) + rhs.SetRotationSpeed(node[ROTATION_SPEED_TAG.data()].as()); + + if (node[TEXTURE_ASSET_ID_TAG.data()].IsDefined()) + { + AssetID id = node[TEXTURE_ASSET_ID_TAG.data()].as(); + + Handle texture = SHResourceManager::LoadOrGet(id); + gfxSystem->BuildTextures(); + + rhs.SetTextureIndex(texture->TextureArrayIndex); + rhs.SetTextureAssetID(id); + } + return true; } };