Implemented serialization for text color and trajectory rendering #381
|
@ -0,0 +1,117 @@
|
|||
#version 450
|
||||
|
||||
layout(local_size_x = 128) in;
|
||||
|
||||
struct EmitterParameters
|
||||
{
|
||||
vec4 angularMin;
|
||||
vec4 angularMax;
|
||||
vec4 lifeAndSizeRange; // min life, max life, min size, max size
|
||||
}
|
||||
|
||||
struct ParticleData
|
||||
{
|
||||
vec4 position;
|
||||
vec4 rotation;
|
||||
vec4 velocity;
|
||||
vec4 acceleration;
|
||||
vec4 scaleAndDecay;
|
||||
float life;
|
||||
uint textureIndex;
|
||||
}
|
||||
|
||||
struct GenericData
|
||||
{
|
||||
//! Delta time
|
||||
float dt;
|
||||
|
||||
//! Elapsed time of the application
|
||||
float elapsedTime;
|
||||
|
||||
//! Viewport width of the scene (excluding imgui, that means smaller than window)
|
||||
uint viewportWidth;
|
||||
|
||||
//! Ditto but for height
|
||||
uint viewportHeight;
|
||||
};
|
||||
|
||||
layout (set = 0, binding = 0) uniform GenericDataBuffer
|
||||
{
|
||||
GenericData data;
|
||||
} genericDataBuffer;
|
||||
|
||||
layout (std430, set = 2, binding = 0) readonly buffer EmitterBuffer
|
||||
{
|
||||
EmitterParameters data;
|
||||
} emitterParams;
|
||||
|
||||
layout (std430, set = 2, binding = 1) coherent restrict buffer ParticlesInputBuffer
|
||||
{
|
||||
ParticleData data[];
|
||||
} inputParticles;
|
||||
|
||||
// output buffer not needed
|
||||
// layout (std430, set = 2, binding = 2) coherent restrict buffer ParticlesOutputBuffer
|
||||
// {
|
||||
// ParticleData data[];
|
||||
// } outputParticles;
|
||||
|
||||
layout (std430, set = 2, binding = 3) coherent restrict buffer ParticlesFreelistBuffer
|
||||
{
|
||||
int freeCount;
|
||||
int freeIndices[];
|
||||
|
||||
} freelist;
|
||||
|
||||
|
||||
// push constants
|
||||
layout(std140, push_constant) uniform EmitterPushConstant
|
||||
{
|
||||
vec4 emitterPosition;
|
||||
uint emissionCount;
|
||||
|
||||
} emitterPushConstant;
|
||||
|
||||
uint pcg_hash(uint seed)
|
||||
{
|
||||
uint state = seed * 747796405u + 2891336453u;
|
||||
uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
|
||||
return (word >> 22u) ^ word;
|
||||
}
|
||||
|
||||
// Used to advance the PCG state.
|
||||
uint rand_pcg(inout uint rng_state)
|
||||
{
|
||||
uint state = rng_state;
|
||||
rng_state = rng_state * 747796405u + 2891336453u;
|
||||
uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
|
||||
return (word >> 22u) ^ word;
|
||||
}
|
||||
|
||||
// Advances the prng state and returns the corresponding random float.
|
||||
float rand(inout uint state)
|
||||
{
|
||||
uint x = rand_pcg(state);
|
||||
state = x;
|
||||
return float(x)*uintBitsToFloat(0x2f800004u);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
uint emitterInvocationIndex = gl_GlobalInvocationID.x;
|
||||
|
||||
if (emitterInvocationIndex >= emitterPushConstant.emissionCount)
|
||||
return;
|
||||
|
||||
int freelistIndex = atomicAdd (freelist.freeCount, -1) - 1;
|
||||
if (freelistIndex < 0)
|
||||
atomicAdd (freelist.freeCount, 1);
|
||||
|
||||
ParticleData particle;
|
||||
|
||||
int index = freelist.freeIndices[freelistIndex];
|
||||
particle.position = emitterPosition;
|
||||
particle.life = emitterParams.10.0f;
|
||||
|
||||
particles[index] = particle;
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
#version 450
|
||||
|
||||
layout(local_size_x = 128) in;
|
||||
|
||||
struct DrawArraysIndirectArgs
|
||||
{
|
||||
uint count;
|
||||
uint instanceCount;
|
||||
uint first;
|
||||
uint baseInstance;
|
||||
};
|
||||
|
||||
struct ParticleData
|
||||
{
|
||||
vec4 position;
|
||||
vec4 rotation;
|
||||
vec4 velocity;
|
||||
vec4 acceleration;
|
||||
vec4 scaleAndDecay;
|
||||
float life;
|
||||
uint textureIndex;
|
||||
}
|
||||
|
||||
struct GenericData
|
||||
{
|
||||
//! Delta time
|
||||
float dt;
|
||||
|
||||
//! Elapsed time of the application
|
||||
float elapsedTime;
|
||||
|
||||
//! Viewport width of the scene (excluding imgui, that means smaller than window)
|
||||
uint viewportWidth;
|
||||
|
||||
//! Ditto but for height
|
||||
uint viewportHeight;
|
||||
};
|
||||
|
||||
layout(set = 1, binding = 0) uniform CameraData
|
||||
{
|
||||
vec4 position;
|
||||
mat4 vpMat;
|
||||
mat4 viewMat;
|
||||
mat4 projMat;
|
||||
} cameraData;
|
||||
|
||||
|
||||
layout (set = 0, binding = 0) uniform GenericDataBuffer
|
||||
{
|
||||
GenericData data;
|
||||
} genericDataBuffer;
|
||||
|
||||
layout (std430, set = 2, binding = 1) coherent restrict readonly buffer ParticlesInputBuffer
|
||||
{
|
||||
ParticleData data[];
|
||||
} inputParticles;
|
||||
|
||||
// output buffer not needed
|
||||
layout (std430, set = 2, binding = 2) coherent restrict buffer ParticlesOutputBuffer
|
||||
{
|
||||
ParticleData data[];
|
||||
} outputParticles;
|
||||
|
||||
layout (std430, set = 2, binding = 3) coherent restrict buffer ParticlesFreelistBuffer
|
||||
{
|
||||
int freeCount;
|
||||
int freeIndices[];
|
||||
|
||||
} freelist;
|
||||
|
||||
layout (std430, set = 2, binding = 4) coherent restrict buffer IndicesData
|
||||
{
|
||||
uint indices[];
|
||||
};
|
||||
|
||||
layout (std140, set = 2, binding = 5) coherent restrict uniform IndirectDrawArgs
|
||||
{
|
||||
DrawArraysIndirectArgs indirectArgs;
|
||||
};
|
||||
|
||||
// push constants
|
||||
layout(std140, push_constant) uniform EmitterPushConstant
|
||||
{
|
||||
vec4 emitterPosition;
|
||||
uint emissionCount;
|
||||
|
||||
} emitterPushConstant;
|
||||
|
||||
uint pcg_hash(uint seed)
|
||||
{
|
||||
uint state = seed * 747796405u + 2891336453u;
|
||||
uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
|
||||
return (word >> 22u) ^ word;
|
||||
}
|
||||
|
||||
// Used to advance the PCG state.
|
||||
uint rand_pcg(inout uint rng_state)
|
||||
{
|
||||
uint state = rng_state;
|
||||
rng_state = rng_state * 747796405u + 2891336453u;
|
||||
uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
|
||||
return (word >> 22u) ^ word;
|
||||
}
|
||||
|
||||
// Advances the prng state and returns the corresponding random float.
|
||||
float rand(inout uint state)
|
||||
{
|
||||
uint x = rand_pcg(state);
|
||||
state = x;
|
||||
return float(x)*uintBitsToFloat(0x2f800004u);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
uint index = gl_GlobalInvocationID.x;
|
||||
|
||||
ParticleData particle = inputParticles.data[index];
|
||||
|
||||
if (particle.lifetime > 0.0f)
|
||||
{
|
||||
// particle.position += particle.velocity * dt;
|
||||
|
||||
// particle.lifetime -= dt;
|
||||
// particle.size -= 1.2f * dt;
|
||||
// particle.color += 1.0f * dt;
|
||||
|
||||
if (particle.lifetime < 0.0f || particle.size < 0.0f)
|
||||
{
|
||||
particle.lifetime = 0.0f;
|
||||
particle.position.x = 99999.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;
|
||||
}
|
||||
}
|
|
@ -600,7 +600,7 @@ namespace SHADE
|
|||
}
|
||||
);
|
||||
|
||||
SHEditorWidgets::ColorPicker("Color", [&textComp = component]() {return textComp->GetColour(); }, [&textComp = component](SHVec4 const& newColor) {textComp->SetColour(newColor); });
|
||||
SHEditorWidgets::ColorPicker("Color", [&textComp = component]() {return textComp->GetColor(); }, [&textComp = component](SHVec4 const& newColor) {textComp->SetColor(newColor); });
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -180,6 +180,10 @@ namespace SHADE
|
|||
{
|
||||
DrawComponent(listenerComponent);
|
||||
}
|
||||
if (auto trajectoryComponent = SHComponentManager::GetComponent_s<SHTrajectoryRenderableComponent>(eid))
|
||||
{
|
||||
DrawComponent(trajectoryComponent);
|
||||
}
|
||||
ImGui::Separator();
|
||||
// Render Scripts
|
||||
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||
|
@ -195,6 +199,7 @@ namespace SHADE
|
|||
DrawAddComponentButton<SHButtonComponent>(eid);
|
||||
DrawAddComponentButton<SHToggleButtonComponent>(eid);
|
||||
DrawAddComponentButton<SHSliderComponent>(eid);
|
||||
DrawAddComponentButton<SHTrajectoryRenderableComponent>(eid);
|
||||
|
||||
// Components that require Transforms
|
||||
|
||||
|
|
|
@ -59,6 +59,13 @@ namespace SHADE
|
|||
{SHPredefinedDescriptorTypes::STATIC_DATA, 0},
|
||||
{SHPredefinedDescriptorTypes::CAMERA, 1},
|
||||
});
|
||||
|
||||
perSystemData[SHUtilities::ConvertEnum(SystemType::PARTICLE_RENEDERING)].descMappings.AddMappings
|
||||
({
|
||||
{SHPredefinedDescriptorTypes::STATIC_DATA, 0},
|
||||
{SHPredefinedDescriptorTypes::CAMERA, 1},
|
||||
{SHPredefinedDescriptorTypes::PARTICLES, 2},
|
||||
});
|
||||
}
|
||||
|
||||
void SHGraphicsPredefinedData::InitDummyPipelineLayouts(Handle<SHVkLogicalDevice> logicalDevice) noexcept
|
||||
|
@ -194,6 +201,73 @@ namespace SHADE
|
|||
Handle<SHVkDescriptorSetLayout> materialBoneDataPerInstanceLayout = logicalDevice->CreateDescriptorSetLayout({ materialDataBinding, boneDataBinding });
|
||||
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, materialBoneDataPerInstanceLayout->GetVkHandle(), "[Descriptor Set Layout] Material and Bone Globals");
|
||||
|
||||
// particle emitter binding
|
||||
SHVkDescriptorSetLayout::Binding emitterDataBinding
|
||||
{
|
||||
.Type = vk::DescriptorType::eStorageBufferDynamic,
|
||||
.Stage = vk::ShaderStageFlagBits::eCompute,
|
||||
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::PARTICLE_EMITTER_DATA,
|
||||
.DescriptorCount = 1,
|
||||
};
|
||||
|
||||
// particle input binding
|
||||
SHVkDescriptorSetLayout::Binding particleInputDataBinding
|
||||
{
|
||||
.Type = vk::DescriptorType::eStorageBufferDynamic,
|
||||
.Stage = vk::ShaderStageFlagBits::eCompute,
|
||||
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::PARTICLE_INPUT_DATA,
|
||||
.DescriptorCount = 1,
|
||||
};
|
||||
|
||||
// particle output binding
|
||||
SHVkDescriptorSetLayout::Binding particleOutputDataBinding
|
||||
{
|
||||
.Type = vk::DescriptorType::eStorageBufferDynamic,
|
||||
.Stage = vk::ShaderStageFlagBits::eCompute | vk::ShaderStageFlagBits::eVertex,
|
||||
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::PARTICLE_OUTPUT_DATA,
|
||||
.DescriptorCount = 1,
|
||||
};
|
||||
|
||||
// particle freelist binding
|
||||
SHVkDescriptorSetLayout::Binding particleFreelistBinding
|
||||
{
|
||||
.Type = vk::DescriptorType::eStorageBuffer, // non dynamic because we only need 1 copy for all frames
|
||||
.Stage = vk::ShaderStageFlagBits::eCompute,
|
||||
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::PARTICLE_FREELIST_DATA,
|
||||
.DescriptorCount = 1,
|
||||
};
|
||||
|
||||
// particle indices binding
|
||||
SHVkDescriptorSetLayout::Binding particleIndicesBinding
|
||||
{
|
||||
.Type = vk::DescriptorType::eStorageBufferDynamic, // dynamic because we have multiple copies.
|
||||
.Stage = vk::ShaderStageFlagBits::eCompute | vk::ShaderStageFlagBits::eVertex,
|
||||
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::PARTICLE_INDICES_DATA,
|
||||
.DescriptorCount = 1,
|
||||
};
|
||||
|
||||
// particle draw call binding
|
||||
SHVkDescriptorSetLayout::Binding particleDrawDataBinding
|
||||
{
|
||||
.Type = vk::DescriptorType::eUniformBufferDynamic, // UBO (Because lesser data), dynamic (1 set for each frame)
|
||||
.Stage = vk::ShaderStageFlagBits::eCompute,
|
||||
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::PARTICLE_DRAW_DATA,
|
||||
.DescriptorCount = 1,
|
||||
};
|
||||
|
||||
Handle<SHVkDescriptorSetLayout> particleDescSetLayout = logicalDevice->CreateDescriptorSetLayout(
|
||||
{
|
||||
emitterDataBinding,
|
||||
particleInputDataBinding,
|
||||
particleOutputDataBinding,
|
||||
particleFreelistBinding,
|
||||
particleIndicesBinding,
|
||||
particleDrawDataBinding
|
||||
});
|
||||
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, particleDescSetLayout->GetVkHandle(), "[Descriptor Set Layout] Particle System Data");
|
||||
|
||||
|
||||
|
||||
predefinedLayouts.push_back(staticGlobalLayout);
|
||||
predefinedLayouts.push_back(lightDataDescSetLayout);
|
||||
predefinedLayouts.push_back(cameraDataGlobalLayout);
|
||||
|
@ -201,6 +275,7 @@ namespace SHADE
|
|||
predefinedLayouts.push_back(fontDataDescSetLayout);
|
||||
predefinedLayouts.push_back(shadowMapDescLayout);
|
||||
predefinedLayouts.push_back(materialBoneDataPerInstanceLayout);
|
||||
predefinedLayouts.push_back(particleDescSetLayout);
|
||||
|
||||
perSystemData[SHUtilities::ConvertEnum(SystemType::BATCHING)].descSetLayouts = GetPredefinedDescSetLayouts
|
||||
(
|
||||
|
@ -235,6 +310,13 @@ namespace SHADE
|
|||
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::STATIC_DATA |
|
||||
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::CAMERA
|
||||
);
|
||||
|
||||
perSystemData[SHUtilities::ConvertEnum(SystemType::PARTICLE_RENEDERING)].descSetLayouts = GetPredefinedDescSetLayouts
|
||||
(
|
||||
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::STATIC_DATA |
|
||||
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::CAMERA |
|
||||
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::PARTICLES
|
||||
);
|
||||
}
|
||||
|
||||
void SHGraphicsPredefinedData::InitPredefinedVertexInputState(void) noexcept
|
||||
|
|
|
@ -29,7 +29,8 @@ namespace SHADE
|
|||
MATERIALS = 0b00001000,
|
||||
FONT = 0b00010000,
|
||||
SHADOW = 0b00100000,
|
||||
MATERIAL_AND_BONES = 0b01000000
|
||||
MATERIAL_AND_BONES = 0b01000000,
|
||||
PARTICLES = 0b10000000
|
||||
};
|
||||
|
||||
enum class SystemType
|
||||
|
@ -39,6 +40,7 @@ namespace SHADE
|
|||
TEXT_RENDERING,
|
||||
RENDER_GRAPH_NODE_COMPUTE,
|
||||
TRAJECTORY_RENDERING,
|
||||
PARTICLE_RENEDERING,
|
||||
NUM_TYPES
|
||||
};
|
||||
static constexpr int SYSTEM_TYPE_COUNT = static_cast<int>(SystemType::NUM_TYPES);
|
||||
|
|
|
@ -16,5 +16,6 @@ namespace SHADE
|
|||
FONT,
|
||||
RENDER_GRAPH_NODE_COMPUTE_RESOURCE,
|
||||
RENDER_GRAPH_RESOURCE,
|
||||
PARTICLES,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -233,6 +233,61 @@ namespace SHADE
|
|||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr uint32_t BONE_MATRIX_DATA = 1;
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
Descriptor set binding for particle emitter data.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr uint32_t PARTICLE_EMITTER_DATA = 0;
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
Descriptor set binding for input particle data.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr uint32_t PARTICLE_INPUT_DATA = 1;
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
Descriptor set binding for output particle data.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr uint32_t PARTICLE_OUTPUT_DATA = 2;
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
Descriptor set binding for particle freelist data.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr uint32_t PARTICLE_FREELIST_DATA = 3;
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
Descriptor set binding for particle indices data.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr uint32_t PARTICLE_INDICES_DATA = 4;
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
Descriptor set binding for bone matrix data.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr uint32_t PARTICLE_DRAW_DATA = 5;
|
||||
|
||||
};
|
||||
|
||||
struct VertexBufferBindings
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHParticleEmitterComponent.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
||||
void SHParticleEmitterComponent::OnCreate(void)
|
||||
{
|
||||
timeBeforeEmission = emissionInterval;
|
||||
|
||||
}
|
||||
|
||||
void SHParticleEmitterComponent::OnDestroy(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SHParticleEmitterComponent::Emit(void) noexcept
|
||||
{
|
||||
toEmit = true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
#pragma once
|
||||
|
||||
#include "Resource/SHHandle.h"
|
||||
#include "Math/Vector/SHVec4.h"
|
||||
#include "ECS_Base/Components/SHComponent.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHVkBuffer;
|
||||
class SHVkDescriptorSetGroup;
|
||||
class SHVkDescriptorSetLayout;
|
||||
|
||||
class SHParticleEmitterComponent : public SHComponent
|
||||
{
|
||||
private:
|
||||
struct GPUEmitterStruct
|
||||
{
|
||||
//! Minimum emitting angular range
|
||||
SHVec4 angularMin;
|
||||
|
||||
//! Maximum emitting angular range
|
||||
SHVec4 angularMax;
|
||||
|
||||
//! Spawn lifetime and size range (min and max)
|
||||
SHVec4 lifeAndSizeRange;
|
||||
};
|
||||
|
||||
struct GPUParticleStruct
|
||||
{
|
||||
//! Position of the particle
|
||||
SHVec4 position;
|
||||
|
||||
//! Rotation of the particle
|
||||
SHVec4 rotation;
|
||||
|
||||
//! Velocity of the particle
|
||||
SHVec4 velocity;
|
||||
|
||||
//! Acceleration of the particle
|
||||
SHVec4 acceleration;
|
||||
|
||||
//! x scale, x scale decay, y scale and y scale decay
|
||||
SHVec4 scaleAndDecay;
|
||||
|
||||
//! Life of the particle
|
||||
float life;
|
||||
|
||||
//! Texture into the desc array that the particle is using
|
||||
uint32_t textureIndex;
|
||||
};
|
||||
|
||||
//! Max number of particles of this emitter
|
||||
uint32_t maxParticles;
|
||||
|
||||
//! num bytes of all particles in 1 chunk (1 frame)
|
||||
uint32_t chunkSize;
|
||||
|
||||
//! emission count per emit
|
||||
uint32_t emissionCount;
|
||||
|
||||
//! emission interval of the emitter
|
||||
float emissionInterval;
|
||||
|
||||
//! Counter that decreases to 0 from emissionInterval. When 0, emit particles.
|
||||
float timeBeforeEmission;
|
||||
|
||||
//! Data for the emitter
|
||||
Handle<SHVkBuffer> emitterData;
|
||||
|
||||
//! GPU Particle data
|
||||
Handle<SHVkBuffer> particleData;
|
||||
|
||||
//! Freelist data
|
||||
Handle<SHVkBuffer> freelistData;
|
||||
|
||||
//! Indices data
|
||||
Handle<SHVkBuffer> indicesData;
|
||||
|
||||
//! draw call data
|
||||
Handle<SHVkBuffer> drawCallData;
|
||||
|
||||
//! We need more descriptor sets because the operations on a frame's particle data needs to rely on the previous frame's. Each set
|
||||
//! will contain 2 bindings that point to 2 buffers (input and output).
|
||||
Handle<SHVkDescriptorSetGroup> particleDescriptorSet;
|
||||
|
||||
//! Emitter's data on the CPU side. To be copied to GPU.
|
||||
GPUEmitterStruct cpuEmitterData;
|
||||
|
||||
//! If passive, emitter emits particles based on timer above.
|
||||
bool isPassive;
|
||||
|
||||
//! Have the particle system initialize variables in this component when this is false
|
||||
bool initialized;
|
||||
|
||||
//! If true, particle system will emit particles in Run function. Sets to false every frame.
|
||||
bool toEmit;
|
||||
|
||||
//! For all the dynamic SSBOs in the descriptor set
|
||||
std::array<std::array<uint32_t, 5>, SHGraphicsConstants::NUM_FRAME_BUFFERS> dynamicOffsets{};
|
||||
|
||||
public:
|
||||
void OnCreate(void) override final;
|
||||
void OnDestroy(void) override final;
|
||||
|
||||
void Emit (void) noexcept;
|
||||
|
||||
friend class SHParticleSubSystem;
|
||||
|
||||
};
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "Resource/SHHandle.h"
|
||||
#include "Graphics/Pipeline/SHPipelineState.h"
|
||||
#include "Math/SHMatrix.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHVkLogicalDevice;
|
||||
class SHVkDescriptorPool;
|
||||
class SHVkDescriptorSetGroup;
|
||||
class SHVkDescriptorSetLayout;
|
||||
class SHVkBuffer;
|
||||
class SHLightComponent;
|
||||
class SHVkCommandBuffer;
|
||||
class SHVkPipeline;
|
||||
class SHVkPipelineLayout;
|
||||
class SHVkRenderpass;
|
||||
class SHSubpass;
|
||||
class SHVkShaderModule;
|
||||
class SHRenderer;
|
||||
|
||||
|
||||
|
||||
class SHParticleSubSystem
|
||||
{
|
||||
private:
|
||||
|
||||
Handle<SHVkLogicalDevice> logicalDevice;
|
||||
|
||||
|
||||
public:
|
||||
void Init(Handle<SHVkLogicalDevice> device, Handle<SHVkRenderpass> compatibleRenderpass, Handle<SHSubpass> subpass) noexcept;
|
||||
|
||||
void Run(uint32_t frameIndex) noexcept;
|
||||
|
||||
void Render(Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHRenderer> renderer, uint32_t frameIndex) noexcept;
|
||||
void Exit(void) noexcept;
|
||||
|
||||
};
|
||||
}
|
|
@ -1,7 +1,309 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHParticleSubSustem.h"
|
||||
#include "SHParticleSubSystem.h"
|
||||
#include "Graphics/Pipeline/SHPipelineLayoutParams.h"
|
||||
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.h"
|
||||
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
||||
#include "Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h"
|
||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||
#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
|
||||
#include "Graphics/MiddleEnd/GlobalData/SHGlobalDescriptorSets.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
#include "Graphics/Buffers/SHVkBuffer.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
||||
void SHParticleSubSystem::InitializeComponent(SHParticleEmitterComponent& comp) noexcept
|
||||
{
|
||||
uint32_t emitterStructAligned = logicalDevice->PadSSBOSize(sizeof (SHParticleEmitterComponent::GPUEmitterStruct));
|
||||
uint32_t particleStructAligned = logicalDevice->PadUBOSize(sizeof (SHParticleEmitterComponent::GPUParticleStruct));
|
||||
uint32_t sizeofIndirectCmd = static_cast<uint32_t>(sizeof(vk::DrawIndirectCommand));
|
||||
uint32_t sizeofUint = static_cast<uint32_t>(sizeof(uint32_t));
|
||||
|
||||
// TODO: temporary only.
|
||||
static constexpr uint32_t NUM_PARTICLES = 500;
|
||||
comp.maxParticles = NUM_PARTICLES;
|
||||
|
||||
// offset into the buffer for input and output
|
||||
uint32_t const PARTICLE_FRAME_CHUNK_SIZE = (particleStructAligned * comp.maxParticles);
|
||||
|
||||
// Buffer Initialization
|
||||
{
|
||||
// count, value
|
||||
std::vector<uint32_t> freelistInit(comp.maxParticles + 1, 0);
|
||||
freelistInit[0] = comp.maxParticles;
|
||||
|
||||
// Particle emitter buffer. Multiple copies, Host-visible mapped. We want multiple copies because we'll be writing to it from the CPU. We don't want to do that while the GPU
|
||||
// is using it during compute operations so we write to another portion.
|
||||
comp.emitterData = logicalDevice->CreateBuffer(SHGraphicsConstants::NUM_FRAME_BUFFERS * emitterStructAligned, nullptr, 0, vk::BufferUsageFlagBits::eStorageBuffer, VMA_MEMORY_USAGE_AUTO, VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_MAPPED_BIT);
|
||||
|
||||
// buffer for particle data: pure GPU memory, no transfers, no flags. We want to triple buffer this so that we can submit work to the GPU
|
||||
// without having to wait for rendering to finish reading the data
|
||||
comp.particleData = logicalDevice->CreateBuffer(SHGraphicsConstants::NUM_FRAME_BUFFERS * particleStructAligned * NUM_PARTICLES, nullptr, 0, vk::BufferUsageFlagBits::eStorageBuffer, VMA_MEMORY_USAGE_AUTO, {});
|
||||
|
||||
// Buffer for freelist data. 1 copy only, host-visible mapped. We only need 1 copy because it is only required in compute. If it was used or read in another
|
||||
// stage we would need more copies.
|
||||
comp.freelistData = logicalDevice->CreateBuffer(sizeofUint * (comp.maxParticles + 1), freelistInit.data(), sizeofUint * (comp.maxParticles + 1), vk::BufferUsageFlagBits::eStorageBuffer, VMA_MEMORY_USAGE_AUTO, VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_MAPPED_BIT);
|
||||
|
||||
// Buffer for indices. NUM_FRAME_BUFFERS copies since it's used in rendering. host-visible mapped.
|
||||
comp.indicesData = logicalDevice->CreateBuffer(sizeofUint * comp.maxParticles, nullptr, 0, vk::BufferUsageFlagBits::eStorageBuffer, VMA_MEMORY_USAGE_AUTO, VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_MAPPED_BIT);
|
||||
|
||||
// Draw call data will not be tampered with after this initialization except for one variable: instanceCount, which will be modified from compute shader
|
||||
std::array<vk::DrawIndirectCommand, SHGraphicsConstants::NUM_FRAME_BUFFERS> indirectCommands{};
|
||||
for (auto& cmd : indirectCommands)
|
||||
{
|
||||
cmd.vertexCount = 4;
|
||||
cmd.firstVertex = 0;
|
||||
cmd.firstInstance = 0;
|
||||
cmd.instanceCount = 0;
|
||||
}
|
||||
|
||||
// buffer to store draw call data. Non-indexed, host-visible mapped, triple buffered.
|
||||
comp.drawCallData = logicalDevice->CreateBuffer(SHGraphicsConstants::NUM_FRAME_BUFFERS * sizeofIndirectCmd, indirectCommands.data(), SHGraphicsConstants::NUM_FRAME_BUFFERS * sizeofIndirectCmd, vk::BufferUsageFlagBits::eUniformBuffer | vk::BufferUsageFlagBits::eIndirectBuffer, VMA_MEMORY_USAGE_AUTO, VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_MAPPED_BIT);
|
||||
|
||||
}
|
||||
|
||||
// Descriptor set initialization
|
||||
{
|
||||
// Get particle desc set layout
|
||||
auto descSetLayout = SHGraphicsPredefinedData::GetPredefinedDescSetLayouts(SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::PARTICLES);
|
||||
|
||||
// Since we are populating the set as is, the set index will be 0
|
||||
static constexpr uint32_t PARTICLE_DATA_SET_INDEX = 0;
|
||||
|
||||
// Variable desc counts, all ignored anyway (This is required but its a dumb interface. You can only blame yourself, Brandon. )
|
||||
std::vector const VARIABLE_COUNTS = {0u,0u,0u,0u,0u};
|
||||
|
||||
// allocate new desc set
|
||||
comp.particleDescriptorSet = descPool->Allocate(descSetLayout, VARIABLE_COUNTS);
|
||||
|
||||
// convenience handle
|
||||
auto set = comp.particleDescriptorSet;
|
||||
|
||||
// After buffers are created, we want to populate all bindings(6) with the buffers
|
||||
set->ModifyWriteDescBuffer(PARTICLE_DATA_SET_INDEX, SHGraphicsConstants::DescriptorSetBindings::PARTICLE_EMITTER_DATA, { &comp.emitterData, 1 }, 0, emitterStructAligned);
|
||||
set->ModifyWriteDescBuffer(PARTICLE_DATA_SET_INDEX, SHGraphicsConstants::DescriptorSetBindings::PARTICLE_INPUT_DATA, { &comp.particleData, 1 }, 0, PARTICLE_FRAME_CHUNK_SIZE); // input and output will be th same until we bind using dynamic offsets
|
||||
set->ModifyWriteDescBuffer(PARTICLE_DATA_SET_INDEX, SHGraphicsConstants::DescriptorSetBindings::PARTICLE_OUTPUT_DATA, { &comp.particleData, 1 }, 0, PARTICLE_FRAME_CHUNK_SIZE);
|
||||
set->ModifyWriteDescBuffer(PARTICLE_DATA_SET_INDEX, SHGraphicsConstants::DescriptorSetBindings::PARTICLE_FREELIST_DATA, { &comp.freelistData, 1 }, 0, sizeofUint * (comp.maxParticles + 1));
|
||||
set->ModifyWriteDescBuffer(PARTICLE_DATA_SET_INDEX, SHGraphicsConstants::DescriptorSetBindings::PARTICLE_INDICES_DATA, { &comp.indicesData, 1 }, 0, sizeofUint * (comp.maxParticles));
|
||||
set->ModifyWriteDescBuffer(PARTICLE_DATA_SET_INDEX, SHGraphicsConstants::DescriptorSetBindings::PARTICLE_DRAW_DATA, { &comp.drawCallData, 1 }, 0, sizeofIndirectCmd);
|
||||
}
|
||||
|
||||
comp.initialized = true;
|
||||
comp.timeBeforeEmission = comp.emissionInterval;
|
||||
comp.toEmit = false;
|
||||
comp.chunkSize = PARTICLE_FRAME_CHUNK_SIZE;
|
||||
|
||||
for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
|
||||
{
|
||||
auto& offsets = comp.dynamicOffsets[i];
|
||||
|
||||
uint32_t inputOffset = PARTICLE_FRAME_CHUNK_SIZE * ((i + SHGraphicsConstants::NUM_FRAME_BUFFERS - 1) % SHGraphicsConstants::NUM_FRAME_BUFFERS); // take previous frame's data
|
||||
uint32_t outputOffset = PARTICLE_FRAME_CHUNK_SIZE * i;
|
||||
|
||||
// In the order of:
|
||||
// 1. Emitter data
|
||||
// 2. Particle input
|
||||
// 3. Particle output
|
||||
// 4. Particle draw data
|
||||
offsets[DYOFF_INDEX_EMITTER] = i * emitterStructAligned;
|
||||
offsets[DYOFF_INDEX_PARTICLE_INPUT] = inputOffset;
|
||||
offsets[DYOFF_INDEX_PARTICLE_OUTPUT] = outputOffset;
|
||||
offsets[DYOFF_INDEX_INDICES_DATA] = i * sizeofUint * comp.maxParticles;
|
||||
offsets[DYOFF_INDEX_DRAW_DATA] = i * sizeofIndirectCmd;
|
||||
}
|
||||
}
|
||||
|
||||
void SHParticleSubSystem::EmitComponent(Handle<SHVkCommandBuffer> cmdBuffer, SHParticleEmitterComponent& comp, uint32_t frameIndex) noexcept
|
||||
{
|
||||
auto const& mappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::PARTICLE_RENEDERING);
|
||||
auto* transform = SHComponentManager::GetComponent<SHTransformComponent>(comp.GetEID());
|
||||
|
||||
// bind the descriptor sets required for emitting particles
|
||||
cmdBuffer->BindDescriptorSet(comp.particleDescriptorSet, SH_PIPELINE_TYPE::COMPUTE, mappings.at(SHPredefinedDescriptorTypes::PARTICLES), comp.dynamicOffsets[frameIndex]);
|
||||
|
||||
cmdBuffer->SetPushConstantVariable("EmitterPushConstant.emitterPosition", transform->GetWorldPosition(), SH_PIPELINE_TYPE::COMPUTE);
|
||||
cmdBuffer->SetPushConstantVariable("EmitterPushConstant.emissionCount", comp.emissionCount, SH_PIPELINE_TYPE::COMPUTE);
|
||||
|
||||
// emit particles
|
||||
cmdBuffer->ComputeDispatch((comp.emissionCount / EMITTER_WORKGROUP_SIZE) + 1, 1, 1);
|
||||
}
|
||||
|
||||
void SHParticleSubSystem::UpdateCompoennt(Handle<SHVkCommandBuffer> cmdBuffer, SHParticleEmitterComponent& comp, uint32_t frameIndex) noexcept
|
||||
{
|
||||
auto const& mappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::PARTICLE_RENEDERING);
|
||||
|
||||
uint32_t instanceCountOffset = sizeof (vk::DrawIndirectCommand) * frameIndex + offsetof(vk::DrawIndirectCommand, instanceCount);
|
||||
uint32_t ZERO = 0;
|
||||
|
||||
// reset instance count to 0
|
||||
comp.drawCallData->WriteToMemory (&ZERO, sizeof(uint32_t), 0, instanceCountOffset);
|
||||
|
||||
|
||||
// bind the descriptor sets required for emitting particles
|
||||
cmdBuffer->BindDescriptorSet(comp.particleDescriptorSet, SH_PIPELINE_TYPE::COMPUTE, mappings.at(SHPredefinedDescriptorTypes::PARTICLES), comp.dynamicOffsets[frameIndex]);
|
||||
|
||||
// dispatch the compute shaders to update particles
|
||||
cmdBuffer->ComputeDispatch((comp.maxParticles / EMITTER_WORKGROUP_SIZE) + 1, 1, 1);
|
||||
}
|
||||
|
||||
void SHParticleSubSystem::RenderComponent(Handle<SHVkCommandBuffer> cmdBuffer, SHParticleEmitterComponent& comp, uint32_t frameIndex) noexcept
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
descPool = inDescPool;
|
||||
logicalDevice = device;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* INITIALIZE ALL PIPELINES */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
SHPipelineLayoutParams plParams
|
||||
{
|
||||
.shaderModules = {VS, FS},
|
||||
.predefinedDescSetLayouts = SHGraphicsPredefinedData::GetSystemData(SHGraphicsPredefinedData::SystemType::PARTICLE_RENEDERING).descSetLayouts
|
||||
};
|
||||
|
||||
renderingPipelineData.pipelineLayout = logicalDevice->CreatePipelineLayout(plParams);
|
||||
renderingPipelineData.pipeline = logicalDevice->CreateGraphicsPipeline(renderingPipelineData.pipelineLayout, nullptr, compatibleRenderpass, subpass);
|
||||
|
||||
SHPipelineLayoutParams emitPlParams
|
||||
{
|
||||
.shaderModules = {emitCS},
|
||||
.predefinedDescSetLayouts = SHGraphicsPredefinedData::GetSystemData(SHGraphicsPredefinedData::SystemType::PARTICLE_RENEDERING).descSetLayouts
|
||||
};
|
||||
|
||||
emittingPipelineData.pipelineLayout = logicalDevice->CreatePipelineLayout(emitPlParams);
|
||||
emittingPipelineData.pipeline = logicalDevice->CreateComputePipeline(emittingPipelineData.pipelineLayout);
|
||||
|
||||
SHPipelineLayoutParams defaultUpdatePlParams
|
||||
{
|
||||
.shaderModules = {defaultUpdateCS},
|
||||
.predefinedDescSetLayouts = SHGraphicsPredefinedData::GetSystemData(SHGraphicsPredefinedData::SystemType::PARTICLE_RENEDERING).descSetLayouts
|
||||
};
|
||||
|
||||
defaultUpdatePipelineData.pipelineLayout = logicalDevice->CreatePipelineLayout(defaultUpdatePlParams);
|
||||
defaultUpdatePipelineData.pipeline = logicalDevice->CreateComputePipeline(defaultUpdatePipelineData.pipelineLayout);
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* OTHER INITIALIZATION */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
SHComponentManager::CreateComponentSparseSet<SHParticleEmitterComponent>();
|
||||
}
|
||||
|
||||
void SHParticleSubSystem::Run(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, float dt) noexcept
|
||||
{
|
||||
auto& emitters = SHComponentManager::GetDense<SHParticleEmitterComponent>();
|
||||
auto const& mappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::PARTICLE_RENEDERING);
|
||||
|
||||
// Get offset into GPU emitter data (for updating)
|
||||
uint32_t emitterDataOffset = frameIndex * sizeof (SHParticleEmitterComponent::GPUEmitterStruct);
|
||||
|
||||
// Barriers to make sure emitting shader is done completely before update is run.
|
||||
// Every emitter will have its own barrier.
|
||||
std::vector<vk::BufferMemoryBarrier> preUpdateBarriers{};
|
||||
preUpdateBarriers.resize(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
|
||||
// the update compute. HOWEVER since a NUM_FRAME_BUFFERS frames would have passed by then, we will not insert 1 here.
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* 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);
|
||||
|
||||
// Generic data
|
||||
SHGlobalDescriptorSets::BindGenericAndTextureData(logicalDevice, cmdBuffer, SH_PIPELINE_TYPE::COMPUTE, mappings.at(SHPredefinedDescriptorTypes::STATIC_DATA), frameIndex);
|
||||
|
||||
uint32_t i = 0;
|
||||
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)
|
||||
{
|
||||
// decrement emission timer
|
||||
emitter.timeBeforeEmission -= dt;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// make new barrier on stack...
|
||||
vk::BufferMemoryBarrier barrier
|
||||
{
|
||||
.srcAccessMask = vk::AccessFlagBits::eShaderWrite,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead,
|
||||
.buffer = emitter.particleData->GetVkBuffer(),
|
||||
.offset = emitter.dynamicOffsets[frameIndex][DYOFF_INDEX_PARTICLE_INPUT],
|
||||
.size = emitter.chunkSize
|
||||
};
|
||||
|
||||
// ...copy assign barrier on heap
|
||||
preUpdateBarriers[i] = barrier;
|
||||
|
||||
emitter.toEmit = false;
|
||||
++i;
|
||||
}
|
||||
|
||||
// issue the barrier to wait
|
||||
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eComputeShader, vk::PipelineStageFlagBits::eComputeShader, {}, {}, preUpdateBarriers, {});
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* EMITTING PARTICLES DONE, BEGIN UPDATES.... */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
// bind the pipeline for updating
|
||||
cmdBuffer->BindPipeline(defaultUpdatePipelineData.pipeline);
|
||||
|
||||
for (auto& emitter : emitters)
|
||||
{
|
||||
UpdateCompoennt(cmdBuffer, emitter, frameIndex);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void SHParticleSubSystem::Render(Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHRenderer> renderer, uint32_t frameIndex) noexcept
|
||||
{
|
||||
auto& emitters = SHComponentManager::GetDense<SHParticleEmitterComponent>();
|
||||
|
||||
// TODO: Issue barrier for output particle data. Semaphore should also be issued outside in SHGraphicsSystem
|
||||
for (auto& emitter : emitters)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void SHParticleSubSystem::Exit(void) noexcept
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
#pragma once
|
||||
|
||||
#include "Resource/SHHandle.h"
|
||||
#include "Graphics/Pipeline/SHPipelineState.h"
|
||||
#include "Math/SHMatrix.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHVkLogicalDevice;
|
||||
class SHVkDescriptorPool;
|
||||
class SHVkDescriptorSetGroup;
|
||||
class SHVkDescriptorSetLayout;
|
||||
class SHVkBuffer;
|
||||
class SHLightComponent;
|
||||
class SHVkCommandBuffer;
|
||||
class SHVkPipeline;
|
||||
class SHVkPipelineLayout;
|
||||
class SHVkRenderpass;
|
||||
class SHSubpass;
|
||||
class SHVkShaderModule;
|
||||
class SHRenderer;
|
||||
class SHParticleEmitterComponent;
|
||||
|
||||
|
||||
|
||||
class SHParticleSubSystem
|
||||
{
|
||||
private:
|
||||
static constexpr uint32_t EMITTER_WORKGROUP_SIZE = 128;
|
||||
static constexpr uint32_t DYOFF_INDEX_EMITTER = 0;
|
||||
static constexpr uint32_t DYOFF_INDEX_PARTICLE_INPUT = 1;
|
||||
static constexpr uint32_t DYOFF_INDEX_PARTICLE_OUTPUT = 2;
|
||||
static constexpr uint32_t DYOFF_INDEX_INDICES_DATA = 3;
|
||||
static constexpr uint32_t DYOFF_INDEX_DRAW_DATA = 4;
|
||||
|
||||
|
||||
// To hold data for a pipeline and pipeline layout.
|
||||
// We want this here because particles require 3 pipeline sets:
|
||||
// - Rendering
|
||||
// - Emit Compute
|
||||
// - Update Compute
|
||||
struct PipelineData
|
||||
{
|
||||
//! Pipeline
|
||||
Handle<SHVkPipeline> pipeline;
|
||||
|
||||
//! Pipeline layout for pipeline creation
|
||||
Handle<SHVkPipelineLayout> pipelineLayout;
|
||||
};
|
||||
|
||||
#if 0 // not used, mainly for convenience to show what shaders use
|
||||
// Push constant data for emitters
|
||||
struct EmitterShaderPC
|
||||
{
|
||||
//! Emitter position
|
||||
SHVec4 emitterPosition;
|
||||
|
||||
//! emission count for 1 single emission
|
||||
uint32_t emissionCount;
|
||||
};
|
||||
#endif
|
||||
|
||||
//! Logical device for creation and destruction
|
||||
Handle<SHVkLogicalDevice> logicalDevice;
|
||||
|
||||
//! Pipeline data for rendering particles
|
||||
PipelineData renderingPipelineData;
|
||||
|
||||
//! Pipeline data for emitting particles
|
||||
PipelineData emittingPipelineData;
|
||||
|
||||
//! Pipeline data for updating particles
|
||||
PipelineData defaultUpdatePipelineData;
|
||||
|
||||
//! Desc pool for particle component desc set allocation
|
||||
Handle<SHVkDescriptorPool> descPool;
|
||||
|
||||
|
||||
void InitializeComponent (SHParticleEmitterComponent& comp) noexcept;
|
||||
void EmitComponent (Handle<SHVkCommandBuffer> cmdBuffer, SHParticleEmitterComponent& comp, uint32_t frameIndex) noexcept;
|
||||
void UpdateCompoennt(Handle<SHVkCommandBuffer> cmdBuffer, SHParticleEmitterComponent& comp, uint32_t frameIndex) noexcept;
|
||||
void RenderComponent(Handle<SHVkCommandBuffer> cmdBuffer, SHParticleEmitterComponent& comp, uint32_t frameIndex) 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;
|
||||
|
||||
void Run(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, float dt) noexcept;
|
||||
|
||||
void Render(Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHRenderer> renderer, uint32_t frameIndex) noexcept;
|
||||
void Exit(void) noexcept;
|
||||
|
||||
};
|
||||
}
|
|
@ -61,7 +61,7 @@ namespace SHADE
|
|||
MakeDirty();
|
||||
}
|
||||
|
||||
void SHTextRenderableComponent::SetColour(SHColour const& newColor) noexcept
|
||||
void SHTextRenderableComponent::SetColor(SHColour const& newColor) noexcept
|
||||
{
|
||||
color = newColor;
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ namespace SHADE
|
|||
return fontHandle;
|
||||
}
|
||||
|
||||
SHADE::SHColour const& SHTextRenderableComponent::GetColour(void) const noexcept
|
||||
SHADE::SHColour const& SHTextRenderableComponent::GetColor(void) const noexcept
|
||||
{
|
||||
return color;
|
||||
}
|
||||
|
|
|
@ -52,11 +52,11 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
void SetText (std::string_view newText) noexcept;
|
||||
void SetFont(Handle<SHFont> font) noexcept;
|
||||
void SetColour(SHColour const& newColor) noexcept;
|
||||
void SetColor(SHColour const& newColor) noexcept;
|
||||
|
||||
std::string const& GetText (void) const noexcept;
|
||||
Handle<SHFont> GetFont (void) const noexcept;
|
||||
SHColour const& GetColour (void) const noexcept;
|
||||
SHColour const& GetColor (void) const noexcept;
|
||||
|
||||
friend class SHTextRenderingSubSystem;
|
||||
|
||||
|
|
|
@ -42,16 +42,26 @@ namespace SHADE
|
|||
return mesh;
|
||||
}
|
||||
|
||||
SHVec4 const& SHTrajectoryRenderableComponent::GetStartColor(void) const noexcept
|
||||
SHVec3 const& SHTrajectoryRenderableComponent::GetStartColor(void) const noexcept
|
||||
{
|
||||
return startColor;
|
||||
}
|
||||
|
||||
SHVec4 const& SHTrajectoryRenderableComponent::GetEndColor(void) const noexcept
|
||||
SHVec3 const& SHTrajectoryRenderableComponent::GetEndColor(void) const noexcept
|
||||
{
|
||||
return endColor;
|
||||
}
|
||||
|
||||
float SHTrajectoryRenderableComponent::GetStartAlpha(void) const noexcept
|
||||
{
|
||||
return startAlpha;
|
||||
}
|
||||
|
||||
float SHTrajectoryRenderableComponent::GetEndAlpha(void) const noexcept
|
||||
{
|
||||
return endAlpha;
|
||||
}
|
||||
|
||||
float SHTrajectoryRenderableComponent::GetColorEvolveRate(void) const noexcept
|
||||
{
|
||||
return colorEvolveRate;
|
||||
|
@ -67,17 +77,27 @@ namespace SHADE
|
|||
positions = inPositions;
|
||||
}
|
||||
|
||||
void SHTrajectoryRenderableComponent::SetStartColor(SHVec4 color) noexcept
|
||||
void SHTrajectoryRenderableComponent::SetStartColor(SHVec3 color) noexcept
|
||||
{
|
||||
startColor = color;
|
||||
}
|
||||
|
||||
void SHTrajectoryRenderableComponent::SetEndColor(SHVec4 color) noexcept
|
||||
void SHTrajectoryRenderableComponent::SetEndColor(SHVec3 color) noexcept
|
||||
{
|
||||
endColor = color;
|
||||
|
||||
}
|
||||
|
||||
void SHTrajectoryRenderableComponent::SetStartAlpha(float a) noexcept
|
||||
{
|
||||
startAlpha = a;
|
||||
}
|
||||
|
||||
void SHTrajectoryRenderableComponent::SetEndAlpha(float a) noexcept
|
||||
{
|
||||
endAlpha = a;
|
||||
}
|
||||
|
||||
void SHTrajectoryRenderableComponent::SetColorEvolveRate(float rate) noexcept
|
||||
{
|
||||
colorEvolveRate = rate;
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace SHADE
|
|||
{
|
||||
class SHMesh;
|
||||
|
||||
class SHTrajectoryRenderableComponent : public SHComponent
|
||||
class SH_API SHTrajectoryRenderableComponent : public SHComponent
|
||||
{
|
||||
private:
|
||||
|
||||
|
@ -21,10 +21,16 @@ namespace SHADE
|
|||
std::vector<SHVec3> positions;
|
||||
|
||||
//! Starting color of the trajectory
|
||||
SHVec4 startColor;
|
||||
SHVec3 startColor;
|
||||
|
||||
//! Color the trajectory should evolve to the longer it is
|
||||
SHVec4 endColor;
|
||||
SHVec3 endColor;
|
||||
|
||||
//! Starting alpha of the trajectory
|
||||
float startAlpha;
|
||||
|
||||
//! end alpha of the trajectory
|
||||
float endAlpha;
|
||||
|
||||
//! evolving rate of the color
|
||||
float colorEvolveRate;
|
||||
|
@ -35,14 +41,18 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
void SetMesh(Handle<SHMesh> newMesh) noexcept;
|
||||
void SetPositions (std::vector<SHVec3> const& inPositions) noexcept;
|
||||
void SetStartColor(SHVec4 startColor) noexcept;
|
||||
void SetEndColor (SHVec4 endColor) noexcept;
|
||||
void SetColorEvolveRate (float rate) noexcept;
|
||||
void SetStartColor(SHVec3 startColor) noexcept;
|
||||
void SetEndColor (SHVec3 endColor) noexcept;
|
||||
void SetStartAlpha(float a) noexcept;
|
||||
void SetEndAlpha (float a) noexcept;
|
||||
void SetColorEvolveRate(float rate) noexcept;
|
||||
|
||||
std::vector<SHVec3> GetPositions (void) const noexcept;
|
||||
Handle<SHMesh> GetMesh (void) const noexcept;
|
||||
SHVec4 const& GetStartColor (void) const noexcept;
|
||||
SHVec4 const& GetEndColor (void) const noexcept;
|
||||
SHVec3 const& GetStartColor (void) const noexcept;
|
||||
SHVec3 const& GetEndColor (void) const noexcept;
|
||||
float GetStartAlpha (void) const noexcept;
|
||||
float GetEndAlpha (void) const noexcept;
|
||||
float GetColorEvolveRate (void) const noexcept;
|
||||
|
||||
void OnCreate(void) override final;
|
||||
|
|
|
@ -59,8 +59,8 @@ namespace SHADE
|
|||
.srcColorBlendFactor = vk::BlendFactor::eSrcAlpha,
|
||||
.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha,
|
||||
.colorBlendOp = vk::BlendOp::eAdd,
|
||||
.srcAlphaBlendFactor = vk::BlendFactor::eOne,
|
||||
.dstAlphaBlendFactor = vk::BlendFactor::eZero,
|
||||
.srcAlphaBlendFactor = vk::BlendFactor::eSrcAlpha,
|
||||
.dstAlphaBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha,
|
||||
.alphaBlendOp = vk::BlendOp::eAdd,
|
||||
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
|
||||
}
|
||||
|
@ -84,12 +84,18 @@ namespace SHADE
|
|||
// If has positions, feed data to buffer.
|
||||
if (comp.HasPositions())
|
||||
{
|
||||
auto meshHandle = comp.GetMesh();
|
||||
|
||||
// dont do anything if no mesh
|
||||
if (!meshHandle)
|
||||
continue;
|
||||
|
||||
SHTransformComponent* transform = SHComponentManager::GetComponent_s<SHTransformComponent>(comp.GetEID());
|
||||
if (transform)
|
||||
{
|
||||
// convenient variable
|
||||
SHVec4 const& startColor = comp.GetStartColor();
|
||||
SHVec4 const& endColor = comp.GetEndColor();
|
||||
SHVec3 const& startColor = comp.GetStartColor();
|
||||
SHVec3 const& endColor = comp.GetEndColor();
|
||||
float colorEvolveRate = comp.GetColorEvolveRate();
|
||||
|
||||
// trs to be reused
|
||||
|
@ -104,7 +110,6 @@ namespace SHADE
|
|||
// Will be used for baseInstance later
|
||||
uint32_t oldTransformDataSize = transformData.size();
|
||||
|
||||
auto meshHandle = comp.GetMesh();
|
||||
|
||||
auto const& positions = comp.GetPositions();
|
||||
for (auto& pos : positions)
|
||||
|
@ -118,7 +123,8 @@ namespace SHADE
|
|||
colorData.push_back(currentColor);
|
||||
|
||||
// evolve color
|
||||
currentColor = SHVec4::Lerp(startColor, endColor, lerpValue);
|
||||
currentColor = SHVec3::Lerp(startColor, endColor, lerpValue);
|
||||
currentColor.w = SHMath::Lerp (comp.GetStartAlpha(), comp.GetEndAlpha(), lerpValue);
|
||||
|
||||
// evolve lerp value and clamp to 1
|
||||
lerpValue = std::max (1.0f, lerpValue + colorEvolveRate);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "Graphics/MiddleEnd/TextRendering/SHFont.h"
|
||||
#include "Animation/SHAnimatorComponent.h"
|
||||
#include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h"
|
||||
#include "Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.h"
|
||||
|
||||
namespace YAML
|
||||
{
|
||||
|
@ -353,12 +354,14 @@ namespace YAML
|
|||
{
|
||||
static constexpr std::string_view TEXT_YAML_TAG = "Text";
|
||||
static constexpr std::string_view FONT_YAML_TAG = "Font";
|
||||
static constexpr std::string_view COLOR_YAML_TAG = "Color";
|
||||
|
||||
static YAML::Node encode(SHTextRenderableComponent const& rhs)
|
||||
{
|
||||
YAML::Node node;
|
||||
node[TEXT_YAML_TAG.data()] = rhs.GetText();
|
||||
auto font = rhs.GetFont();
|
||||
SHColour const& textColor = rhs.GetColor();
|
||||
if (font)
|
||||
{
|
||||
node[FONT_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHFont>(rhs.GetFont()).value_or(0);
|
||||
|
@ -367,6 +370,7 @@ namespace YAML
|
|||
{
|
||||
node[FONT_YAML_TAG.data()] = 0;
|
||||
}
|
||||
node[COLOR_YAML_TAG.data()] = SHVec4 (textColor);
|
||||
return node;
|
||||
}
|
||||
static bool decode(YAML::Node const& node, SHTextRenderableComponent& rhs)
|
||||
|
@ -385,6 +389,10 @@ namespace YAML
|
|||
|
||||
rhs.SetFont(SHResourceManager::LoadOrGet<SHFont>(node[FONT_YAML_TAG.data()].as<AssetID>()));
|
||||
}
|
||||
if (node[COLOR_YAML_TAG.data()].IsDefined())
|
||||
{
|
||||
rhs.SetColor(node[COLOR_YAML_TAG.data()].as<SHVec4>());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -417,4 +425,37 @@ namespace YAML
|
|||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct convert<SHTrajectoryRenderableComponent>
|
||||
{
|
||||
static constexpr std::string_view MESH_YAML_TAG = "Mesh";
|
||||
static constexpr std::string_view START_COLOR_YAML_TAG = "Start Color";
|
||||
static constexpr std::string_view END_COLOR_YAML_TAG = "End Color";
|
||||
static constexpr std::string_view COLOR_EVAL_RATE_YAML_TAG = "Color Eval Rate ";
|
||||
|
||||
static YAML::Node encode(SHTrajectoryRenderableComponent const& rhs)
|
||||
{
|
||||
YAML::Node node;
|
||||
node[MESH_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHMesh>(rhs.GetMesh()).value_or(0);
|
||||
node[START_COLOR_YAML_TAG.data()] = SHVec3(rhs.GetStartColor());
|
||||
node[END_COLOR_YAML_TAG.data()] = SHVec3(rhs.GetEndColor());
|
||||
node[COLOR_EVAL_RATE_YAML_TAG.data()] = rhs.GetColorEvolveRate();
|
||||
|
||||
return node;
|
||||
}
|
||||
static bool decode(YAML::Node const& node, SHTrajectoryRenderableComponent& rhs)
|
||||
{
|
||||
if (node[MESH_YAML_TAG.data()].IsDefined())
|
||||
rhs.SetMesh(SHResourceManager::LoadOrGet<SHMesh>(node[MESH_YAML_TAG.data()].as<AssetID>()));
|
||||
if (node[START_COLOR_YAML_TAG.data()].IsDefined())
|
||||
rhs.SetStartColor(node[START_COLOR_YAML_TAG.data()].as<SHVec3>());
|
||||
if (node[END_COLOR_YAML_TAG.data()].IsDefined())
|
||||
rhs.SetEndColor(node[END_COLOR_YAML_TAG.data()].as<SHVec3>());
|
||||
if (node[COLOR_EVAL_RATE_YAML_TAG.data()].IsDefined())
|
||||
rhs.SetColorEvolveRate(node[COLOR_EVAL_RATE_YAML_TAG.data()].as<float>());
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
#include "SHpch.h"
|
||||
|
||||
#include "TrajectoryRenderable.hxx"
|
||||
#include "Assets/NativeAsset.hxx"
|
||||
#include "Utility/Convert.hxx"
|
||||
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
TrajectoryRenderable::TrajectoryRenderable(Entity entity)
|
||||
:Component(entity)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
MeshAsset TrajectoryRenderable::Mesh::get()
|
||||
{
|
||||
auto mesh = GetNativeComponent()->GetMesh();
|
||||
return mesh ? MeshAsset(mesh) : MeshAsset();
|
||||
}
|
||||
void TrajectoryRenderable::Mesh::set(MeshAsset value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
GetNativeComponent()->SetMesh(Handle<SHMesh>());
|
||||
}
|
||||
else
|
||||
{
|
||||
GetNativeComponent()->SetMesh(value.NativeObject);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TrajectoryRenderable::StartColor::set(Vector3 val)
|
||||
{
|
||||
GetNativeComponent()->SetStartColor(Convert::ToNative(val));
|
||||
}
|
||||
|
||||
Vector3 TrajectoryRenderable::StartColor::get()
|
||||
{
|
||||
return Convert::ToCLI(GetNativeComponent()->GetStartColor());
|
||||
}
|
||||
|
||||
void TrajectoryRenderable::EndColor::set(Vector3 val)
|
||||
{
|
||||
GetNativeComponent()->SetEndColor(Convert::ToNative(val));
|
||||
}
|
||||
|
||||
Vector3 TrajectoryRenderable::EndColor::get()
|
||||
{
|
||||
return Convert::ToCLI(GetNativeComponent()->GetEndColor());
|
||||
}
|
||||
|
||||
void TrajectoryRenderable::StartAlpha::set(float val)
|
||||
{
|
||||
GetNativeComponent()->SetStartAlpha(val);
|
||||
}
|
||||
|
||||
float TrajectoryRenderable::StartAlpha::get()
|
||||
{
|
||||
return GetNativeComponent()->GetStartAlpha();
|
||||
}
|
||||
|
||||
void TrajectoryRenderable::EndAlpha::set(float val)
|
||||
{
|
||||
GetNativeComponent()->SetEndAlpha(val);
|
||||
}
|
||||
|
||||
float TrajectoryRenderable::EndAlpha::get()
|
||||
{
|
||||
return GetNativeComponent()->GetEndAlpha();
|
||||
}
|
||||
|
||||
void TrajectoryRenderable::ColorEvolveRate::set(float val)
|
||||
{
|
||||
GetNativeComponent()->SetColorEvolveRate(val);
|
||||
}
|
||||
|
||||
float TrajectoryRenderable::ColorEvolveRate::get()
|
||||
{
|
||||
return GetNativeComponent()->GetColorEvolveRate();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/************************************************************************************//*!
|
||||
\file TrajectoryRenderable.hxx
|
||||
\author Brandon Mak, brandon.hao,
|
||||
\par email: brandon.hao\@digipen.edu
|
||||
\date 1st March, 2023
|
||||
\brief Contains the definition of the managed Renderable class with the
|
||||
declaration of functions for working with it.
|
||||
|
||||
Note: This file is written in C++17/CLI.
|
||||
|
||||
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
// Project Includes
|
||||
#include "Components/Component.hxx"
|
||||
#include "Math/Quaternion.hxx"
|
||||
// External Dependencies
|
||||
#include "Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.h"
|
||||
#include "Graphics/Color.hxx"
|
||||
#include "Assets/MeshAsset.hxx"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/// <summary>
|
||||
/// CLR version of the SHADE Engine's SHRenderableComponent.
|
||||
/// </summary>
|
||||
public ref class TrajectoryRenderable : public Component<SHTrajectoryRenderableComponent>
|
||||
{
|
||||
internal:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Constructs a Trajectory Renderable Component that represents a native Trajectory Renderable
|
||||
/// component tied to the specified Entity.
|
||||
/// </summary>
|
||||
/// <param name="entity">Entity that this Component will be tied to.</param>
|
||||
TrajectoryRenderable(Entity entity);
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Mesh used to render this Renderable.
|
||||
/// </summary>
|
||||
property MeshAsset Mesh
|
||||
{
|
||||
MeshAsset get();
|
||||
void set(MeshAsset value);
|
||||
}
|
||||
|
||||
property Vector3 StartColor
|
||||
{
|
||||
Vector3 get();
|
||||
void set (Vector3 val);
|
||||
}
|
||||
|
||||
property Vector3 EndColor
|
||||
{
|
||||
Vector3 get();
|
||||
void set(Vector3 val);
|
||||
}
|
||||
|
||||
property float StartAlpha
|
||||
{
|
||||
float get();
|
||||
void set (float val);
|
||||
}
|
||||
|
||||
property float EndAlpha
|
||||
{
|
||||
float get();
|
||||
void set(float val);
|
||||
}
|
||||
|
||||
property float ColorEvolveRate
|
||||
{
|
||||
float get();
|
||||
void set(float val);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -46,6 +46,8 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Components\UIElement.hxx"
|
||||
#include "Components\Canvas.hxx"
|
||||
#include "Components\Slider.hxx"
|
||||
#include "Components\TrajectoryRenderable.hxx"
|
||||
#include "Graphics\MiddleEnd\TrajectoryRendering\SHTrajectoryRenderableComponent.h"
|
||||
|
||||
|
||||
|
||||
|
@ -335,6 +337,7 @@ namespace SHADE
|
|||
componentMap.Add(createComponentSet<SHUIComponent, UIElement>());
|
||||
componentMap.Add(createComponentSet<SHCanvasComponent, Canvas>());
|
||||
componentMap.Add(createComponentSet<SHSliderComponent, Slider>());
|
||||
componentMap.Add(createComponentSet<SHTrajectoryRenderableComponent, TrajectoryRenderable>());
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
|
Loading…
Reference in New Issue