Improved particles and trajectory rendering #430
|
@ -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: ~
|
|
@ -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);
|
||||
|
|
Binary file not shown.
|
@ -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;
|
||||
}
|
Binary file not shown.
|
@ -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);
|
||||
}
|
Binary file not shown.
|
@ -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); });
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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<uint32_t>(sizeof(uint32_t));
|
||||
|
@ -166,34 +166,46 @@ namespace SHADE
|
|||
//cmdBuffer->DrawArrays(4, 1, 0, 0);
|
||||
}
|
||||
|
||||
void SHParticleSubSystem::PreparePrePostUpdateBarriers(std::vector<vk::BufferMemoryBarrier>& preUpdateBarriers, std::vector<vk::BufferMemoryBarrier>& postUpdateBarriers, std::vector<vk::BufferMemoryBarrier>& preDrawBarriers, SHParticleEmitterComponent const& emitter, uint32_t const EMITTER_INDEX, uint32_t const FRAME_INDEX) noexcept
|
||||
void SHParticleSubSystem::PreparePrePostUpdateBarriers(std::vector<vk::BufferMemoryBarrier>& preUpdateBarriers, std::vector<vk::BufferMemoryBarrier>& 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<uint32_t>(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<uint32_t>(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<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> inDescPool, Handle<SHVkRenderpass> compatibleRenderpass, Handle<SHSubpass> subpass, Handle<SHVkShaderModule> VS, Handle<SHVkShaderModule> FS, Handle<SHVkShaderModule> emitCS, Handle<SHVkShaderModule> 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<vk::BufferMemoryBarrier> 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<vk::BufferMemoryBarrier> postUpdateBarriers{};
|
||||
postUpdateBarriers.resize(emitters.size() * 2);
|
||||
postUpdateBarriers.resize(emitters.size() * 3);
|
||||
|
||||
std::vector<vk::BufferMemoryBarrier> 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<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
|
||||
{
|
||||
auto& emitters = SHComponentManager::GetDense<SHParticleEmitterComponent>();
|
||||
std::vector<vk::BufferMemoryBarrier> 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<uint32_t>(sizeof(vk::DrawIndirectCommand))
|
||||
};
|
||||
|
||||
preResetBarriers[i] = drawDataHostWriteBarrier;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eDrawIndirect, vk::PipelineStageFlagBits::eHost, {}, {}, preResetBarriers, {});
|
||||
|
||||
|
||||
for (auto& emitter : emitters)
|
||||
{
|
||||
|
|
|
@ -82,7 +82,7 @@ namespace SHADE
|
|||
void UpdateCompoennt(Handle<SHVkCommandBuffer> cmdBuffer, SHParticleEmitterComponent& comp, uint32_t frameIndex) noexcept;
|
||||
void RenderComponent(Handle<SHVkCommandBuffer> cmdBuffer, SHParticleEmitterComponent& comp, uint32_t frameIndex) noexcept;
|
||||
|
||||
void PreparePrePostUpdateBarriers (std::vector<vk::BufferMemoryBarrier>& preUpdateBarriers, std::vector<vk::BufferMemoryBarrier>& postUpdateBarriers, std::vector<vk::BufferMemoryBarrier>& preDrawBarriers, SHParticleEmitterComponent const& emitter, uint32_t const EMITTER_INDEX, uint32_t const FRAME_INDEX) noexcept;
|
||||
void PreparePrePostUpdateBarriers (std::vector<vk::BufferMemoryBarrier>& preUpdateBarriers, std::vector<vk::BufferMemoryBarrier>& postUpdateBarriers, SHParticleEmitterComponent const& emitter, uint32_t const EMITTER_INDEX, uint32_t const FRAME_INDEX) noexcept;
|
||||
|
||||
public:
|
||||
void Init(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> inDescPool, Handle<SHVkRenderpass> compatibleRenderpass, Handle<SHSubpass> subpass, Handle<SHVkShaderModule> VS, Handle<SHVkShaderModule> FS, Handle<SHVkShaderModule> emitCS, Handle<SHVkShaderModule> defaultUpdateCS) noexcept;
|
||||
|
|
|
@ -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<float>());
|
||||
|
||||
if (node[ANGULAR_MIN_TAG.data()].IsDefined())
|
||||
rhs.SetAngularMin(node[ANGULAR_MIN_TAG.data()].as<SHVec3>());
|
||||
if (node[ANGULAR_RANGES_OFFSET_TAG.data()].IsDefined())
|
||||
rhs.SetAngularRangesAndOffsets(node[ANGULAR_RANGES_OFFSET_TAG.data()].as<SHVec4>());
|
||||
|
||||
if (node[ANGULAR_MAX_TAG.data()].IsDefined())
|
||||
rhs.SetAngularMax(node[ANGULAR_MAX_TAG.data()].as<SHVec3>());
|
||||
if (node[MIN_SPEED_TAG.data()].IsDefined())
|
||||
rhs.SetMinSpeed(node[MIN_SPEED_TAG.data()].as<float>());
|
||||
|
||||
if (node[MIN_VEL_TAG.data()].IsDefined())
|
||||
rhs.SetMinVelocity(node[MIN_VEL_TAG.data()].as<SHVec3>());
|
||||
|
||||
if (node[MAX_VEL_TAG.data()].IsDefined())
|
||||
rhs.SetMaxVelocity(node[MAX_VEL_TAG.data()].as<SHVec3>());
|
||||
|
||||
if (node[MIN_SIZE_TAG.data()].IsDefined())
|
||||
rhs.SetMinSize(node[MIN_SIZE_TAG.data()].as<float>());
|
||||
if (node[MAX_SPEED_TAG.data()].IsDefined())
|
||||
rhs.SetMaxSpeed (node[MAX_SPEED_TAG.data()].as<float>());
|
||||
|
||||
if (node[MAX_SIZE_TAG.data()].IsDefined())
|
||||
rhs.SetMaxSize(node[MAX_SIZE_TAG.data()].as<float>());
|
||||
|
|
Loading…
Reference in New Issue