diff --git a/Assets/Scenes/Scene2.shade b/Assets/Scenes/Scene2.shade index 2cfa3fb7..76595523 100644 --- a/Assets/Scenes/Scene2.shade +++ b/Assets/Scenes/Scene2.shade @@ -158,15 +158,14 @@ IsActive: true classSHADE::SHParticleEmitterComponent: Emission Count: 1 - Is Passive: false - Emission Interval: 3 - Min Life: 7 - Max Life: 20 - Angular Min: {x: 2.29999995, y: 1.70000005, z: 2.9000001} - Angular Max: {x: 0, y: 0, z: 0} - Minimum Velocity: {x: 1, y: 1, z: 0} - Maximum Velocity: {x: 2, y: 2, z: 0} - Minimum Size: 1 - Maximum Size: 3 + Is Passive: true + Emission Interval: 0.200000003 + 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} IsActive: true Scripts: ~ \ No newline at end of file diff --git a/Assets/Shaders/ParticleEmit_CS.glsl b/Assets/Shaders/ParticleEmit_CS.glsl index 6c65ff83..1e2a0882 100644 --- a/Assets/Shaders/ParticleEmit_CS.glsl +++ b/Assets/Shaders/ParticleEmit_CS.glsl @@ -4,10 +4,10 @@ layout(local_size_x = 128) in; struct EmitterParameters { - vec4 angularMin; - vec4 angularMax; - vec4 minVel; - vec4 maxVel; + vec4 angularRangesAndOffsets; + float minSpeed; + float maxSpeed; + float padding[2]; vec4 lifeAndSizeRange; // min life, max life, min size, max size }; @@ -107,6 +107,9 @@ void main() { uint emitterInvocationIndex = gl_GlobalInvocationID.x; vec4 emitterPosition = emitterPushConstant.emitterPosition; + vec4 angularRangesAndOffsets = emitterParams.data.angularRangesAndOffsets; + float minSpeed = emitterParams.data.minSpeed; + float maxSpeed = emitterParams.data.maxSpeed; if (emitterInvocationIndex >= emitterPushConstant.emissionCount) return; @@ -127,15 +130,24 @@ void main() // emit particle from emitter position particle.position = vec4 (emitterPosition.xyz, 1.0f); + vec2 eulerAngles = vec2 (rand(seed) * angularRangesAndOffsets.x + angularRangesAndOffsets.z, + rand(seed) * angularRangesAndOffsets.y + angularRangesAndOffsets.w); + // Set its velocity - particle.velocity = emitterParams.data.minVel; + particle.velocity.xyz = vec3 (cos(eulerAngles.x) * cos(eulerAngles.y), + sin(eulerAngles.x) * cos(eulerAngles.y), + sin(eulerAngles.y)); + + particle.velocity *= map (rand (seed), 0.0f, 1.0f, minSpeed.x, maxSpeed.x); // randomize life value that ranges from minLife to maxLife particle.life = map (rand(seed), 0.0f, 1.0f, emitterParams.data.lifeAndSizeRange.x, emitterParams.data.lifeAndSizeRange.y); + float particleSize = map (rand(seed), 0.0f, 1.0f, emitterParams.data.lifeAndSizeRange.z, emitterParams.data.lifeAndSizeRange.w); + // Set size of particle - particle.scaleAndDecay.x = emitterParams.data.lifeAndSizeRange.z; - particle.scaleAndDecay.z = emitterParams.data.lifeAndSizeRange.z; + particle.scaleAndDecay.x = particleSize; + particle.scaleAndDecay.z = particleSize; particle.rotation = vec4 (5.0f); particle.acceleration = vec4 (0.01f); diff --git a/Assets/Shaders/ParticleEmit_CS.shshaderb b/Assets/Shaders/ParticleEmit_CS.shshaderb index 898baf45..125d5621 100644 Binary files a/Assets/Shaders/ParticleEmit_CS.shshaderb and b/Assets/Shaders/ParticleEmit_CS.shshaderb differ diff --git a/Assets/Shaders/ParticleUpdate_CS.glsl b/Assets/Shaders/ParticleUpdate_CS.glsl index 722833ad..56b0470c 100644 --- a/Assets/Shaders/ParticleUpdate_CS.glsl +++ b/Assets/Shaders/ParticleUpdate_CS.glsl @@ -119,23 +119,23 @@ void main() if (particle.life > 0.0f) { // update position from velocity - // particle.position += particle.velocity * genericDataBuffer.data.dt; - // particle.life -= genericDataBuffer.data.dt; + particle.position += particle.velocity * genericDataBuffer.data.dt; + particle.life -= genericDataBuffer.data.dt; if (particle.life < 0.0f || particle.scaleAndDecay.x < 0.0f || particle.scaleAndDecay.y < 0.0f) { particle.life = 0.0f; - particle.position.x = 99999.0f; + particle.position.x = 9999.0f; outputParticles.data[index] = particle; freelist.freeIndices[atomicAdd(freelist.freeCount, 1)] = int (index); return; } - outputParticles.data[index] = particle; uint drawIndex = atomicAdd (indirectArgs.instanceCount, 1); indices[drawIndex] = index; - // indirectArgs.instanceCount = 1; } + + outputParticles.data[index] = particle; } \ No newline at end of file diff --git a/Assets/Shaders/ParticleUpdate_CS.shshaderb b/Assets/Shaders/ParticleUpdate_CS.shshaderb index 53c89d01..8f0de701 100644 Binary files a/Assets/Shaders/ParticleUpdate_CS.shshaderb and b/Assets/Shaders/ParticleUpdate_CS.shshaderb differ diff --git a/Assets/Shaders/Particle_VS.glsl b/Assets/Shaders/Particle_VS.glsl index 2645fe87..d74acdd9 100644 --- a/Assets/Shaders/Particle_VS.glsl +++ b/Assets/Shaders/Particle_VS.glsl @@ -74,24 +74,22 @@ void main() ParticleData particle = outputParticles.data[indices[gl_InstanceIndex]]; vec3 normalized = normalize (particle.velocity.xyz); - float angle = atan (normalized.y, normalized.x); + float angle = 1.1f; + // float angle = atan (normalized.y, normalized.x); vec2 particleScaleData = particle.scaleAndDecay.xz; // x and y - mat4 localModel = mat4 (1.0f); - localModel[0][0] = 1.0f; - localModel[1][1] = 1.0f; - - // localModel[0][0] = particleScaleData.x; - // localModel[1][1] = particleScaleData.y; - - mat4 rotate = mat4(1.0f); + mat3 rotate = mat3 (1.0f); rotate[0][0] = cos(angle); rotate[0][1] = sin(angle); rotate[1][0] = -sin(angle); rotate[1][1] = cos(angle); - // localModel = rotate * localModel; - localModel[3] = vec4 (particle.position.xyz, 1.0f); - // gl_Position = cameraData.vpMat * localModel * vec4(vertexPos, 1.0f); - gl_Position = vec4(vertexPos, 1.0f); + vec3 particlePos = rotate * vertexPos; + + vec3 viewRight = normalize (vec3 (cameraData.viewMat[0][0], cameraData.viewMat[1][0], cameraData.viewMat[2][0])); + 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); + + 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 c863fca2..d79ee1d1 100644 Binary files a/Assets/Shaders/Particle_VS.shshaderb and b/Assets/Shaders/Particle_VS.shshaderb differ diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 893d485e..0e1f4fd4 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -827,46 +827,37 @@ namespace SHADE SHEditorWidgets::DragFloat("Min Life", [comp = component]() {return comp->GetMinLife(); }, [comp = component](float val) {comp->SetMinLife(val); }); SHEditorWidgets::DragFloat("Max Life", [comp = component]() {return comp->GetMaxLife(); }, [comp = component](float val) {comp->SetMaxLife(val); }); SHEditorWidgets::DragFloat("Min Size", [comp = component]() {return comp->GetMinSize(); }, [comp = component](float val) {comp->SetMinSize(val); }); - SHEditorWidgets::DragFloat("Man Size", [comp = component]() {return comp->GetMaxSize(); }, [comp = component](float val) {comp->SetMaxSize(val); }); + SHEditorWidgets::DragFloat("Max Size", [comp = component]() {return comp->GetMaxSize(); }, [comp = component](float val) {comp->SetMaxSize(val); }); - SHEditorWidgets::DragVec3("Angular Min", {"x", "y", "z"}, + SHEditorWidgets::DragVec4("Angles and Offsets", {"yaw", "pitch", "yaw off", "pitch off"}, [comp = component]() { - return comp->GetAngularMin(); + return comp->GetAngularRangesAndOffsets(); }, - [comp = component](SHVec3 const& val) + [comp = component](SHVec4 const& val) { - comp->SetAngularMin(val); + comp->SetAngularRangesAndOffsets(val); }); - SHEditorWidgets::DragVec3("Angular Max", { "x", "y", "z" }, + + SHEditorWidgets::DragFloat("Min Speed", [comp = component]() { - return comp->GetAngularMax(); + return comp->GetMinSpeed(); }, - [comp = component](SHVec3 const& val) + [comp = component](float val) { - comp->SetAngularMax(val); + comp->SetMinSpeed(val); }); - SHEditorWidgets::DragVec3("Min Vel", { "x", "y", "z" }, + SHEditorWidgets::DragFloat("Max Speed", [comp = component]() { - return comp->GetMinVelocity(); + return comp->GetMaxSpeed(); }, - [comp = component](SHVec3 const& val) + [comp = component](float val) { - comp->SetMinVelocity(val); - }); - - SHEditorWidgets::DragVec3("Max Vel", { "x", "y", "z" }, - [comp = component]() - { - return comp->GetMaxVelocity(); - }, - [comp = component](SHVec3 const& val) - { - comp->SetMaxVelocity(val); + comp->SetMaxSpeed(val); }); 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 d2c0e05a..b095f26b 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp @@ -46,24 +46,20 @@ namespace SHADE cpuEmitterData.lifeAndSizeRange.y = val; } - void SHParticleEmitterComponent::SetAngularMin(SHVec3 const& min) noexcept + void SHParticleEmitterComponent::SetAngularRangesAndOffsets(SHVec4 const& ranges) noexcept { - cpuEmitterData.angularMin = SHVec4 (min); + cpuEmitterData.angularRangesAndOffsets = SHVec4 (ranges); } - void SHParticleEmitterComponent::SetAngularMax(SHVec3 const& max) noexcept + + void SHParticleEmitterComponent::SetMinSpeed(float speed) noexcept { - cpuEmitterData.angularMax = SHVec4(max); + cpuEmitterData.minSpeed = speed; } - void SHParticleEmitterComponent::SetMinVelocity(SHVec3 const& vel) noexcept + void SHParticleEmitterComponent::SetMaxSpeed(float speed) noexcept { - cpuEmitterData.minVel = vel; - } - - void SHParticleEmitterComponent::SetMaxVelocity(SHVec3 const& vel) noexcept - { - cpuEmitterData.maxVel = vel; + cpuEmitterData.maxSpeed = speed; } void SHParticleEmitterComponent::SetMinSize(float size) noexcept @@ -102,19 +98,19 @@ namespace SHADE } - SHVec3 SHParticleEmitterComponent::GetAngularMin(void) const noexcept + SHVec4 const& SHParticleEmitterComponent::GetAngularRangesAndOffsets(void) const noexcept { - return SHVec3 (cpuEmitterData.angularMin.x, cpuEmitterData.angularMin.y, cpuEmitterData.angularMin.z); + return cpuEmitterData.angularRangesAndOffsets; } - SHVec3 SHParticleEmitterComponent::GetMinVelocity(void) const noexcept + float SHParticleEmitterComponent::GetMinSpeed(void) const noexcept { - return SHVec3(cpuEmitterData.minVel.x, cpuEmitterData.minVel.y, cpuEmitterData.minVel.z); + return cpuEmitterData.minSpeed; } - SHVec3 SHParticleEmitterComponent::GetMaxVelocity(void) const noexcept + float SHParticleEmitterComponent::GetMaxSpeed(void) const noexcept { - return SHVec3(cpuEmitterData.maxVel.x, cpuEmitterData.maxVel.y, cpuEmitterData.maxVel.z); + return cpuEmitterData.maxSpeed; } float SHParticleEmitterComponent::GetMinSize(void) const noexcept @@ -127,9 +123,5 @@ namespace SHADE return cpuEmitterData.lifeAndSizeRange.w; } - SHVec3 SHParticleEmitterComponent::GetAngularMax(void) const noexcept - { - return SHVec3(cpuEmitterData.angularMax.x, cpuEmitterData.angularMax.y, cpuEmitterData.angularMax.z); - } } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h index 7781c29f..e345c24d 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h @@ -16,17 +16,16 @@ namespace SHADE private: struct GPUEmitterStruct { - //! Minimum emitting angular range - SHVec4 angularMin; - - //! Maximum emitting angular range - SHVec4 angularMax; + //! Angular ranges of emission + SHVec4 angularRangesAndOffsets; //! minimum starting velocity - SHVec4 minVel; + float minSpeed; //! Maximum starting velocity - SHVec4 maxVel; + float maxSpeed; + + float padding[2]; //! Spawn lifetime and size range (min and max) SHVec4 lifeAndSizeRange; @@ -111,30 +110,28 @@ namespace SHADE void Emit (void) noexcept; - void SetEmissionCount (uint32_t count) noexcept; - void SetPassive (bool flag) noexcept; - void SetEmissionInterval (float interval) noexcept; - void SetMinLife (float val) noexcept; - void SetMaxLife (float val) noexcept; - void SetAngularMin (SHVec3 const& min) noexcept; - void SetAngularMax (SHVec3 const& max) noexcept; - void SetMinVelocity (SHVec3 const& vel) noexcept; - void SetMaxVelocity (SHVec3 const& vel) noexcept; - void SetMinSize (float size) noexcept; - void SetMaxSize (float size) noexcept; + void SetEmissionCount (uint32_t count) noexcept; + void SetPassive (bool flag) noexcept; + void SetEmissionInterval (float interval) noexcept; + void SetMinLife (float val) noexcept; + void SetMaxLife (float val) noexcept; + void SetAngularRangesAndOffsets (SHVec4 const& ranges) noexcept; + void SetMinSpeed (float speed) noexcept; + void SetMaxSpeed (float speed) noexcept; + void SetMinSize (float size) noexcept; + void SetMaxSize (float size) noexcept; - uint32_t GetEmissionCount (void) const noexcept; - bool GetPassive (void) const noexcept; - float GetEmissionInterval (void) const noexcept; - float GetMinLife (void) const noexcept; - float GetMaxLife (void) const noexcept; - SHVec3 GetAngularMax (void) const noexcept; - SHVec3 GetAngularMin (void) const noexcept; - SHVec3 GetMinVelocity (void) const noexcept; - SHVec3 GetMaxVelocity (void) const noexcept; - float GetMinSize (void) const noexcept; - float GetMaxSize (void) const noexcept; + uint32_t GetEmissionCount (void) const noexcept; + bool GetPassive (void) const noexcept; + float GetEmissionInterval (void) const noexcept; + float GetMinLife (void) const noexcept; + float GetMaxLife (void) const noexcept; + SHVec4 const& GetAngularRangesAndOffsets (void) const noexcept; + float GetMinSpeed (void) const noexcept; + float GetMaxSpeed (void) const noexcept; + float GetMinSize (void) const noexcept; + float GetMaxSize (void) const noexcept; friend class SHParticleSubSystem; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.cpp index 7e1e9455..665f43aa 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.cpp @@ -23,7 +23,7 @@ namespace SHADE void SHParticleSubSystem::InitializeComponent(SHParticleEmitterComponent& comp) noexcept { // TODO: temporary only. - static constexpr uint32_t NUM_PARTICLES = 5; + static constexpr uint32_t NUM_PARTICLES = 2000; comp.maxParticles = NUM_PARTICLES; uint32_t sizeofUint = static_cast(sizeof(uint32_t)); @@ -166,34 +166,46 @@ namespace SHADE //cmdBuffer->DrawArrays(4, 1, 0, 0); } - void SHParticleSubSystem::PreparePrePostUpdateBarriers(std::vector& preUpdateBarriers, std::vector& postUpdateBarriers, std::vector& preDrawBarriers, SHParticleEmitterComponent const& emitter, uint32_t const EMITTER_INDEX, uint32_t const FRAME_INDEX) noexcept + void SHParticleSubSystem::PreparePrePostUpdateBarriers(std::vector& preUpdateBarriers, std::vector& postUpdateBarriers, SHParticleEmitterComponent const& emitter, uint32_t const EMITTER_INDEX, uint32_t const FRAME_INDEX) noexcept { // pre-update particles data barrier. Note that this is for input because we want the input to be available before we use it. - vk::BufferMemoryBarrier particleDataBarrier + vk::BufferMemoryBarrier inputParticleDataBarrierPreUpdate { - .srcAccessMask = vk::AccessFlagBits::eShaderWrite, + .srcAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite, .dstAccessMask = vk::AccessFlagBits::eShaderRead, .buffer = emitter.particleData->GetVkBuffer(), .offset = emitter.dynamicOffsets[FRAME_INDEX][DYOFF_INDEX_PARTICLE_INPUT], .size = emitter.chunkSize }; - // pre-update free list data barrier - vk::BufferMemoryBarrier freelistDataBarrier + // pre-update free list data barrier. + vk::BufferMemoryBarrier freelistDataBarrierPreUpdate { - .srcAccessMask = vk::AccessFlagBits::eShaderWrite, - .dstAccessMask = vk::AccessFlagBits::eShaderRead, + .srcAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite, + .dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite, .buffer = emitter.freelistData->GetVkBuffer(), .offset = 0, // Only 1 copy of freelist data, so offset is at 0 .size = static_cast(sizeof (uint32_t)) * (emitter.maxParticles + 1) }; + // pre update indices data barrier. + vk::BufferMemoryBarrier indicesDataBarrierPreUpdate + { + + .srcAccessMask = vk::AccessFlagBits::eShaderWrite | vk::AccessFlagBits::eShaderRead, + .dstAccessMask = vk::AccessFlagBits::eShaderWrite, + .buffer = emitter.indicesData->GetVkBuffer(), + .offset = emitter.dynamicOffsets[FRAME_INDEX][DYOFF_INDEX_INDICES_DATA], + .size = static_cast(sizeof(uint32_t)) * emitter.maxParticles + }; + // ...copy assign barriers on heap - preUpdateBarriers[EMITTER_INDEX * 2] = particleDataBarrier; - preUpdateBarriers[(EMITTER_INDEX * 2) + 1] = freelistDataBarrier; + preUpdateBarriers[EMITTER_INDEX * 3] = inputParticleDataBarrierPreUpdate; + preUpdateBarriers[(EMITTER_INDEX * 3) + 1] = freelistDataBarrierPreUpdate; + preUpdateBarriers[(EMITTER_INDEX * 3) + 2] = indicesDataBarrierPreUpdate; // make new barrier on stack... - vk::BufferMemoryBarrier particleDataBarrierPost + vk::BufferMemoryBarrier outputParticleDataBarrierPostUpdate { .srcAccessMask = vk::AccessFlagBits::eShaderWrite, .dstAccessMask = vk::AccessFlagBits::eShaderRead, @@ -203,7 +215,7 @@ namespace SHADE }; // make new barrier on stack... - vk::BufferMemoryBarrier indicesDataBarrier + vk::BufferMemoryBarrier indicesDataBarrierPostUpdate { .srcAccessMask = vk::AccessFlagBits::eShaderWrite, .dstAccessMask = vk::AccessFlagBits::eShaderRead, @@ -213,9 +225,9 @@ namespace SHADE }; // make new barrier on stack... - vk::BufferMemoryBarrier drawDataBarrier + vk::BufferMemoryBarrier drawDataBarrierPostUpdate { - .srcAccessMask = vk::AccessFlagBits::eShaderWrite | vk::AccessFlagBits::eMemoryWrite, + .srcAccessMask = vk::AccessFlagBits::eShaderWrite, .dstAccessMask = vk::AccessFlagBits::eIndirectCommandRead, .buffer = emitter.drawCallData->GetVkBuffer(), .offset = emitter.dynamicOffsets[FRAME_INDEX][DYOFF_INDEX_DRAW_DATA], @@ -223,9 +235,9 @@ namespace SHADE }; // ...copy assign barriers on heap - postUpdateBarriers[EMITTER_INDEX * 2] = particleDataBarrierPost; - postUpdateBarriers[(EMITTER_INDEX * 2) + 1] = indicesDataBarrier; - preDrawBarriers[EMITTER_INDEX] = drawDataBarrier; + postUpdateBarriers[EMITTER_INDEX * 3] = outputParticleDataBarrierPostUpdate; + postUpdateBarriers[(EMITTER_INDEX * 3) + 1] = indicesDataBarrierPostUpdate; + postUpdateBarriers[(EMITTER_INDEX * 3) + 2] = drawDataBarrierPostUpdate; } void SHParticleSubSystem::Init(Handle device, Handle inDescPool, Handle compatibleRenderpass, Handle subpass, Handle VS, Handle FS, Handle emitCS, Handle defaultUpdateCS) noexcept @@ -322,12 +334,12 @@ 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() * 2); + preUpdateBarriers.resize(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() * 2); + postUpdateBarriers.resize(emitters.size() * 3); std::vector preDrawBarriers{}; preDrawBarriers.resize(emitters.size()); @@ -340,8 +352,6 @@ namespace SHADE /* BEGIN EMITTING PARTICES */ /*-----------------------------------------------------------------------*/ - // TODO: Might need to issue a barrier here for input particle data - // bind the pipeline for emitting particles cmdBuffer->BindPipeline(emittingPipelineData.pipeline); @@ -385,7 +395,7 @@ namespace SHADE } // prepare barriers - PreparePrePostUpdateBarriers(preUpdateBarriers, postUpdateBarriers, preDrawBarriers, emitter, i, frameIndex); + 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; @@ -393,7 +403,7 @@ namespace SHADE } // issue the barrier to wait - cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eComputeShader, vk::PipelineStageFlagBits::eComputeShader, {}, {}, preUpdateBarriers, {}); + cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eComputeShader | vk::PipelineStageFlagBits::eVertexShader | vk::PipelineStageFlagBits::eDrawIndirect, vk::PipelineStageFlagBits::eComputeShader, {}, {}, preUpdateBarriers, {}); @@ -414,39 +424,13 @@ namespace SHADE /* 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::eComputeShader, {}, {}, postUpdateBarriers, {}); - cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eComputeShader, vk::PipelineStageFlagBits::eDrawIndirect, {}, {}, preDrawBarriers, {}); + cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eComputeShader, vk::PipelineStageFlagBits::eVertexShader | vk::PipelineStageFlagBits::eDrawIndirect | vk::PipelineStageFlagBits::eVertexShader, {}, {}, postUpdateBarriers, {}); } void SHParticleSubSystem::ResetInstanceCounts(Handle cmdBuffer, uint32_t frameIndex) noexcept { auto& emitters = SHComponentManager::GetDense(); - std::vector preResetBarriers{}; - preResetBarriers.resize(emitters.size()); - - uint32_t i = 0; - for (auto& emitter : emitters) - { - if (emitter.initialized) - { - // pre-update particles data barrier. Note that this is for input because we want the input to be available before we use it. - vk::BufferMemoryBarrier drawDataHostWriteBarrier - { - .srcAccessMask = vk::AccessFlagBits::eIndirectCommandRead | vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite, - .dstAccessMask = vk::AccessFlagBits::eMemoryWrite | vk::AccessFlagBits::eHostWrite, - .buffer = emitter.drawCallData->GetVkBuffer(), - .offset = emitter.dynamicOffsets[frameIndex][DYOFF_INDEX_DRAW_DATA], - .size = static_cast(sizeof(vk::DrawIndirectCommand)) - }; - - preResetBarriers[i] = drawDataHostWriteBarrier; - } - ++i; - } - - cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eDrawIndirect, vk::PipelineStageFlagBits::eHost, {}, {}, preResetBarriers, {}); - for (auto& emitter : emitters) { diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.h index bb8f570d..ec7418cd 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.h @@ -73,7 +73,7 @@ namespace SHADE //! Pipeline data for updating particles PipelineData defaultUpdatePipelineData; - //! Desc pool for particle component desc set allocation + //! Desc pool for particle component desc set allocation Handle descPool; @@ -82,7 +82,7 @@ namespace SHADE void UpdateCompoennt(Handle cmdBuffer, SHParticleEmitterComponent& comp, uint32_t frameIndex) noexcept; void RenderComponent(Handle cmdBuffer, SHParticleEmitterComponent& comp, uint32_t frameIndex) noexcept; - void PreparePrePostUpdateBarriers (std::vector& preUpdateBarriers, std::vector& postUpdateBarriers, std::vector& preDrawBarriers, SHParticleEmitterComponent const& emitter, uint32_t const EMITTER_INDEX, uint32_t const FRAME_INDEX) noexcept; + void PreparePrePostUpdateBarriers (std::vector& preUpdateBarriers, std::vector& postUpdateBarriers, SHParticleEmitterComponent const& emitter, uint32_t const EMITTER_INDEX, uint32_t const FRAME_INDEX) noexcept; public: void Init(Handle device, Handle inDescPool, Handle compatibleRenderpass, Handle subpass, Handle VS, Handle FS, Handle emitCS, Handle defaultUpdateCS) noexcept; diff --git a/SHADE_Engine/src/Serialization/SHYAMLConverters.h b/SHADE_Engine/src/Serialization/SHYAMLConverters.h index 6826efa7..b5f0ffdf 100644 --- a/SHADE_Engine/src/Serialization/SHYAMLConverters.h +++ b/SHADE_Engine/src/Serialization/SHYAMLConverters.h @@ -509,12 +509,11 @@ namespace YAML static constexpr std::string_view EMISSION_INTERVAL_TAG = "Emission Interval"; static constexpr std::string_view MIN_LIFE_TAG = "Min Life"; static constexpr std::string_view MAX_LIFE_TAG = "Max Life"; - static constexpr std::string_view ANGULAR_MIN_TAG = "Angular Min"; - static constexpr std::string_view ANGULAR_MAX_TAG = "Angular Max"; - static constexpr std::string_view MIN_VEL_TAG = "Minimum Velocity"; - static constexpr std::string_view MAX_VEL_TAG = "Maximum Velocity"; + static constexpr std::string_view ANGULAR_RANGES_OFFSET_TAG = "Angular Ranges And Offset"; static constexpr std::string_view MIN_SIZE_TAG = "Minimum Size"; 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 YAML::Node encode(SHParticleEmitterComponent const& rhs) { @@ -524,12 +523,11 @@ namespace YAML node[EMISSION_INTERVAL_TAG.data()] = rhs.GetEmissionInterval(); node[MIN_LIFE_TAG.data()] = rhs.GetMinLife(); node[MAX_LIFE_TAG.data()] = rhs.GetMaxLife(); - node[ANGULAR_MIN_TAG.data()] = rhs.GetAngularMin(); - node[ANGULAR_MAX_TAG.data()] = rhs.GetAngularMax(); - node[MIN_VEL_TAG.data()] = rhs.GetMinVelocity(); - node[MAX_VEL_TAG.data()] = rhs.GetMaxVelocity(); + node[MIN_SPEED_TAG.data()] = rhs.GetMinSpeed(); + node[MAX_SPEED_TAG.data()] = rhs.GetMaxSpeed(); node[MIN_SIZE_TAG.data()] = rhs.GetMinSize(); node[MAX_SIZE_TAG.data()] = rhs.GetMaxSize(); + node[ANGULAR_RANGES_OFFSET_TAG.data()] = rhs.GetAngularRangesAndOffsets(); return node; } @@ -550,20 +548,14 @@ namespace YAML if (node[MAX_LIFE_TAG.data()].IsDefined()) rhs.SetMaxLife(node[MAX_LIFE_TAG.data()].as()); - if (node[ANGULAR_MIN_TAG.data()].IsDefined()) - rhs.SetAngularMin(node[ANGULAR_MIN_TAG.data()].as()); + if (node[ANGULAR_RANGES_OFFSET_TAG.data()].IsDefined()) + rhs.SetAngularRangesAndOffsets(node[ANGULAR_RANGES_OFFSET_TAG.data()].as()); - if (node[ANGULAR_MAX_TAG.data()].IsDefined()) - rhs.SetAngularMax(node[ANGULAR_MAX_TAG.data()].as()); + if (node[MIN_SPEED_TAG.data()].IsDefined()) + rhs.SetMinSpeed(node[MIN_SPEED_TAG.data()].as()); - if (node[MIN_VEL_TAG.data()].IsDefined()) - rhs.SetMinVelocity(node[MIN_VEL_TAG.data()].as()); - - if (node[MAX_VEL_TAG.data()].IsDefined()) - rhs.SetMaxVelocity(node[MAX_VEL_TAG.data()].as()); - - if (node[MIN_SIZE_TAG.data()].IsDefined()) - rhs.SetMinSize(node[MIN_SIZE_TAG.data()].as()); + if (node[MAX_SPEED_TAG.data()].IsDefined()) + rhs.SetMaxSpeed (node[MAX_SPEED_TAG.data()].as()); if (node[MAX_SIZE_TAG.data()].IsDefined()) rhs.SetMaxSize(node[MAX_SIZE_TAG.data()].as());