diff --git a/Engine/BuiltInShaders/shaders/fs_particle.sc b/Engine/BuiltInShaders/shaders/fs_particle.sc new file mode 100644 index 00000000..9418a7d3 --- /dev/null +++ b/Engine/BuiltInShaders/shaders/fs_particle.sc @@ -0,0 +1,8 @@ +$input v_color0 +#include "../common/common.sh" + + +void main() +{ + gl_FragColor = float4(v_color0.rgb,1.0f); +} \ No newline at end of file diff --git a/Engine/BuiltInShaders/shaders/varying.def.sc b/Engine/BuiltInShaders/shaders/varying.def.sc deleted file mode 100644 index 07bd3c26..00000000 --- a/Engine/BuiltInShaders/shaders/varying.def.sc +++ /dev/null @@ -1,21 +0,0 @@ -vec2 v_texcoord0 : TEXCOORD0 = vec2(0.0, 0.0); -vec3 v_worldPos : TEXCOORD1 = vec3(0.0, 0.0, 0.0); -vec3 v_skyboxDir : TEXCOORD2 = vec3(0.0, 0.0, 0.0); -vec3 v_bc : TEXCOORD3 = vec3(0.0, 0.0, 0.0); -vec3 v_normal : NORMAL = vec3(0.0, 0.0, 1.0); -mat3 v_TBN : TEXCOORD4; -vec4 v_color0 : COLOR0 = vec4(1.0, 0.0, 0.0, 1.0); -vec4 v_color1 : COLOR1 = vec4(1.0, 0.0, 0.0, 1.0); -flat ivec4 v_indices : BLENDINDICES = vec4(0, 0, 0, 0); -vec4 v_weight : BLENDWEIGHT = vec4(1.0, 1.0, 1.0, 1.0); -vec2 v_alphaMapTexCoord : TEXCOORD5 = vec2(0.0, 0.0); - -vec3 a_position : POSITION; -vec3 a_normal : NORMAL; -vec3 a_tangent : TANGENT; -vec3 a_bitangent : BITANGENT; -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 diff --git a/Engine/BuiltInShaders/shaders/vs_particle.sc b/Engine/BuiltInShaders/shaders/vs_particle.sc new file mode 100644 index 00000000..a4051a8a --- /dev/null +++ b/Engine/BuiltInShaders/shaders/vs_particle.sc @@ -0,0 +1,10 @@ +$input a_position, a_color0 +$output v_color0 + +#include "../common/common.sh" + +void main() +{ + gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0) ); + v_color0 = a_color0; +} \ No newline at end of file diff --git a/Engine/Source/Editor/UILayers/EntityList.cpp b/Engine/Source/Editor/UILayers/EntityList.cpp index 03b10e8c..318c0a21 100644 --- a/Engine/Source/Editor/UILayers/EntityList.cpp +++ b/Engine/Source/Editor/UILayers/EntityList.cpp @@ -221,8 +221,12 @@ void EntityList::AddEntity(engine::SceneWorld* pSceneWorld) else if (ImGui::MenuItem("Add Particle Emitter")) { 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(); + + auto& particleEmitterComponent = pWorld->CreateComponent(entity); } } diff --git a/Engine/Source/Editor/UILayers/Inspector.cpp b/Engine/Source/Editor/UILayers/Inspector.cpp index 6a798860..3e0c6f48 100644 --- a/Engine/Source/Editor/UILayers/Inspector.cpp +++ b/Engine/Source/Editor/UILayers/Inspector.cpp @@ -489,15 +489,16 @@ 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; } - bool isOpen = ImGui::CollapsingHeader("Particle Component", ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_DefaultOpen); + bool isOpen = ImGui::CollapsingHeader("ParticleEmitter Component", ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_DefaultOpen); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2)); ImGui::Separator(); @@ -570,8 +571,7 @@ void Inspector::Update() details::UpdateComponentWidget(pSceneWorld, selectedEntity); details::UpdateComponentWidget(pSceneWorld, selectedEntity); details::UpdateComponentWidget(pSceneWorld, selectedEntity); - details::UpdateComponentWidget(pSceneWorld, selectedEntity); - details::UpdateComponentWidget(pSceneWorld, selectedEntity); + details::UpdateComponentWidget(pSceneWorld, selectedEntity); #ifdef ENABLE_DDGI details::UpdateComponentWidget(pSceneWorld, selectedEntity); diff --git a/Engine/Source/Editor/UILayers/TestNodeEditor.cpp b/Engine/Source/Editor/UILayers/TestNodeEditor.cpp index 22095b7f..edb286fb 100644 --- a/Engine/Source/Editor/UILayers/TestNodeEditor.cpp +++ b/Engine/Source/Editor/UILayers/TestNodeEditor.cpp @@ -1,17 +1,8 @@ #include "TestNodeEditor.h" -#include "ECWorld/CameraComponent.h" -#include "ECWorld/SceneWorld.h" -#include "ECWorld/StaticMeshComponent.h" -#include "ECWorld/TransformComponent.h" -#include "ImGui/ImGuiContextInstance.h" // TODO : can use StringCrc to access other UILayers from ImGuiContextInstance. -#include "UILayers/SceneView.h" -#include -#include -#include namespace ed = ax::NodeEditor; @@ -24,39 +15,229 @@ TestNodeEditor::~TestNodeEditor() void TestNodeEditor::Init() { - ImGuizmo::SetGizmoSizeClipSpace(0.25f); + ImGuizmo::SetGizmoSizeClipSpace(0.25f); - ed::Config config; - config.SettingsFile = "Simple.json"; - m_pNodeEditorContext = ed::CreateEditor(&config); + ed::Config config; + config.SettingsFile = "BasicInteraction.json"; + m_Context = ed::CreateEditor(&config); } void TestNodeEditor::Update() { - { - auto& io = ImGui::GetIO(); - - ImGui::Text("FPS: %.2f (%.2gms)", io.Framerate, io.Framerate ? 1000.0f / io.Framerate : 0.0f); - - ImGui::Separator(); - - ed::SetCurrentEditor(m_pNodeEditorContext); - ed::Begin("My Editor", ImVec2(0.0, 0.0f)); - int uniqueId = 1; - // Start drawing nodes. - ed::BeginNode(uniqueId++); - ImGui::Text("Node A"); - ed::BeginPin(uniqueId++, ed::PinKind::Input); - ImGui::Text("-> In"); - ed::EndPin(); - ImGui::SameLine(); - ed::BeginPin(uniqueId++, ed::PinKind::Output); - ImGui::Text("Out ->"); - ed::EndPin(); - ed::EndNode(); - ed::End(); - ed::SetCurrentEditor(nullptr); - } + { + auto& io = ImGui::GetIO(); + + ImGui::Text("FPS: %.2f (%.2gms)", io.Framerate, io.Framerate ? 1000.0f / io.Framerate : 0.0f); + + ImGui::Separator(); + + ed::SetCurrentEditor(m_Context); + + // Start interaction with editor. + ed::Begin("My Editor", ImVec2(0.0, 0.0f)); + + int uniqueId = 1; + + // + // 1) Commit known data to editor + // + + engine::SceneWorld* pSceneWorld = GetSceneWorld(); + ed::NodeId MaterialNode = uniqueId++; + materialNodePinIds.clear(); + textureMap.clear(); + textureNodeId.clear(); + textureNodePinId.clear(); + + for (int i = 0; i < 9; i++) + { + materialNodePinIds.push_back(uniqueId++); + } + + for (auto& texture : pSceneWorld->GetSceneDatabase()->GetTextures()) + { + textureNodeId.push_back(uniqueId++); + textureNodePinId.push_back(uniqueId++); + switch (texture.GetType()) + { + case cd::MaterialTextureType::BaseColor: + textureTypeList.push_back(0); + break; + case cd::MaterialTextureType::Occlusion: + textureTypeList.push_back(1); + break; + case cd::MaterialTextureType::Roughness: + textureTypeList.push_back(2); + break; + case cd::MaterialTextureType::Metallic: + textureTypeList.push_back(3); + break; + case cd::MaterialTextureType::Normal: + textureTypeList.push_back(4); + break; + case cd::MaterialTextureType::Emissive: + textureTypeList.push_back(5); + break; + case cd::MaterialTextureType::Elevation: + textureTypeList.push_back(6); + break; + case cd::MaterialTextureType::AlphaMap: + textureTypeList.push_back(7); + break; + case cd::MaterialTextureType::General: + textureTypeList.push_back(8); + break; + } + } + + int numNodes = sizeof(textureNodeId) / sizeof(textureNodeId[0]); + if (pSceneWorld->GetSceneDatabase()->GetTextureCount()) + { + for (int i = 0; i < numNodes; i++) + { + if (m_FirstFrame) + ed::SetNodePosition(textureNodeId[i], ImVec2(1, i * 90.0f)); + ed::BeginNode(textureNodeId[i]); + ImGui::Text("texture %d", i); + ed::BeginPin(textureNodePinId[i], ed::PinKind::Output); + ImGui::Text("Out ->"); + ed::EndPin(); + ed::EndNode(); + } + } + + if (pSceneWorld->GetSceneDatabase()->GetMaterialCount()) + { + if (m_FirstFrame) + ed::SetNodePosition(MaterialNode, ImVec2(0, 90)); + ed::BeginNode(MaterialNode); + ImGui::Text("Material "); + ed::BeginPin(materialNodePinIds[0], ed::PinKind::Input); + ImGui::Text(" BaseColor"); + ed::EndPin(); + ed::BeginPin(materialNodePinIds[1], ed::PinKind::Input); + ImGui::Text(" Occlusion"); + ed::EndPin(); + ed::BeginPin(materialNodePinIds[2], ed::PinKind::Input); + ImGui::Text(" Roughness"); + ed::EndPin(); + ed::BeginPin(materialNodePinIds[3], ed::PinKind::Input); + ImGui::Text(" Metallic"); + ed::EndPin(); + ed::BeginPin(materialNodePinIds[4], ed::PinKind::Input); + ImGui::Text(" Normal"); + ed::EndPin(); + ed::BeginPin(materialNodePinIds[5], ed::PinKind::Input); + ImGui::Text(" Emissive"); + ed::EndPin(); + ed::BeginPin(materialNodePinIds[6], ed::PinKind::Input); + ImGui::Text(" Elevation"); + ed::EndPin(); + ed::BeginPin(materialNodePinIds[7], ed::PinKind::Input); + ImGui::Text(" AlphaMap"); + ed::EndPin(); + ed::BeginPin(materialNodePinIds[8], ed::PinKind::Input); + ImGui::Text(" General"); + ed::EndPin(); + ed::EndNode(); + } + + if ((pSceneWorld->GetSceneDatabase()->GetMaterialCount() || pSceneWorld->GetSceneDatabase()->GetTextureCount() )&& linkSwitch) + { + for (int i = 0; i < numNodes; i++) + { + m_Links.push_back({ ed::LinkId(m_NextLinkId++), textureNodePinId[i], materialNodePinIds[textureTypeList[i]] }); + ed::Link(m_Links.back().Id, m_Links.back().InputId, m_Links.back().OutputId); + } + linkSwitch = false; + } + + // Submit Links + for (auto& linkInfo : m_Links) + ed::Link(linkInfo.Id, linkInfo.InputId, linkInfo.OutputId); + + // + // 2) Handle interactions + // + + // Handle creation action, returns true if editor want to create new object (node or link) + if (ed::BeginCreate()) + { + ed::PinId inputPinId, outputPinId; + if (ed::QueryNewLink(&inputPinId, &outputPinId)) + { + // QueryNewLink returns true if editor want to create new link between pins. + // + // Link can be created only for two valid pins, it is up to you to + // validate if connection make sense. Editor is happy to make any. + // + // Link always goes from input to output. User may choose to drag + // link from output pin or input pin. This determine which pin ids + // are valid and which are not: + // * input valid, output invalid - user started to drag new ling from input pin + // * input invalid, output valid - user started to drag new ling from output pin + // * input valid, output valid - user dragged link over other pin, can be validated + + if (inputPinId && outputPinId) // both are valid, let's accept link + { + // ed::AcceptNewItem() return true when user release mouse button. + if (ed::AcceptNewItem()) + { + // Since we accepted new link, lets add one to our list of links. + m_Links.push_back({ ed::LinkId(m_NextLinkId++), inputPinId, outputPinId }); + + // Draw new link. + ed::Link(m_Links.back().Id, m_Links.back().InputId, m_Links.back().OutputId); + } + + // You may choose to reject connection between these nodes + // by calling ed::RejectNewItem(). This will allow editor to give + // visual feedback by changing link thickness and color. + } + } + } + ed::EndCreate(); // Wraps up object creation action handling. + + + // Handle deletion action + if (ed::BeginDelete()) + { + // There may be many links marked for deletion, let's loop over them. + ed::LinkId deletedLinkId; + while (ed::QueryDeletedLink(&deletedLinkId)) + { + // If you agree that link can be deleted, accept deletion. + if (ed::AcceptDeletedItem()) + { + // Then remove link from your data. + for (auto& link : m_Links) + { + if (link.Id == deletedLinkId) + { + m_Links.erase(&link); + break; + } + } + } + + // You may reject link deletion by calling: + // ed::RejectDeletedItem(); + } + } + ed::EndDelete(); // Wrap up deletion action + + // End of interaction with editor. + ed::End(); + + if (m_FirstFrame) + ed::NavigateToContent(0.0f); + + ed::SetCurrentEditor(nullptr); + + m_FirstFrame = false; + + // ImGui::ShowMetricsWindow(); + } } } \ No newline at end of file diff --git a/Engine/Source/Editor/UILayers/TestNodeEditor.h b/Engine/Source/Editor/UILayers/TestNodeEditor.h index 6630fa15..dce008bb 100644 --- a/Engine/Source/Editor/UILayers/TestNodeEditor.h +++ b/Engine/Source/Editor/UILayers/TestNodeEditor.h @@ -1,10 +1,26 @@ +#include +#include #include "ImGui/ImGuiBaseLayer.h" - +#include +#include +#include +#include + +#include "ECWorld/CameraComponent.h" +#include "ECWorld/SceneWorld.h" +#include "ECWorld/StaticMeshComponent.h" +#include "ECWorld/TransformComponent.h" +#include "ImGui/ImGuiContextInstance.h" namespace ax::NodeEditor { struct EditorContext; - +struct LinkInfo +{ + LinkId Id; + PinId InputId; + PinId OutputId; +}; } namespace editor @@ -20,7 +36,19 @@ class TestNodeEditor : public engine::ImGuiBaseLayer virtual void Update() override; private: - ax::NodeEditor::EditorContext* m_pNodeEditorContext = nullptr; + + ax::NodeEditor::EditorContext* m_Context = nullptr; + bool m_FirstFrame = true; + ImVector m_Links; + int m_NextLinkId = 100; + + std::vector materialNodePinIds; + + std::map textureMap; + std::vector< ax::NodeEditor::NodeId> textureNodeId; + std::vector< ax::NodeEditor::PinId> textureNodePinId; + std::vector< int> textureTypeList; + bool linkSwitch = true; }; } \ No newline at end of file diff --git a/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h b/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h index 7a12eb12..7ba4a552 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..cdda36f0 100644 --- a/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.cpp +++ b/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.cpp @@ -1 +1,57 @@ #include "ParticleEmitterComponent.h" +#include "Scene/VertexFormat.h" +#include "Rendering/Utility/VertexLayoutUtility.h" + +void engine::ParticleEmitterComponent::Build() +{ + cd::VertexFormat vertexFormat; + vertexFormat.AddAttributeLayout(cd::VertexAttributeType::Position, cd::AttributeValueType::Float, 3); + vertexFormat.AddAttributeLayout(cd::VertexAttributeType::Color, cd::AttributeValueType::Float, 3); + + bgfx::VertexLayout vertexLayout; + VertexLayoutUtility::CreateVertexLayout(vertexLayout, vertexFormat.GetVertexLayout()); + + size_t vertexCount = m_particleSystem.GetMaxCount(); + + size_t vertexBufferSize = vertexCount * (sizeof(cd::Vec3f) + sizeof(cd::Vec3f)); + + 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::Vec3f)); + currentDataSize += sizeof(cd::Vec3f); + } + +/* +* indexBuffer +*/ + size_t indexTypeSize = sizeof(uint16_t); + m_particleIndexBuffer.resize(3 * m_particleSystem.GetMaxCount() * indexTypeSize); + currentDataSize = 0U; + currentDataPtr = m_particleIndexBuffer.data(); + + std::vector indexes; + for (uint16_t i = 0; i < m_particleSystem.GetMaxCount(); i++) + { + uint16_t vertexIndex = static_cast(i * 3); + indexes.push_back(vertexIndex); + indexes.push_back(vertexIndex + 1); + indexes.push_back(vertexIndex + 2); + } + + for (const auto& index : indexes) + { + std::memcpy(¤tDataPtr[currentDataSize], &index, indexTypeSize); + currentDataSize += static_cast(indexTypeSize); + } + + 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; +} diff --git a/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.h b/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.h index b21634cd..a0a6d636 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,26 @@ class ParticleEmitterComponent final ParticleEmitterComponent& operator=(ParticleEmitterComponent&&) = default; ~ParticleEmitterComponent() = default; -private: + engine::ParticleSystem GetParticleSystem() { return m_particleSystem; } + void SetParticleSystem(engine::ParticleSystem& system) { m_particleSystem = system; } + + uint16_t& GetParticleVBH(){ return m_particleVBH; } + void setParticleVBH(uint16_t vbh) { m_particleVBH = vbh; } + + uint16_t& GetParticleIBH() { return m_particleIBH; } + void SetParticleIBH(uint16_t ibh) { m_particleIBH = ibh; } + std::vector &GetVertexBuffer() { return m_particleVertexBuffer; } + std::vector &GetIndexBuffer() { return m_particleIndexBuffer; } + + void Build(); + +private: + ParticleSystem m_particleSystem; + 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 080c99cc..a7f17d4d 100644 --- a/Engine/Source/Runtime/ECWorld/SceneWorld.cpp +++ b/Engine/Source/Runtime/ECWorld/SceneWorld.cpp @@ -35,10 +35,9 @@ SceneWorld::SceneWorld() m_pShaderVariantCollectionsComponentStorage = 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(); + m_pParticleEmitterComponentStorage = m_pWorld->Register(); #ifdef ENABLE_DDGI CreateDDGIMaterialType(); diff --git a/Engine/Source/Runtime/ECWorld/SceneWorld.h b/Engine/Source/Runtime/ECWorld/SceneWorld.h index 5774d21c..7863664b 100644 --- a/Engine/Source/Runtime/ECWorld/SceneWorld.h +++ b/Engine/Source/Runtime/ECWorld/SceneWorld.h @@ -41,6 +41,8 @@ class SceneWorld DEFINE_COMPONENT_STORAGE_WITH_APIS(Sky); DEFINE_COMPONENT_STORAGE_WITH_APIS(StaticMesh); DEFINE_COMPONENT_STORAGE_WITH_APIS(Particle); + DEFINE_COMPONENT_STORAGE_WITH_APIS(Terrain); + DEFINE_COMPONENT_STORAGE_WITH_APIS(Transform); DEFINE_COMPONENT_STORAGE_WITH_APIS(ParticleEmitter); DEFINE_COMPONENT_STORAGE_WITH_APIS(Terrain); DEFINE_COMPONENT_STORAGE_WITH_APIS(Transform); @@ -101,10 +103,9 @@ class SceneWorld DeleteShaderVariantCollectionsComponent(entity); DeleteSkyComponent(entity); DeleteStaticMeshComponent(entity); - DeleteParticleComponent(entity); - DeleteParticleEmitterComponent(entity); DeleteTerrainComponent(entity); DeleteTransformComponent(entity); + DeleteParticleEmitterComponent(entity); } void CreatePBRMaterialType(bool isAtmosphericScatteringEnable = false); diff --git a/Engine/Source/Runtime/ImGui/ImGuiContextInstance.cpp b/Engine/Source/Runtime/ImGui/ImGuiContextInstance.cpp index 0f174135..65610268 100644 --- a/Engine/Source/Runtime/ImGui/ImGuiContextInstance.cpp +++ b/Engine/Source/Runtime/ImGui/ImGuiContextInstance.cpp @@ -92,6 +92,7 @@ std::unordered_map kImguiKeyLookup { {engine::KeyCode::x, ImGuiKey::ImGuiKey_X}, {engine::KeyCode::y, ImGuiKey::ImGuiKey_Y}, {engine::KeyCode::z, ImGuiKey::ImGuiKey_Z}, + {engine::KeyCode::del, ImGuiKey::ImGuiKey_Delete}, }; std::unordered_map kImguiKeyModToImGuiKeyLookup{ diff --git a/Engine/Source/Runtime/ParticleSystem/ParticleSystem.cpp b/Engine/Source/Runtime/ParticleSystem/ParticleSystem.cpp new file mode 100644 index 00000000..172530cf --- /dev/null +++ b/Engine/Source/Runtime/ParticleSystem/ParticleSystem.cpp @@ -0,0 +1,99 @@ +#include "ParticleSystem.h" + +void engine::ParticleSystem::AllocateParticleIndex() +{ + if (!m_FreeParticleIndex.empty()) + { + int index = m_FreeParticleIndex.back(); + m_FreeParticleIndex.pop_back(); + m_particleIndex = index; + } + else + { + ++m_particleIndex; + if (m_particleIndex >= m_particleMaxCount) + { + m_particleIndex = 0; + } + + if (m_isActive[m_particleIndex]) + { + //full + m_particleIndex = -1; + } + } + + 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_velocity[index] = cd::Vec3f(rand() % 41, 0.0f, 0.0f); + m_acceleration[index] = cd::Vec3f(0.0f, 0.0f, 0.0f); + + m_color[index] = cd::Vec3f{rand() %30, rand() %45,0.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; + return; + } + + //x = v0t +1/2 at*2 + m_pos[index].x() = m_pos[index].x() + m_velocity[index].x() * deltaTime + 0.5f * m_acceleration[index].x() * deltaTime * deltaTime; + m_pos[index].y() = m_pos[index].y() + m_velocity[index].y() * deltaTime + 0.5f * m_acceleration[index].y() * deltaTime * deltaTime; + m_pos[index].z() = m_pos[index].z() + m_velocity[index].z() * deltaTime + 0.5f * m_acceleration[index].z() * deltaTime * deltaTime; + + m_velocity[index].x() += m_acceleration[index].x() * deltaTime; + m_velocity[index].y() += m_acceleration[index].y() * deltaTime; + m_velocity[index].z() += m_acceleration[index].z() * deltaTime; + + m_currentTime[index] += deltaTime; +} + +void engine::ParticleSystem::UpdateActive(float deltaTime) +{ + for (int i = 0; i < m_particleMaxCount; ++i) + { + if (!m_isActive[i]) + { + continue; + } + + Update(deltaTime, i); + if (!m_isActive[i]) + { + m_FreeParticleIndex.push_back(i); + } + else + { + ++m_currentActiveCount; + } + } +} + +void engine::ParticleSystem::Init() +{ + m_FreeParticleIndex.resize(m_particleMaxCount); + m_pos.resize(m_particleMaxCount); + m_velocity.resize(m_particleMaxCount); + m_acceleration.resize(m_particleMaxCount); + m_color.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..0dc6d876 --- /dev/null +++ b/Engine/Source/Runtime/ParticleSystem/ParticleSystem.h @@ -0,0 +1,71 @@ +#pragma once + +#include "Base/Template.h" +#include "Core/StringCrc.h" +#include "Math/Vector.hpp" +#include + +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& GetVelocity(int index) { return m_velocity[index]; } + void SetVelocity(cd::Vec3f velocity) { m_velocity[m_particleIndex] = velocity; } + + cd::Vec3f& GetAcceleration(int index) { return m_acceleration[index]; } + void SetAcceleration(cd::Vec3f acceleration) { m_acceleration[m_particleIndex] = acceleration; } + + cd::Vec3f& GetColor(int index) { return m_color[index]; } + void SetColor(cd::Vec3f color) { m_color[m_particleIndex] = color; } + + 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); + + void UpdateActive(float deltaTime); + + void Init(); + +private: + int m_particleIndex = -1; + int m_particleMaxCount = 300; + int m_currentActiveCount = 0; + + std::vector m_FreeParticleIndex; + std::vector m_pos; + std::vector m_velocity; + std::vector m_acceleration; + std::vector m_color; + + 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 a9e14364..3bdcfa79 100644 --- a/Engine/Source/Runtime/Rendering/ParticleRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/ParticleRenderer.cpp @@ -4,11 +4,13 @@ #include "ECWorld/SceneWorld.h" #include "ECWorld/TransformComponent.h" #include "RenderContext.h" +#include "Rendering/Utility/VertexLayoutUtility.h" namespace engine { void ParticleRenderer::Init() { + GetRenderContext()->CreateProgram("ParticleProgram", "vs_particle.bin", "fs_particle.bin"); bgfx::setViewName(GetViewID(), "ParticleRenderer"); } @@ -20,7 +22,80 @@ 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); + + engine::ParticleSystem particles; + particles.Init(); + particles.AllocateParticleIndex(); + particles.UpdateActive(1/deltaTime); + + pEmitterComponent->SetParticleSystem(particles); + pEmitterComponent->Build(); + + bgfx::setVertexBuffer(0, bgfx::VertexBufferHandle{ pEmitterComponent->GetParticleVBH() }); + bgfx::setIndexBuffer(bgfx::IndexBufferHandle{ pEmitterComponent->GetParticleIBH() }); + + 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_LINES; + bgfx::setState(state); + + constexpr StringCrc ParticleProgram("ParticleProgram"); + bgfx::submit(GetViewID(), GetRenderContext()->GetProgram(ParticleProgram)); + } + // engine::ParticleEmitterComponent* pEmitterComponent = m_pCurrentSceneWorld->GetParticleEmitterComponent(entity); + // const cd::Transform& transform = m_pCurrentSceneWorld->GetTransformComponent(entity)->GetTransform(); + // pEmitterComponent->init(); + // int particleindex = pEmitterComponent->allocateParticleIndex(); + // ParticleComponent& particle = pEmitterComponent->getParticle(particleindex); + // if (pEmitterComponent->allocateParticleIndex() != -1) + // { + // particle.setPos(transform.GetTranslation()); + // particle.setVelocity(cd::Vec3f(-0.02f + rand() % 4100, 0.0f, 0.0f)); + // particle.setAcceleration(cd::Vec3f(0.0f, 0.0f, 0.0f)); + // particle.setColor(cd::Vec3f(1.0f, 0.0f, 0.0f)); + // particle.setLifeTime(1.0f + rand() % 7); + // } + + // pEmitterComponent->update(1.0f / deltaTime); + + // cd::VertexFormat vertexFormat; + // vertexFormat.AddAttributeLayout(cd::VertexAttributeType::Position, cd::AttributeValueType::Float, 3); + // vertexFormat.AddAttributeLayout(cd::VertexAttributeType::Color, cd::AttributeValueType::Float, 3); + + // bgfx::VertexLayout vertexLayout; + // VertexLayoutUtility::CreateVertexLayout(vertexLayout, vertexFormat.GetVertexLayout()); + + // //vertex + // pEmitterComponent->GetVertexBuffer().resize(2*sizeof(cd::Vec3f)); + + + // std::memcpy(pEmitterComponent->GetVertexBuffer().data(), &particle.getPos(), sizeof(cd::Vec3f)); + // std::memcpy(pEmitterComponent->GetVertexBuffer().data()+sizeof(cd::Vec3f), &particle.getColor(), sizeof(cd::Vec3f)); + + + // //index + ///* std::vector indices = { 0, 1 }; + // emitter->GetIndexBuffer().resize(2*sizeof(uint16_t)); + // std::memcpy(emitter->GetIndexBuffer().data(), indices.data(), sizeof(indices));*/ + + + // pEmitterComponent->setParticleVBH(bgfx::createVertexBuffer(bgfx::makeRef(pEmitterComponent->GetVertexBuffer().data(), static_cast(pEmitterComponent->GetVertexBuffer().size())), vertexLayout).idx); + // //emitter->setParticleIBH( bgfx::createIndexBuffer(bgfx::makeRef(emitter->GetIndexBuffer().data(), static_cast(emitter->GetIndexBuffer().size())),0U).idx); + + // bgfx::setVertexBuffer(0, bgfx::VertexBufferHandle{ pEmitterComponent->getParticleVBH() }); + //// bgfx::setIndexBuffer(bgfx::IndexBufferHandle{ emitter->getParticleIBH() }); + + // 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_POINTS; + + // bgfx::setState(state); + + // constexpr StringCrc ParticleProgram("ParticleProgram"); + // bgfx::submit(GetViewID(), GetRenderContext()->GetProgram(ParticleProgram)); + // + //const cd::Transform& cameraTransform = m_pCurrentSceneWorld->GetTransformComponent(m_pCurrentSceneWorld->GetMainCameraEntity())->GetTransform(); } } \ No newline at end of file diff --git a/Engine/Source/Runtime/Window/KeyCode.h b/Engine/Source/Runtime/Window/KeyCode.h index c250fa9d..178482e4 100644 --- a/Engine/Source/Runtime/Window/KeyCode.h +++ b/Engine/Source/Runtime/Window/KeyCode.h @@ -367,7 +367,7 @@ enum class KeyCode : uint8_t //INSERT = SCANCODE_TO_KEYCODE(SCANCODE_INSERT), //HOME = SCANCODE_TO_KEYCODE(SCANCODE_HOME), //PAGEUP = SCANCODE_TO_KEYCODE(SCANCODE_PAGEUP), - //DELETE = '\x7F', + del = '\x7F', //END = SCANCODE_TO_KEYCODE(SCANCODE_END), //PAGEDOWN = SCANCODE_TO_KEYCODE(SCANCODE_PAGEDOWN), //RIGHT = SCANCODE_TO_KEYCODE(SCANCODE_RIGHT), diff --git a/Engine/Source/ThirdParty/AssetPipeline b/Engine/Source/ThirdParty/AssetPipeline index 1e4b58f9..0b264e08 160000 --- a/Engine/Source/ThirdParty/AssetPipeline +++ b/Engine/Source/ThirdParty/AssetPipeline @@ -1 +1 @@ -Subproject commit 1e4b58f964f8adeff84038fb4f3be89eb26e6514 +Subproject commit 0b264e08618a3ff041a82603427279d2dc1f2ba0