diff --git a/Engine/BuiltInShaders/shaders/fs_particle.sc b/Engine/BuiltInShaders/shaders/fs_particle.sc new file mode 100644 index 00000000..cf67f0d1 --- /dev/null +++ b/Engine/BuiltInShaders/shaders/fs_particle.sc @@ -0,0 +1,13 @@ +$input v_color0, v_texcoord0 +#include "../common/common.sh" + +SAMPLER2D(s_texColor, 0); + +void main() +{ + vec4 rgba = texture2D(s_texColor, v_texcoord0.xy); + + rgba.xyz = rgba.xyz * v_color0.xyz; + rgba.w = v_color0.w; + gl_FragColor = rgba; +} \ No newline at end of file diff --git a/Engine/BuiltInShaders/shaders/varying.def.sc b/Engine/BuiltInShaders/shaders/varying.def.sc index 07bd3c26..bd82f0c4 100644 --- a/Engine/BuiltInShaders/shaders/varying.def.sc +++ b/Engine/BuiltInShaders/shaders/varying.def.sc @@ -18,4 +18,10 @@ vec2 a_texcoord0 : TEXCOORD0; vec4 a_color0 : COLOR0; vec4 a_color1 : COLOR1; ivec4 a_indices : BLENDINDICES; -vec4 a_weight : BLENDWEIGHT; \ No newline at end of file +vec4 a_weight : BLENDWEIGHT; + +vec4 i_data0 : TEXCOORD7; +vec4 i_data1 : TEXCOORD6; +vec4 i_data2 : TEXCOORD5; +vec4 i_data3 : TEXCOORD4; +vec4 i_data4 : TEXCOORD3; \ No newline at end of file diff --git a/Engine/BuiltInShaders/shaders/vs_particle.sc b/Engine/BuiltInShaders/shaders/vs_particle.sc new file mode 100644 index 00000000..8b4c71c6 --- /dev/null +++ b/Engine/BuiltInShaders/shaders/vs_particle.sc @@ -0,0 +1,14 @@ +$input a_position, a_color0, a_texcoord0, i_data0, i_data1 ,i_data2 ,i_data3 ,i_data4 +$output v_color0, v_texcoord0 + +#include "../common/common.sh" + +void main() +{ + mat4 model = mtxFromCols(i_data0, i_data1, i_data2, i_data3); + + vec4 worldPos = mul(model,vec4(a_position,1.0)); + gl_Position = mul(u_viewProj, worldPos); + v_color0 = a_color0*i_data4; + v_texcoord0 = a_texcoord0; +} \ No newline at end of file diff --git a/Engine/EditorTools/Win64/texturec.exe b/Engine/EditorTools/Win64/texturec.exe index f610d94b..e69de29b 100644 Binary files a/Engine/EditorTools/Win64/texturec.exe and b/Engine/EditorTools/Win64/texturec.exe differ diff --git a/Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp b/Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp index c69075dd..f2d52076 100644 --- a/Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp +++ b/Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp @@ -57,6 +57,11 @@ void ECWorldConsumer::Execute(const cd::SceneDatabase* pSceneDatabase) CD_WARN("[ECWorldConsumer] No valid meshes in the consumed SceneDatabase."); } + if (0U != pSceneDatabase->GetParticleEmitterCount()) + { + CD_INFO("[ECWorldConsumer] Have ParticleEmitter"); + } + auto ParseMesh = [&](cd::MeshID meshID, const cd::Transform& tranform) { engine::Entity meshEntity = m_pSceneWorld->GetWorld()->CreateEntity(); @@ -139,7 +144,7 @@ void ECWorldConsumer::Execute(const cd::SceneDatabase* pSceneDatabase) } for (const auto& node : pSceneDatabase->GetNodes()) - { + { if (m_nodeMinID > node.GetID().Data()) { continue; @@ -167,6 +172,12 @@ void ECWorldConsumer::Execute(const cd::SceneDatabase* pSceneDatabase) engine::Entity lightEntity = m_pSceneWorld->GetWorld()->CreateEntity(); AddLight(lightEntity, light); } + + for (const auto& particle : pSceneDatabase->GetParticleEmitters()) + { + engine::Entity particleEntity = m_pSceneWorld->GetWorld()->CreateEntity(); + AddParticleEmitter(particleEntity, particle); + } } void ECWorldConsumer::AddCamera(engine::Entity entity, const cd::Camera& camera) @@ -371,4 +382,23 @@ void ECWorldConsumer::AddMorphs(engine::Entity entity, const std::vectorGetWorld(); + engine::NameComponent& nameComponent = pWorld->CreateComponent(entity); + nameComponent.SetName(particle.GetName()); + auto& particleEmitterComponent = pWorld->CreateComponent(entity); + // TODO : Some initialization here. + auto& transformComponent = pWorld->CreateComponent(entity); + cd::Vec3f pos = particle.GetPosition(); + transformComponent.SetTransform(cd::Transform::Identity()); + transformComponent.GetTransform().SetTranslation(pos); + transformComponent.Build(); + + particleEmitterComponent.GetParticleSystem().Init(); + particleEmitterComponent.SetFVelocity(particle.GetVelocity()); + particleEmitterComponent.SetFColor(particle.GetColor()/255.0f); + particleEmitterComponent.Build(); +} + } \ No newline at end of file diff --git a/Engine/Source/Editor/ECWorld/ECWorldConsumer.h b/Engine/Source/Editor/ECWorld/ECWorldConsumer.h index 04878995..d578aa37 100644 --- a/Engine/Source/Editor/ECWorld/ECWorldConsumer.h +++ b/Engine/Source/Editor/ECWorld/ECWorldConsumer.h @@ -27,6 +27,7 @@ class Node; class SceneDatabase; class Texture; class VertexFormat; +class ParticleEmitter; } @@ -67,6 +68,7 @@ class ECWorldConsumer final : public cdtools::IConsumer void AddAnimation(engine::Entity entity, const cd::Animation& animation, const cd::SceneDatabase* pSceneDatabase); void AddMaterial(engine::Entity entity, const cd::Material* pMaterial, engine::MaterialType* pMaterialType, const cd::SceneDatabase* pSceneDatabase); void AddMorphs(engine::Entity entity, const std::vector& morphs, const cd::Mesh* pMesh); + void AddParticleEmitter(engine::Entity entity, const cd::ParticleEmitter& particle); private: engine::MaterialType* m_pDefaultMaterialType = nullptr; diff --git a/Engine/Source/Editor/UILayers/AssetBrowser.cpp b/Engine/Source/Editor/UILayers/AssetBrowser.cpp index 69a51095..fa5b0f38 100644 --- a/Engine/Source/Editor/UILayers/AssetBrowser.cpp +++ b/Engine/Source/Editor/UILayers/AssetBrowser.cpp @@ -13,6 +13,7 @@ #include "Log/Log.h" #include "Material/MaterialType.h" #include "Producers/CDProducer/CDProducer.h" +#include "Producers/EffekseerProducer/EffekseerProducer.h" #include "Rendering/WorldRenderer.h" #include "Rendering/RenderContext.h" #include "Resources/ResourceBuilder.h" @@ -22,6 +23,7 @@ #include "Producers/GenericProducer/GenericProducer.h" #endif +#include #include #include @@ -98,6 +100,21 @@ bool IsLightInputFile(const char* pFileExtension) return false; } +bool IsParticleInputFile(const char* pFileExtension) +{ + constexpr const char* pFileExtensions[] = { ".efkefc"}; + constexpr const int fileExtensionsSize = sizeof(pFileExtensions) / sizeof(pFileExtensions[0]); + for (int extensionIndex = 0; extensionIndex < fileExtensionsSize; ++extensionIndex) + { + if (0 == strcmp(pFileExtensions[extensionIndex], pFileExtension)) + { + return true; + } + } + + return false; +} + std::string GetFilePathExtension(const std::string& FileName) { auto pos = FileName.find_last_of('.'); @@ -780,6 +797,10 @@ void AssetBrowser::ImportAssetFile(const char* pFilePath) { m_importOptions.AssetType = IOAssetType::Light; } + else if (IsParticleInputFile(pFileExtension.c_str())) + { + m_importOptions.AssetType = IOAssetType::Particle; + } else { // Still unknown, exit. @@ -852,6 +873,10 @@ void AssetBrowser::ImportAssetFile(const char* pFilePath) { ImportJson(pFilePath); } + else if (IOAssetType::Particle == m_importOptions.AssetType) + { + ImportParticleEffect(pFilePath); + } } void AssetBrowser::ProcessSceneDatabase(cd::SceneDatabase* pSceneDatabase, bool keepMesh, bool keepMaterial, bool keepTexture, bool keepCamera, bool keepLight) @@ -1084,6 +1109,36 @@ void AssetBrowser::ImportJson(const char* pFilePath) } } +void AssetBrowser::ImportParticleEffect(const char* pFilePath) +{ + ////engine::RenderContext* pCurrentRenderContext = GetRenderContext(); + //engine::SceneWorld* pSceneWorld = GetImGuiContextInstance()->GetSceneWorld(); + + //cd::SceneDatabase* pSceneDatabase = pSceneWorld->GetSceneDatabase(); + ////uint32_t oldNodeCount = pSceneDatabase->GetNodeCount(); + ////uint32_t oldMeshCount = pSceneDatabase->GetMeshCount(); + //uint32_t oldParticleEmitterCount = pSceneDatabase->GetParticleEmitterCount(); + + //// Step 1 : Convert model file to cd::SceneDatabase + //std::filesystem::path inputFilePath(pFilePath); + //std::filesystem::path inputFileExtension = inputFilePath.extension(); + //if (0 == inputFileExtension.compare(".efkefc")) + //{ + ///* cdtools::CDProducer cdProducer(pFilePath); + // cd::SceneDatabase newSceneDatabase; + // cdtools::Processor processor(&cdProducer, nullptr, &newSceneDatabase); + // proce qssor.Run(); + // pSceneDatabase->Merge(cd::MoveTemp(newSceneDatabase));*/ + // std::string filePath = pFilePath; + // int size = MultiByteToWideChar(CP_UTF8, 0, filePath.c_str(), -1, nullptr, 0); + // std::wstring wstr(size, 0); + // MultiByteToWideChar(CP_UTF8, 0, filePath.c_str(), -1, &wstr[0], size); + // std::wstring wFilePath = wstr; + // const char16_t* u16_cstr = reinterpret_cast(wFilePath.c_str()); + // cdtools::EffekseerProducer efkProducer(u16_cstr); + //} +} + void AssetBrowser::ExportAssetFile(const char* pFilePath) { engine::SceneWorld* pSceneWorld = GetImGuiContextInstance()->GetSceneWorld(); diff --git a/Engine/Source/Editor/UILayers/AssetBrowser.h b/Engine/Source/Editor/UILayers/AssetBrowser.h index 3fb19549..0538a566 100644 --- a/Engine/Source/Editor/UILayers/AssetBrowser.h +++ b/Engine/Source/Editor/UILayers/AssetBrowser.h @@ -38,6 +38,7 @@ enum class IOAssetType SceneDatabase, Terrain, Light, + Particle, Unknown, }; @@ -95,6 +96,7 @@ class AssetBrowser : public engine::ImGuiBaseLayer private: void ProcessSceneDatabase(cd::SceneDatabase* pSceneDatabase, bool keepMesh, bool keepMaterial, bool keepTexture, bool keepCamera, bool keepLight); void ImportModelFile(const char* pFilePath); + void ImportParticleEffect(const char* pFilePath); void ImportJson(const char* pFilePath); void DrawFolder(const std::shared_ptr& dirInfo, bool defaultOpen = false); void ChangeDirectory(std::shared_ptr& directory); diff --git a/Engine/Source/Editor/UILayers/EntityList.cpp b/Engine/Source/Editor/UILayers/EntityList.cpp index 8c6151c8..418a54c4 100644 --- a/Engine/Source/Editor/UILayers/EntityList.cpp +++ b/Engine/Source/Editor/UILayers/EntityList.cpp @@ -228,6 +228,12 @@ void EntityList::AddEntity(engine::SceneWorld* pSceneWorld) engine::Entity entity = AddNamedEntity("ParticleEmitter"); auto& particleEmitterComponent = pWorld->CreateComponent(entity); // TODO : Some initialization here. + auto& transformComponent = pWorld->CreateComponent(entity); + transformComponent.SetTransform(cd::Transform::Identity()); + transformComponent.Build(); + + particleEmitterComponent.GetParticleSystem().Init(); + particleEmitterComponent.Build(); } } diff --git a/Engine/Source/Editor/UILayers/Inspector.cpp b/Engine/Source/Editor/UILayers/Inspector.cpp index 64535630..b0be24b2 100644 --- a/Engine/Source/Editor/UILayers/Inspector.cpp +++ b/Engine/Source/Editor/UILayers/Inspector.cpp @@ -616,10 +616,10 @@ void UpdateComponentWidget(engine::SceneWorld* pSceneWorld } template<> -void UpdateComponentWidget(engine::SceneWorld* pSceneWorld, engine::Entity entity) +void UpdateComponentWidget(engine::SceneWorld* pSceneWorld, engine::Entity entity) { - auto* pParticleComponent = pSceneWorld->GetParticleComponent(entity); - if (!pParticleComponent) + auto* pParticleEmitterComponent = pSceneWorld->GetParticleEmitterComponent(entity); + if (!pParticleEmitterComponent) { return; } @@ -630,7 +630,8 @@ void UpdateComponentWidget(engine::SceneWorld* pScene if (isOpen) { - + ImGuiUtils::ImGuiVectorProperty("Velocity",pParticleEmitterComponent->GetFVelocity()); + ImGuiUtils::ColorPickerProperty(" Color", pParticleEmitterComponent->GetFColor()); } ImGui::Separator(); @@ -674,7 +675,6 @@ void Inspector::Update() } ImGui::BeginChild("Inspector"); - details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); @@ -683,7 +683,7 @@ void Inspector::Update() details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); - details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); + details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); diff --git a/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h b/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h index 53f38877..fca85ff7 100644 --- a/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h +++ b/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h @@ -15,5 +15,4 @@ #include "ECWorld/StaticMeshComponent.h" #include "ECWorld/TerrainComponent.h" #include "ECWorld/TransformComponent.h" -#include "ECWorld/ParticleComponent.h" #include "ECWorld/ParticleEmitterComponent.h" \ No newline at end of file diff --git a/Engine/Source/Runtime/ECWorld/ParticleComponent.cpp b/Engine/Source/Runtime/ECWorld/ParticleComponent.cpp deleted file mode 100644 index f7e32e89..00000000 --- a/Engine/Source/Runtime/ECWorld/ParticleComponent.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "ParticleComponent.h" diff --git a/Engine/Source/Runtime/ECWorld/ParticleComponent.h b/Engine/Source/Runtime/ECWorld/ParticleComponent.h deleted file mode 100644 index e2be6580..00000000 --- a/Engine/Source/Runtime/ECWorld/ParticleComponent.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "Base/Template.h" -#include "Core/StringCrc.h" -#include "Math/Vector.hpp" - -namespace engine -{ - -class ParticleComponent final -{ -public: - static constexpr StringCrc GetClassName() - { - constexpr StringCrc className("ParticleComponent"); - return className; - } - - ParticleComponent() = default; - ParticleComponent(const ParticleComponent&) = default; - ParticleComponent& operator=(const ParticleComponent&) = default; - ParticleComponent(ParticleComponent&&) = default; - ParticleComponent& operator=(ParticleComponent&&) = default; - ~ParticleComponent() = default; - -private: - -}; - -} \ No newline at end of file diff --git a/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.cpp b/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.cpp index 5dcfb9de..b9f92b4c 100644 --- a/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.cpp +++ b/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.cpp @@ -1 +1,89 @@ #include "ParticleEmitterComponent.h" +#include "Scene/VertexFormat.h" +#include "Rendering/Utility/VertexLayoutUtility.h" +#include + +void engine::ParticleEmitterComponent::Build() +{ + cd::VertexFormat vertexFormat; + vertexFormat.AddAttributeLayout(cd::VertexAttributeType::Position, cd::AttributeValueType::Float, 3); + vertexFormat.AddAttributeLayout(cd::VertexAttributeType::Color, cd::AttributeValueType::Float, 4); + vertexFormat.AddAttributeLayout(cd::VertexAttributeType::UV, cd::AttributeValueType::Float, 2); + bgfx::VertexLayout vertexLayout; + VertexLayoutUtility::CreateVertexLayout(vertexLayout, vertexFormat.GetVertexLayout()); + + PaddingVertexBuffer(); + PaddingIndexBuffer(); + + m_particleVBH = bgfx::createVertexBuffer(bgfx::makeRef(m_particleVertexBuffer.data(), static_cast(m_particleVertexBuffer.size())), vertexLayout).idx; + m_particleIBH = bgfx::createIndexBuffer(bgfx::makeRef(m_particleIndexBuffer.data(), static_cast(m_particleIndexBuffer.size())), 0U).idx; +} + +//void engine::ParticleEmitterComponent::UpdateBuffer() +//{ +// //bgfx::update(vbh, 0, bgfx::makeRef(vertexBuffer.data(), vertexBuffer.size())); +// PaddingVertexBuffer(); +// PaddingIndexBuffer(); +// +// bgfx::update(bgfx::DynamicVertexBufferHandle{ GetParticleVBH() }, 0 , bgfx::makeRef(m_particleVertexBuffer.data(), static_cast(m_particleVertexBuffer.size()))); +// bgfx::update(bgfx::DynamicIndexBufferHandle{GetParticleIBH()}, 0, bgfx::makeRef(m_particleIndexBuffer.data(), static_cast(m_particleIndexBuffer.size()))); +//} + +void engine::ParticleEmitterComponent::PaddingVertexBuffer() +{ + //vertexbuffer + + size_t vertexCount = m_particleSystem.GetMaxCount(); + + size_t vertexBufferSize = vertexCount * (sizeof(cd::Vec3f) + sizeof(cd::Vec4f)+sizeof(float)*2); + + m_particleVertexBuffer.resize(vertexBufferSize); + + uint32_t currentDataSize = 0U; + auto currentDataPtr = m_particleVertexBuffer.data(); + + for (int i = 0; i < m_particleSystem.GetMaxCount(); i++) + { + std::memcpy(¤tDataPtr[currentDataSize], &m_particleSystem.GetPos(i), sizeof(cd::Vec3f)); + currentDataSize += sizeof(cd::Vec3f); + + std::memcpy(¤tDataPtr[currentDataSize], &m_particleSystem.GetColor(i), sizeof(cd::Vec4f)); + currentDataSize += sizeof(cd::Vec4f); + + std::memcpy(¤tDataPtr[currentDataSize], &m_particleSystem.GetTexture_u(i), sizeof(float)); + currentDataSize += sizeof(float); + + std::memcpy(¤tDataPtr[currentDataSize], &m_particleSystem.GetTexture_v(i), sizeof(float)); + currentDataSize += sizeof(float); + } +} + +void engine::ParticleEmitterComponent::PaddingIndexBuffer() +{ + /* +* indexBuffer +*/ + size_t indexTypeSize = sizeof(uint16_t); + m_particleIndexBuffer.resize(m_particleSystem.GetMaxCount()/4* 6 * indexTypeSize); + uint32_t currentDataSize = 0U; + auto currentDataPtr = m_particleIndexBuffer.data(); + + std::vector indexes; + for (uint16_t i = 0; i < m_particleSystem.GetMaxCount(); i += 4) + { + uint16_t vertexIndex = static_cast(i); + indexes.push_back(vertexIndex); + indexes.push_back(vertexIndex+1); + indexes.push_back(vertexIndex+2); + indexes.push_back(vertexIndex); + indexes.push_back(vertexIndex+2); + indexes.push_back(vertexIndex+3); + + } + + for (const auto& index : indexes) + { + std::memcpy(¤tDataPtr[currentDataSize], &index, indexTypeSize); + currentDataSize += static_cast(indexTypeSize); + } +} \ No newline at end of file diff --git a/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.h b/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.h index b21634cd..7fac2325 100644 --- a/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.h +++ b/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.h @@ -3,6 +3,8 @@ #include "Base/Template.h" #include "Core/StringCrc.h" #include "Math/Vector.hpp" +#include "Math/Transform.hpp" +#include "ParticleSystem/ParticleSystem.h" namespace engine { @@ -23,8 +25,38 @@ class ParticleEmitterComponent final ParticleEmitterComponent& operator=(ParticleEmitterComponent&&) = default; ~ParticleEmitterComponent() = default; + engine::ParticleSystem &GetParticleSystem() { return m_particleSystem; } + + cd::Vec3f& GetFVelocity() { return m_fill_velocity; } + void SetFVelocity(cd::Vec3f fillnum) { m_fill_velocity = fillnum; } + + cd::Vec4f& GetFColor() { return m_fill_color; } + void SetFColor(cd::Vec4f fillcolor) { m_fill_color = fillcolor; } + + uint16_t& GetParticleVBH(){ return m_particleVBH; } + uint16_t& GetParticleIBH() { return m_particleIBH; } + + std::vector &GetVertexBuffer() { return m_particleVertexBuffer; } + std::vector &GetIndexBuffer() { return m_particleIndexBuffer; } + + void Build(); + + //void UpdateBuffer(); + + void PaddingVertexBuffer(); + + void PaddingIndexBuffer(); + private: + ParticleSystem m_particleSystem; + + cd::Vec3f m_fill_velocity; + cd::Vec4f m_fill_color{1.0f,1.0f,1.0f,1.0f}; + std::vector m_particleVertexBuffer; + std::vector m_particleIndexBuffer; + uint16_t m_particleVBH = UINT16_MAX; + uint16_t m_particleIBH = UINT16_MAX; }; } \ No newline at end of file diff --git a/Engine/Source/Runtime/ECWorld/SceneWorld.cpp b/Engine/Source/Runtime/ECWorld/SceneWorld.cpp index 532275db..2270c18a 100644 --- a/Engine/Source/Runtime/ECWorld/SceneWorld.cpp +++ b/Engine/Source/Runtime/ECWorld/SceneWorld.cpp @@ -35,7 +35,6 @@ SceneWorld::SceneWorld() m_pNameComponentStorage = m_pWorld->Register(); m_pSkyComponentStorage = m_pWorld->Register(); m_pStaticMeshComponentStorage = m_pWorld->Register(); - m_pParticleComponentStorage = m_pWorld->Register(); m_pParticleEmitterComponentStorage = m_pWorld->Register(); m_pTerrainComponentStorage = m_pWorld->Register(); m_pTransformComponentStorage = m_pWorld->Register(); diff --git a/Engine/Source/Runtime/ECWorld/SceneWorld.h b/Engine/Source/Runtime/ECWorld/SceneWorld.h index cdcbbca4..d188fe5a 100644 --- a/Engine/Source/Runtime/ECWorld/SceneWorld.h +++ b/Engine/Source/Runtime/ECWorld/SceneWorld.h @@ -40,7 +40,6 @@ class SceneWorld DEFINE_COMPONENT_STORAGE_WITH_APIS(Name); DEFINE_COMPONENT_STORAGE_WITH_APIS(Sky); DEFINE_COMPONENT_STORAGE_WITH_APIS(StaticMesh); - DEFINE_COMPONENT_STORAGE_WITH_APIS(Particle); DEFINE_COMPONENT_STORAGE_WITH_APIS(ParticleEmitter); DEFINE_COMPONENT_STORAGE_WITH_APIS(Terrain); DEFINE_COMPONENT_STORAGE_WITH_APIS(Transform); @@ -98,7 +97,6 @@ class SceneWorld DeleteNameComponent(entity); DeleteSkyComponent(entity); DeleteStaticMeshComponent(entity); - DeleteParticleComponent(entity); DeleteParticleEmitterComponent(entity); DeleteTerrainComponent(entity); DeleteTransformComponent(entity); diff --git a/Engine/Source/Runtime/ImGui/ImGuiUtils.hpp b/Engine/Source/Runtime/ImGui/ImGuiUtils.hpp index d929a147..4cad5df5 100644 --- a/Engine/Source/Runtime/ImGui/ImGuiUtils.hpp +++ b/Engine/Source/Runtime/ImGui/ImGuiUtils.hpp @@ -263,7 +263,8 @@ static bool ImGuiTransformProperty(const char* pName, cd::Transform& value) return dirty; } -static void ColorPickerProperty(const char* Name, cd::Vec3f& veccolor) +template +static void ColorPickerProperty(const char* Name, T& veccolor) { static std::map showMap; if (!showMap.count(Name)) @@ -282,7 +283,15 @@ static void ColorPickerProperty(const char* Name, cd::Vec3f& veccolor) ImGui::PushItemWidth(-1); ImGui::SameLine(); ImGui::NextColumn(); - ImGui::DragFloat3("", veccolor.Begin(), 0, 0.0f, 1.0f); + if (std::is_same()) + { + ImGui::DragFloat3("", veccolor.Begin(), 0, 0.0f, 1.0f); + } + else if (std::is_same()) + { + ImGui::DragFloat4("", veccolor.Begin(), 0, 0.0f, 1.0f); + } + ImGui::PopItemWidth(); if (showMap[Name]) { @@ -294,7 +303,14 @@ static void ColorPickerProperty(const char* Name, cd::Vec3f& veccolor) ImGui::SetNextWindowPos(windowPos, ImGuiCond_Always); ImGui::Begin(Name, &showMap[Name], ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize); - ImGui::ColorPicker3("Color Picker", veccolor.Begin()); + if (std::is_same()) + { + ImGui::ColorPicker3("Color Picker", veccolor.Begin()); + } + else if (std::is_same()) + { + ImGui::ColorPicker4("Color Picker",veccolor.Begin()); + } ImGui::End(); } ImGui::Separator(); diff --git a/Engine/Source/Runtime/ParticleSystem/ParticleSystem.cpp b/Engine/Source/Runtime/ParticleSystem/ParticleSystem.cpp new file mode 100644 index 00000000..e66c6b26 --- /dev/null +++ b/Engine/Source/Runtime/ParticleSystem/ParticleSystem.cpp @@ -0,0 +1,132 @@ +#include "ParticleSystem.h" +#include + +void engine::ParticleSystem::AllocateParticleIndex() +{ + if (!m_FreeParticleIndex.empty()) + { + int index = m_FreeParticleIndex.back(); + m_FreeParticleIndex.pop_back(); + m_particleIndex = index; + } + else + { + ++m_currentParticleCount; + if (m_currentParticleCount >= m_particleMaxCount) + { + m_currentParticleCount = 0; + } + + if (m_isActive[m_currentParticleCount]) + { + //full + m_currentParticleCount = -1; + } + else + { + m_particleIndex = m_currentParticleCount; + } + } + + if (m_particleIndex != -1) + { + Reset(m_particleIndex); + Active(m_particleIndex); + } +} + +void engine::ParticleSystem::Reset(int index) +{ + + m_pos[index] = cd::Vec3f(0.0f, 0.0f, 0.0f); + m_rotation[index] = cd::Vec3f(0.0f, 0.0f, 0.0f); + m_scale[index] = cd::Vec3f(0.0f, 0.0f, 0.0f); + m_velocity[index] = cd::Vec3f(0.0f, 0.0f, 0.0f); + m_acceleration[index] = cd::Vec3f(0.0f, 0.0f, 0.0f); + + m_color[index] = cd::Vec4f{1.0f, 1.0f,1.0f,1.0f}; + + m_isActive[index] = false; + m_currentTime[index] = 0.0f; + m_lifeTime[index] = 6.0f; + +} + +void engine::ParticleSystem::Update(float deltaTime, int index) +{ + if (m_currentTime[index] >= m_lifeTime[index]) + { + m_isActive[index] = false; + m_currentTime[index] = 0.0f; + return; + } + + if (index % 4 == 0) + { + m_pos[index].x() = m_pos[index].x() + m_velocity[index].x(); + m_pos[index].y() = m_pos[index].y() + m_velocity[index].y(); + m_texture_u[index] = 1.0f; + m_texture_v[index] = 1.0f; + } + else if (index % 4 == 1) + { + m_pos[index].x() = m_pos[index-1].x()+ 1 +m_velocity[index].x() ; + m_pos[index].y() = m_pos[index-1].y() + m_velocity[index].y(); + m_texture_u[index] = 0.0f; + m_texture_v[index] = 1.0f; + } + else if (index % 4 == 2) + { + m_pos[index].x() = m_pos[index-2].x() + 1 + m_velocity[index].x(); + m_pos[index].y() = m_pos[index-2].y() + 1 + m_velocity[index].y(); + m_texture_u[index] = 0.0f; + m_texture_v[index] = 0.0f; + } + else if (index % 4 == 3) + { + m_pos[index].x() = m_pos[index-3].x() + m_velocity[index].x(); + m_pos[index].y() = m_pos[index-3].y() + 1 + m_velocity[index].y() ; + m_texture_u[index] = 1.0f; + m_texture_v[index] = 0.0f; + } + + for (int i = index; i < m_particleMaxCount; ++i) + { + m_currentTime[i] += deltaTime; + } +} + +bool engine::ParticleSystem::UpdateActive(float deltaTime,int i) +{ + if (!m_isActive[i]) + { + return false; + } + + Update(deltaTime, i); + if (!m_isActive[i]) + { + m_FreeParticleIndex.push_back(i); + } + else + { + ++m_currentActiveCount; + } + return true; +} + +void engine::ParticleSystem::Init() +{ + m_pos.resize(m_particleMaxCount); + m_rotation.resize(m_particleMaxCount); + m_scale.resize(m_particleMaxCount); + m_velocity.resize(m_particleMaxCount); + m_acceleration.resize(m_particleMaxCount); + m_color.resize(m_particleMaxCount); + m_texture_u.resize(m_particleMaxCount); + m_texture_v.resize(m_particleMaxCount); + + m_isActive.resize(m_particleMaxCount); + m_currentTime.resize(m_particleMaxCount); + m_lifeTime.resize(m_particleMaxCount); +} diff --git a/Engine/Source/Runtime/ParticleSystem/ParticleSystem.h b/Engine/Source/Runtime/ParticleSystem/ParticleSystem.h new file mode 100644 index 00000000..d41481fa --- /dev/null +++ b/Engine/Source/Runtime/ParticleSystem/ParticleSystem.h @@ -0,0 +1,91 @@ +#pragma once + +#include "Base/Template.h" +#include "Core/StringCrc.h" +#include "Math/Vector.hpp" +#include +#include "ECWorld/TransformComponent.h" + +namespace engine +{ + +class ParticleSystem final +{ +public: + ParticleSystem() = default; + ParticleSystem(const ParticleSystem&) = default; + ParticleSystem& operator=(const ParticleSystem&) = default; + ParticleSystem(ParticleSystem&&) = default; + ParticleSystem& operator=(ParticleSystem&&) = default; + ~ParticleSystem() = default; + + int& GetIndex() { return m_particleIndex; } + + int& GetMaxCount() { return m_particleMaxCount; } + + int& GetParticleActiveCount() { return m_currentActiveCount; } + + cd::Vec3f& GetPos(int index) { return m_pos[index]; } + void SetPos(cd::Vec3f pos) { m_pos[m_particleIndex] = pos; } + + cd::Vec3f& GetRotation(int index) { return m_rotation[index]; } + void SetRotation(cd::Vec3f rotate) { m_rotation[m_particleIndex] = rotate; } + + cd::Vec3f& GetScale(int index) { return m_scale[index]; } + void SetScale(cd::Vec3f scale) { m_scale[m_particleIndex] = scale; } + + cd::Vec3f& GetVelocity() { return m_velocity[m_particleIndex]; } + void SetVelocity(cd::Vec3f velocity) { m_velocity[m_particleIndex] = velocity; } + + //cd::Quaternion& GetEmiterDirection( ) { return m_emiterDirection[m_particleIndex]; } + //void SetEmiterDirection(cd::Quaternion direction) { m_emiterDirection[m_particleIndex] = direction; } + + cd::Vec3f& GetAcceleration(int index) { return m_acceleration[index]; } + void SetAcceleration(cd::Vec3f acceleration) { m_acceleration[m_particleIndex] = acceleration; } + + cd::Vec4f& GetColor(int index) { return m_color[index]; } + void SetColor(cd::Vec4f color) { m_color[m_particleIndex] = color; } + + float& GetTexture_u(int index) { return m_texture_u[index]; } + float& GetTexture_v(int index) { return m_texture_v[index]; } + + void Active(int index) { m_isActive[index] = true; } + bool IsActive(int index) { return m_isActive[index]; } + + float& GetLifeTime(int index) { return m_lifeTime[index]; } + void SetLifeTime(float lifeTime) { m_lifeTime[m_particleIndex] = lifeTime; } + + void AllocateParticleIndex(); + + void Reset( int index); + + void Update(float deltaTime, int index); + + bool UpdateActive(float deltaTime, int i); + + void Init(); + +private: + int m_currentParticleCount = 0; + int m_particleIndex = -1; + int m_particleMaxCount = 300; + int m_currentActiveCount = 0; + + std::vector m_FreeParticleIndex; + std::vector m_pos; + std::vectorm_rotation; + std::vectorm_scale; + + std::vector m_velocity; + //std::vector m_emiterDirection; + std::vector m_acceleration; + std::vector m_color; + std::vector m_texture_u; + std::vector m_texture_v; + + std::vector m_isActive; + std::vector m_currentTime; + std::vector m_lifeTime; +}; + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/ParticleRenderer.cpp b/Engine/Source/Runtime/Rendering/ParticleRenderer.cpp index c0c42474..2ac12ba9 100644 --- a/Engine/Source/Runtime/Rendering/ParticleRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/ParticleRenderer.cpp @@ -1,5 +1,4 @@ #include "ParticleRenderer.h" - #include "ECWorld/CameraComponent.h" #include "ECWorld/SceneWorld.h" #include "ECWorld/TransformComponent.h" @@ -9,12 +8,17 @@ namespace engine { void ParticleRenderer::Init() { + constexpr StringCrc ParticleProgram = StringCrc{ "ParticleProgram" }; + GetRenderContext()->RegisterShaderProgram(ParticleProgram, { "vs_particle", "fs_particle" }); bgfx::setViewName(GetViewID(), "ParticleRenderer"); } void ParticleRenderer::Warmup() { - + constexpr const char* particleTexture = "Textures/Particle.png"; + m_particleTextureHandle = GetRenderContext()->CreateTexture(particleTexture); + GetRenderContext()->CreateUniform("s_texColor", bgfx::UniformType::Sampler); + GetRenderContext()->UploadShaderProgram("ParticleProgram"); } void ParticleRenderer::UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) @@ -25,7 +29,72 @@ void ParticleRenderer::UpdateView(const float* pViewMatrix, const float* pProjec void ParticleRenderer::Render(float deltaTime) { - const cd::Transform& cameraTransform = m_pCurrentSceneWorld->GetTransformComponent(m_pCurrentSceneWorld->GetMainCameraEntity())->GetTransform(); + for (Entity entity : m_pCurrentSceneWorld->GetParticleEmitterEntities()) + { + engine::ParticleEmitterComponent* pEmitterComponent = m_pCurrentSceneWorld->GetParticleEmitterComponent(entity); + auto particleMaxCount = pEmitterComponent->GetParticleSystem().GetMaxCount(); + const cd::Transform& particleTransform = m_pCurrentSceneWorld->GetTransformComponent(entity)->GetTransform(); + /* float newAngle = particleTransform.GetRotation().Pitch(); + auto a = cd::Math::DegreeToRadian(newAngle); + auto b = cd::Quaternion::RotateZ(a); + pEmitterComponent->GetParticleSystem().SetFront(b*pEmitterComponent->GetParticleSystem().GetFront()); + cd::Quaternion rotationQuat = cd::Quaternion::FromAxisAngle(pEmitterComponent->GetParticleSystem().GetFront(), particleTransform.GetRotation().Pitch());*/ + + for (int i = 0; i < particleMaxCount; ++i) + { + pEmitterComponent->GetParticleSystem().AllocateParticleIndex(); + pEmitterComponent->GetParticleSystem().SetPos(particleTransform.GetTranslation()); + pEmitterComponent->GetParticleSystem().SetVelocity(pEmitterComponent->GetFVelocity()); + } + + for (int i = 0; i < particleMaxCount; ++i) + { + pEmitterComponent->GetParticleSystem().UpdateActive(deltaTime, i); + } + + pEmitterComponent->PaddingVertexBuffer(); + pEmitterComponent->PaddingIndexBuffer(); + + + const uint16_t instanceStride = 80; + // to total number of instances to draw + uint32_t totalSprites = pEmitterComponent->GetParticleSystem().GetMaxCount(); + uint32_t drawnSprites = bgfx::getAvailInstanceDataBuffer(totalSprites, instanceStride); + + bgfx::InstanceDataBuffer idb; + bgfx::allocInstanceDataBuffer(&idb, drawnSprites, instanceStride); + + uint8_t* data = idb.data; + + for (uint32_t ii = 0; ii < drawnSprites; ++ii) + { + float* mtx = (float*)data; + bx::mtxRotateXY(mtx,0.0f, 0.0f); + mtx[12] = pEmitterComponent->GetParticleSystem().GetPos(ii).x(); + mtx[13] = pEmitterComponent->GetParticleSystem().GetPos(ii).y(); + mtx[14] = pEmitterComponent->GetParticleSystem().GetPos(ii).z(); + float* color = (float*)&data[64]; + color[0] = pEmitterComponent->GetFColor().x(); + color[1] = pEmitterComponent->GetFColor().y(); + color[2] = pEmitterComponent->GetFColor().z(); + color[3] = pEmitterComponent->GetFColor().w(); + + data += instanceStride; + } + + constexpr StringCrc ParticleSampler("s_texColor"); + bgfx::setTexture(0, GetRenderContext()->GetUniform(ParticleSampler), m_particleTextureHandle); + bgfx::setVertexBuffer(0, bgfx::VertexBufferHandle{ pEmitterComponent->GetParticleVBH() }); + bgfx::setIndexBuffer(bgfx::IndexBufferHandle{ pEmitterComponent->GetParticleIBH() }); + + bgfx::setInstanceDataBuffer(&idb); + + constexpr uint64_t state = BGFX_STATE_WRITE_MASK | BGFX_STATE_MSAA | BGFX_STATE_DEPTH_TEST_LESS | + BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA) | BGFX_STATE_PT_TRISTRIP; + bgfx::setState(state); + + GetRenderContext()->Submit(GetViewID(), "ParticleProgram"); + } } } \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/ParticleRenderer.h b/Engine/Source/Runtime/Rendering/ParticleRenderer.h index 36e8e277..99a1979e 100644 --- a/Engine/Source/Runtime/Rendering/ParticleRenderer.h +++ b/Engine/Source/Runtime/Rendering/ParticleRenderer.h @@ -1,6 +1,11 @@ #pragma once #include "Renderer.h" +#include "ECWorld/CameraComponent.h" +#include "ECWorld/SceneWorld.h" +#include "ECWorld/TransformComponent.h" +#include "RenderContext.h" +#include "Rendering/Utility/VertexLayoutUtility.h" namespace engine { @@ -21,6 +26,8 @@ class ParticleRenderer final : public Renderer private: SceneWorld* m_pCurrentSceneWorld = nullptr; + bgfx::TextureHandle m_particleTextureHandle; + }; } \ No newline at end of file diff --git a/Engine/Source/ThirdParty/AssetPipeline b/Engine/Source/ThirdParty/AssetPipeline index 6133ac03..d136b7c5 160000 --- a/Engine/Source/ThirdParty/AssetPipeline +++ b/Engine/Source/ThirdParty/AssetPipeline @@ -1 +1 @@ -Subproject commit 6133ac03e9854ed4c6116a3addd229a254bb3ef1 +Subproject commit d136b7c5405606f1389255b01a0a54214119e9e6