diff --git a/Engine/BuiltInShaders/UniformDefines/U_Particle.sh b/Engine/BuiltInShaders/UniformDefines/U_Particle.sh new file mode 100644 index 00000000..812b8b5a --- /dev/null +++ b/Engine/BuiltInShaders/UniformDefines/U_Particle.sh @@ -0,0 +1 @@ +#define PT_RIBBON_VERTEX_STAGE 1 \ No newline at end of file diff --git a/Engine/BuiltInShaders/shaders/cs_particleRibbon.sc b/Engine/BuiltInShaders/shaders/cs_particleRibbon.sc new file mode 100644 index 00000000..65ea35aa --- /dev/null +++ b/Engine/BuiltInShaders/shaders/cs_particleRibbon.sc @@ -0,0 +1,32 @@ +#include "../common/bgfx_compute.sh" +#include "../UniformDefines/U_Particle.sh" + +BUFFER_RW(AllRibbonParticleVertex, vec4, PT_RIBBON_VERTEX_STAGE); + +uniform vec4 u_ribbonCount; +// x : allRibbonVertexCount +// y : particleActiveCount + +uniform vec4 u_ribbonMaxPos[300]; +//here have max particle count (max limit of inspector) + +NUM_THREADS(1u, 1u, 1u) +void main() +{ + for(uint i = 0,index= 0; i CreateComponent(entity); nameComponent.SetName(emitter.GetName()); auto& particleEmitterComponent = pWorld->CreateComponent(entity); + auto& particleMaterialComponent = pWorld->CreateComponent(entity); // TODO : Some initialization here. auto& transformComponent = pWorld->CreateComponent(entity); cd::Vec3f pos = emitter.GetPosition(); @@ -465,8 +466,8 @@ void ECWorldConsumer::AddParticleEmitter(engine::Entity entity, const cd::Mesh& particleEmitterComponent.SetEmitterVelocity(emitter.GetVelocity()); particleEmitterComponent.SetEmitterAcceleration(emitter.GetAccelerate()); particleEmitterComponent.SetMeshData(&mesh); - particleEmitterComponent.SetMaterialType(pMaterialType); - particleEmitterComponent.ActivateShaderFeature(engine::ShaderFeature::PARTICLE_INSTANCE); + particleMaterialComponent.SetMaterialType(pMaterialType); + //particleMaterialComponent.ActivateShaderFeature(engine::ShaderFeature::PARTICLE_INSTANCE); particleEmitterComponent.Build(); } diff --git a/Engine/Source/Editor/EditorApp.cpp b/Engine/Source/Editor/EditorApp.cpp index ad40c564..c7e0cfd2 100644 --- a/Engine/Source/Editor/EditorApp.cpp +++ b/Engine/Source/Editor/EditorApp.cpp @@ -264,7 +264,7 @@ void EditorApp::InitMaterialType() m_pRenderContext->RegisterShaderProgram("WorldProgram", "vs_PBR", "fs_PBR"); m_pRenderContext->RegisterShaderProgram("AnimationProgram", "vs_animation", "fs_animation"); m_pRenderContext->RegisterShaderProgram("TerrainProgram", "vs_terrain", "fs_terrain"); - m_pRenderContext->RegisterShaderProgram("ParticleProgram", "vs_particle", "fs_particle"); + m_pRenderContext->RegisterShaderProgram("ParticleProgram", "vs_particleSprite", "fs_particleSprite"); m_pRenderContext->RegisterShaderProgram("CelluloidProgram", "vs_celluloid", "fs_celluloid"); m_pSceneWorld = std::make_unique(); diff --git a/Engine/Source/Editor/UILayers/EntityList.cpp b/Engine/Source/Editor/UILayers/EntityList.cpp index 8826c860..28a06cf4 100644 --- a/Engine/Source/Editor/UILayers/EntityList.cpp +++ b/Engine/Source/Editor/UILayers/EntityList.cpp @@ -261,16 +261,18 @@ void EntityList::AddEntity(engine::SceneWorld* pSceneWorld) { engine::Entity entity = AddNamedEntity("ParticleEmitter"); auto& particleEmitterComponent = pWorld->CreateComponent(entity); + auto& particleRibbonComponent = pWorld->CreateComponent(entity); + auto& particleMaterialComponent = pWorld->CreateComponent(entity); // TODO : Some initialization here. auto& transformComponent = pWorld->CreateComponent(entity); transformComponent.SetTransform(cd::Transform::Identity()); transformComponent.Build(); particleEmitterComponent.SetRequiredVertexFormat(&pParticleMaterialType->GetRequiredVertexFormat());//to do : modify vertexFormat - particleEmitterComponent.SetMaterialType(pParticleMaterialType); - particleEmitterComponent.ActivateShaderFeature(engine::ShaderFeature::PARTICLE_INSTANCE); + particleMaterialComponent.Init(); + particleMaterialComponent.SetMaterialType(pParticleMaterialType); + //particleMaterialComponent.ActivateShaderFeature(engine::ShaderFeature::PARTICLE_INSTANCE); particleEmitterComponent.Build(); - //auto& particleForceFieldComponent = pWorld->CreateComponent(entity); - //particleForceFieldComponent.Build(); + particleRibbonComponent.Build(); } else if (ImGui::MenuItem("Add Particle ForceField")) { diff --git a/Engine/Source/Editor/UILayers/Inspector.cpp b/Engine/Source/Editor/UILayers/Inspector.cpp index 8107e63c..95158932 100644 --- a/Engine/Source/Editor/UILayers/Inspector.cpp +++ b/Engine/Source/Editor/UILayers/Inspector.cpp @@ -653,6 +653,7 @@ template<> void UpdateComponentWidget(engine::SceneWorld* pSceneWorld, engine::Entity entity) { auto* pParticleEmitterComponent = pSceneWorld->GetParticleEmitterComponent(entity); + auto* pParticleMaterialComponent = pSceneWorld->GetMaterialComponent(entity); if (!pParticleEmitterComponent) { return; @@ -664,7 +665,7 @@ void UpdateComponentWidget(engine::SceneWorld* if (isOpen) { - ImGuiUtils::ImGuiEnumProperty("Render Mode", pParticleEmitterComponent->GetRenderMode()); + ImGuiUtils::ImGuiEnumProperty("Render Mode(Work Type Sprite)", pParticleEmitterComponent->GetRenderMode()); ImGuiUtils::ImGuiEnumProperty("Particle Type", pParticleEmitterComponent->GetEmitterParticleType()); //ImGuiUtils::ImGuiEnumProperty("Emitter Shape", pParticleEmitterComponent->GetEmitterShape()); ImGuiUtils::ImGuiVectorProperty("Emitter Range", pParticleEmitterComponent->GetEmitterShapeRange()); @@ -672,17 +673,16 @@ void UpdateComponentWidget(engine::SceneWorld* ImGuiUtils::ImGuiIntProperty("Max Count", pParticleEmitterComponent->GetSpawnCount(), cd::Unit::None, 1, 300); ImGuiUtils::ImGuiVectorProperty("Velocity", pParticleEmitterComponent->GetEmitterVelocity()); ImGuiUtils::ImGuiVectorProperty("Random Velocity", pParticleEmitterComponent->GetRandomVelocity()); - ImGuiUtils::ImGuiBoolProperty("RandomVelocity", pParticleEmitterComponent->GetRandomVelocityState()); + ImGuiUtils::ImGuiBoolProperty("RandomVelocity State", pParticleEmitterComponent->GetRandomVelocityState()); ImGuiUtils::ImGuiVectorProperty("Acceleration", pParticleEmitterComponent->GetEmitterAcceleration()); ImGuiUtils::ColorPickerProperty("Color", pParticleEmitterComponent->GetEmitterColor()); - ImGuiUtils::ImGuiFloatProperty("LifeTime", pParticleEmitterComponent->GetLifeTime()); - if (ImGuiUtils::ImGuiBoolProperty("Instance State", pParticleEmitterComponent->GetInstanceState())) + ImGuiUtils::ImGuiFloatProperty("LifeTime", pParticleEmitterComponent->GetLifeTime(),cd::Unit::None, 0, 6); + bool featureChanged = ImGuiUtils::ImGuiBoolProperty("Instance State(Work Type Sprite)", pParticleEmitterComponent->GetInstanceState()); + if (featureChanged) { - pParticleEmitterComponent->ActivateShaderFeature(engine::ShaderFeature::PARTICLE_INSTANCE); - } - else - { - pParticleEmitterComponent->DeactivateShaderFeature(engine::ShaderFeature::PARTICLE_INSTANCE); + pParticleEmitterComponent->GetInstanceState() ? + pParticleMaterialComponent->ActivateShaderFeature(engine::ShaderFeature::PARTICLE_INSTANCE) : + pParticleMaterialComponent->DeactivateShaderFeature(engine::ShaderFeature::PARTICLE_INSTANCE); } } diff --git a/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h b/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h index 40028a47..9c8e2568 100644 --- a/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h +++ b/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h @@ -18,4 +18,5 @@ #include "ECWorld/TerrainComponent.h" #include "ECWorld/TransformComponent.h" #include "ECWorld/ParticleEmitterComponent.h" +#include "ECWorld/ParticleRibbonComponent.h" #include "ECWorld/ParticleForceFieldComponent.h" \ No newline at end of file diff --git a/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.cpp b/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.cpp index 69093d6d..eecf327e 100644 --- a/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.cpp +++ b/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.cpp @@ -10,155 +10,117 @@ namespace engine void ParticleEmitterComponent::Build() { + //Sprite BuildParticleShape(); bgfx::VertexLayout vertexLayout; VertexLayoutUtility::CreateVertexLayout(vertexLayout, m_pRequiredVertexFormat->GetVertexAttributeLayouts()); + //VertexBuffer IndexBuffer if (m_pMeshData == nullptr) { - PaddingVertexBuffer(); - PaddingIndexBuffer(); + PaddingSpriteVertexBuffer(); + PaddingSpriteIndexBuffer(); - m_particleVertexBufferHandle = bgfx::createVertexBuffer(bgfx::makeRef(m_particleVertexBuffer.data(), static_cast(m_particleVertexBuffer.size())), vertexLayout).idx; - m_particleIndexBufferHandle = bgfx::createIndexBuffer(bgfx::makeRef(m_particleIndexBuffer.data(), static_cast(m_particleIndexBuffer.size())), 0U).idx; + m_spriteParticleVertexBufferHandle = bgfx::createVertexBuffer(bgfx::makeRef(m_spriteParticleVertexBuffer.data(), static_cast(m_spriteParticleVertexBuffer.size())), vertexLayout).idx; + m_spriteParticleIndexBufferHandle = bgfx::createIndexBuffer(bgfx::makeRef(m_spriteParticleIndexBuffer.data(), static_cast(m_spriteParticleIndexBuffer.size())), 0U).idx; } else { - m_particleVertexBuffer = cd::BuildVertexBufferForStaticMesh(*m_pMeshData, *m_pRequiredVertexFormat).value(); + //TODO: mesh only have sprite now we need to add more different particle type + m_spriteParticleVertexBuffer = cd::BuildVertexBufferForStaticMesh(*m_pMeshData, *m_pRequiredVertexFormat).value(); for (const auto& optionalVec : cd::BuildIndexBufferesForMesh(*m_pMeshData)) { const std::vector& vec = optionalVec.value(); - m_particleIndexBuffer.insert(m_particleIndexBuffer.end(), vec.begin(), vec.end()); + m_spriteParticleIndexBuffer.insert(m_spriteParticleIndexBuffer.end(), vec.begin(), vec.end()); } - m_particleVertexBufferHandle = bgfx::createVertexBuffer(bgfx::makeRef(m_particleVertexBuffer.data(), static_cast(m_particleVertexBuffer.size())), vertexLayout).idx; - m_particleIndexBufferHandle = bgfx::createIndexBuffer(bgfx::makeRef(m_particleIndexBuffer.data(), static_cast(m_particleIndexBuffer.size())), 0U).idx; + m_spriteParticleVertexBufferHandle = bgfx::createVertexBuffer(bgfx::makeRef(m_spriteParticleVertexBuffer.data(), static_cast(m_spriteParticleVertexBuffer.size())), vertexLayout).idx; + m_spriteParticleIndexBufferHandle = bgfx::createIndexBuffer(bgfx::makeRef(m_spriteParticleIndexBuffer.data(), static_cast(m_spriteParticleIndexBuffer.size())), 0U).idx; } } -void ParticleEmitterComponent::PaddingVertexBuffer() +void ParticleEmitterComponent::PaddingSpriteVertexBuffer() { //m_particleVertexBuffer.clear(); //m_particleVertexBuffer.insert(m_particleVertexBuffer.end(), m_particlePool.GetRenderDataBuffer().begin(), m_particlePool.GetRenderDataBuffer().end()); - m_particleVertexBuffer.clear(); - const bool containsPosition = m_pRequiredVertexFormat->Contains(cd::VertexAttributeType::Position); const bool containsColor = m_pRequiredVertexFormat->Contains(cd::VertexAttributeType::Color); const bool containsUV = m_pRequiredVertexFormat->Contains(cd::VertexAttributeType::UV); //vertexbuffer - if (m_emitterParticleType == ParticleType::Sprite) - { - constexpr int meshVertexCount = Particle::GetMeshVertexCount(); - const int MAX_VERTEX_COUNT = m_particlePool.GetParticleMaxCount() * meshVertexCount; - size_t vertexCount = MAX_VERTEX_COUNT; - const uint32_t vertexFormatStride = m_pRequiredVertexFormat->GetStride(); - - m_particleVertexBuffer.resize(vertexCount * vertexFormatStride); - - uint32_t currentDataSize = 0U; - auto currentDataPtr = m_particleVertexBuffer.data(); - - std::vector vertexDataBuffer; - vertexDataBuffer.resize(MAX_VERTEX_COUNT); - // pos color uv - // only a picture now - for (int i = 0; i < MAX_VERTEX_COUNT; i += meshVertexCount) - { - vertexDataBuffer[i] = { cd::Vec3f(-1.0f,-1.0f,0.0f),cd::Vec4f(1.0f,1.0f,1.0f,1.0f),cd::Vec2f(1.0f,1.0f) }; - vertexDataBuffer[i + 1] = { cd::Vec3f(1.0f,-1.0f,0.0f),cd::Vec4f(1.0f,1.0f,1.0f,1.0f),cd::Vec2f(0.0f,1.0f) }; - vertexDataBuffer[i + 2] = { cd::Vec3f(1.0f,1.0f,0.0f),cd::Vec4f(1.0f,1.0f,1.0f,1.0f),cd::Vec2f(0.0f,0.0f) }; - vertexDataBuffer[i + 3] = { cd::Vec3f(-1.0f,1.0f,0.0f),cd::Vec4f(1.0f,1.0f,1.0f,1.0f),cd::Vec2f(1.0f,0.0f) }; - } + constexpr int meshVertexCount = Particle::GetMeshVertexCount(); + const int MAX_VERTEX_COUNT = m_particlePool.GetParticleMaxCount() * meshVertexCount; + size_t vertexCount = MAX_VERTEX_COUNT; + const uint32_t vertexFormatStride = m_pRequiredVertexFormat->GetStride(); - for (int i = 0; i < MAX_VERTEX_COUNT; ++i) - { - if (containsPosition) - { - std::memcpy(¤tDataPtr[currentDataSize], &vertexDataBuffer[i].pos, sizeof(cd::Point)); - currentDataSize += sizeof(cd::Point); - } - - if (containsColor) - { - std::memcpy(¤tDataPtr[currentDataSize], &vertexDataBuffer[i].color, sizeof(cd::Color)); - currentDataSize += sizeof(cd::Color); - } - - if (containsUV) - { - std::memcpy(¤tDataPtr[currentDataSize], &vertexDataBuffer[i].uv, sizeof(cd::UV)); - currentDataSize += sizeof(cd::UV); - } - } - } - else if (m_emitterParticleType == engine::ParticleType::Ribbon) - { - - } - else if (m_emitterParticleType == engine::ParticleType::Track) - { + m_spriteParticleVertexBuffer.resize(vertexCount * vertexFormatStride); - } - else if (m_emitterParticleType == engine::ParticleType::Ring) - { + uint32_t currentDataSize = 0U; + auto currentDataPtr = m_spriteParticleVertexBuffer.data(); - } - else if (m_emitterParticleType == engine::ParticleType::Model) + std::vector vertexDataBuffer; + vertexDataBuffer.resize(MAX_VERTEX_COUNT); + // pos color uv + // only a picture now + for (int i = 0; i < MAX_VERTEX_COUNT; i += meshVertexCount) { - + vertexDataBuffer[i] = { cd::Vec3f(-1.0f,-1.0f,0.0f),cd::Vec4f(1.0f,1.0f,1.0f,1.0f),cd::Vec2f(1.0f,1.0f) }; + vertexDataBuffer[i + 1] = { cd::Vec3f(1.0f,-1.0f,0.0f),cd::Vec4f(1.0f,1.0f,1.0f,1.0f),cd::Vec2f(0.0f,1.0f) }; + vertexDataBuffer[i + 2] = { cd::Vec3f(1.0f,1.0f,0.0f),cd::Vec4f(1.0f,1.0f,1.0f,1.0f),cd::Vec2f(0.0f,0.0f) }; + vertexDataBuffer[i + 3] = { cd::Vec3f(-1.0f,1.0f,0.0f),cd::Vec4f(1.0f,1.0f,1.0f,1.0f),cd::Vec2f(1.0f,0.0f) }; } -} -void ParticleEmitterComponent::PaddingIndexBuffer() -{ - m_particleIndexBuffer.clear(); - if (m_emitterParticleType == engine::ParticleType::Sprite) + for (int i = 0; i < MAX_VERTEX_COUNT; ++i) { - constexpr int meshVertexCount = Particle::GetMeshVertexCount(); - const bool useU16Index = meshVertexCount <= static_cast(std::numeric_limits::max()) + 1U; - const uint32_t indexTypeSize = useU16Index ? sizeof(uint16_t) : sizeof(uint32_t); - const int MAX_VERTEX_COUNT = m_particlePool.GetParticleMaxCount() * meshVertexCount; - int indexCountForOneSprite = 6; - const uint32_t indicesCount = MAX_VERTEX_COUNT / meshVertexCount * indexCountForOneSprite; - m_particleIndexBuffer.resize(indicesCount * indexTypeSize); - /// - /* size_t indexTypeSize = sizeof(uint16_t); - m_particleIndexBuffer.resize(m_particleSystem.GetMaxCount() / 4 * 6 * indexTypeSize);*/ - uint32_t currentDataSize = 0U; - auto currentDataPtr = m_particleIndexBuffer.data(); + if (containsPosition) + { + std::memcpy(¤tDataPtr[currentDataSize], &vertexDataBuffer[i].pos, sizeof(cd::Point)); + currentDataSize += sizeof(cd::Point); + } - std::vector indexes; - for (uint16_t i = 0; i < MAX_VERTEX_COUNT; i += meshVertexCount) + if (containsColor) { - 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); + std::memcpy(¤tDataPtr[currentDataSize], &vertexDataBuffer[i].color, sizeof(cd::Color)); + currentDataSize += sizeof(cd::Color); } - for (const auto& index : indexes) + if (containsUV) { - std::memcpy(¤tDataPtr[currentDataSize], &index, indexTypeSize); - currentDataSize += static_cast(indexTypeSize); + std::memcpy(¤tDataPtr[currentDataSize], &vertexDataBuffer[i].uv, sizeof(cd::UV)); + currentDataSize += sizeof(cd::UV); } } - else if (m_emitterParticleType == engine::ParticleType::Ribbon) - { - - } - else if (m_emitterParticleType == engine::ParticleType::Track) - { +} - } - else if (m_emitterParticleType == engine::ParticleType::Ring) +void ParticleEmitterComponent::PaddingSpriteIndexBuffer() +{ + constexpr int meshVertexCount = Particle::GetMeshVertexCount(); + const bool useU16Index = meshVertexCount <= static_cast(std::numeric_limits::max()) + 1U; + const uint32_t indexTypeSize = useU16Index ? sizeof(uint16_t) : sizeof(uint32_t); + const int MAX_VERTEX_COUNT = m_particlePool.GetParticleMaxCount() * meshVertexCount; + int indexCountForOneSprite = 6; + const uint32_t indicesCount = MAX_VERTEX_COUNT / meshVertexCount * indexCountForOneSprite; + m_spriteParticleIndexBuffer.resize(indicesCount * indexTypeSize); + /// +/* size_t indexTypeSize = sizeof(uint16_t); + m_particleIndexBuffer.resize(m_particleSystem.GetMaxCount() / 4 * 6 * indexTypeSize);*/ + uint32_t currentDataSize = 0U; + auto currentDataPtr = m_spriteParticleIndexBuffer.data(); + + std::vector indexes; + for (uint16_t i = 0; i < MAX_VERTEX_COUNT; i += meshVertexCount) { - + 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); } - else if (m_emitterParticleType == engine::ParticleType::Model) - { + for (const auto& index : indexes) + { + std::memcpy(¤tDataPtr[currentDataSize], &index, indexTypeSize); + currentDataSize += static_cast(indexTypeSize); } } @@ -291,49 +253,4 @@ void ParticleEmitterComponent::RePaddingShapeBuffer() } } -const std::string& ParticleEmitterComponent::GetShaderProgramName() const -{ - return m_pParticleMaterialType->GetShaderSchema().GetShaderProgramName(); -} - -void ParticleEmitterComponent::ActivateShaderFeature(ShaderFeature feature) -{ - if (ShaderFeature::DEFAULT == feature) - { - return; - } - - // TODO : Should remove uber shader stuff from ParticleEmitterComponent. - if (const auto& optConflictFeatureSet = m_pParticleMaterialType->GetShaderSchema().GetConflictFeatureSet(feature); optConflictFeatureSet.has_value()) - { - for (const auto& conflictFeature : optConflictFeatureSet.value()) - { - m_shaderFeatures.erase(conflictFeature); - } - } - - m_shaderFeatures.insert(cd::MoveTemp(feature)); - m_isShaderFeatureDirty = true; -} - -void ParticleEmitterComponent::DeactivateShaderFeature(ShaderFeature feature) -{ - m_shaderFeatures.erase(feature); - - m_isShaderFeatureDirty = true; -} - -const std::string& ParticleEmitterComponent::GetFeaturesCombine() -{ - if (m_isShaderFeatureDirty == false) - { - return m_featureCombine; - } - - m_featureCombine = m_pParticleMaterialType->GetShaderSchema().GetFeaturesCombine(m_shaderFeatures); - m_isShaderFeatureDirty = false; - - return m_featureCombine; -} - } \ No newline at end of file diff --git a/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.h b/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.h index 51bc53c4..b2b7ccfd 100644 --- a/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.h +++ b/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.h @@ -56,9 +56,6 @@ class ParticleEmitterComponent final bool& GetInstanceState() { return m_useInstance; } void SetInstanceState(bool state) { m_useInstance = state; } - const engine::MaterialType* GetMaterialType() const { return m_pParticleMaterialType; } - void SetMaterialType(const engine::MaterialType* pMaterialType) { m_pParticleMaterialType = pMaterialType; } - ParticleRenderMode& GetRenderMode() { return m_renderMode; } void SetRenderMode(engine::ParticleRenderMode mode) { m_renderMode = mode; } @@ -87,11 +84,11 @@ class ParticleEmitterComponent final float& GetLifeTime() { return m_emitterLifeTime; } void SetEmitterLifeTime(float lifetime) { m_emitterLifeTime = lifetime; } - uint16_t& GetParticleVertexBufferHandle() { return m_particleVertexBufferHandle; } - uint16_t& GetParticleIndexBufferHandle() { return m_particleIndexBufferHandle; } + uint16_t& GetSpriteParticleVertexBufferHandle() { return m_spriteParticleVertexBufferHandle; } + uint16_t& GetSpriteParticleIndexBufferHandle() { return m_spriteParticleIndexBufferHandle; } - std::vector& GetVertexBuffer() { return m_particleVertexBuffer; } - std::vector& GetIndexBuffer() { return m_particleIndexBuffer; } + std::vector& GetSpriteVertexBuffer() { return m_spriteParticleVertexBuffer; } + std::vector& GetSpriteIndexBuffer() { return m_spriteParticleIndexBuffer; } uint16_t& GetEmitterShapeVertexBufferHandle() { return m_emitterShapeVertexBufferHandle; } uint16_t& GetEmitterShapeIndexBufferHandle() { return m_emitterShapeIndexBufferHandle; } @@ -107,26 +104,17 @@ class ParticleEmitterComponent final void SetRequiredVertexFormat(const cd::VertexFormat* pVertexFormat) { m_pRequiredVertexFormat = pVertexFormat; } //void UpdateBuffer(); - void PaddingVertexBuffer(); - void PaddingIndexBuffer(); + void PaddingSpriteVertexBuffer(); + void PaddingSpriteIndexBuffer(); void BuildParticleShape(); void RePaddingShapeBuffer(); - // Uber shader data. - const std::string& GetShaderProgramName() const; - void ActivateShaderFeature(ShaderFeature feature); - void DeactivateShaderFeature(ShaderFeature feature); - void SetShaderFeatures(std::set options) { m_shaderFeatures = cd::MoveTemp(m_shaderFeatures); } - std::set& GetShaderFeatures() { return m_shaderFeatures; } - const std::set& GetShaderFeatures() const { return m_shaderFeatures; } - const std::string& GetFeaturesCombine(); - private: //ParticleSystem m_particleSystem; ParticlePool m_particlePool; - engine::ParticleType m_emitterParticleType; + engine::ParticleType m_emitterParticleType = engine::ParticleType::Sprite; //emitter data int m_spawnCount = 75; @@ -144,12 +132,6 @@ class ParticleEmitterComponent final //instancing bool m_useInstance = false; - //Uber shader - const engine::MaterialType* m_pParticleMaterialType = nullptr; - bool m_isShaderFeatureDirty = false; - std::set m_shaderFeatures; - std::string m_featureCombine; - //render mode mesh/billboard/ribbon ParticleRenderMode m_renderMode = ParticleRenderMode::Mesh; const cd::Mesh* m_pMeshData = nullptr; @@ -161,11 +143,13 @@ class ParticleEmitterComponent final cd::Vec4f color; cd::UV uv; }; + + //Sprite const cd::VertexFormat* m_pRequiredVertexFormat = nullptr; - std::vector m_particleVertexBuffer; - std::vector m_particleIndexBuffer; - uint16_t m_particleVertexBufferHandle = UINT16_MAX; - uint16_t m_particleIndexBufferHandle = UINT16_MAX; + std::vector m_spriteParticleVertexBuffer; + std::vector m_spriteParticleIndexBuffer; + uint16_t m_spriteParticleVertexBufferHandle = UINT16_MAX; + uint16_t m_spriteParticleIndexBufferHandle = UINT16_MAX; //emitter shape vertex/index ParticleEmitterShape m_emitterShape = ParticleEmitterShape::Box; diff --git a/Engine/Source/Runtime/ECWorld/ParticleRibbonComponent.cpp b/Engine/Source/Runtime/ECWorld/ParticleRibbonComponent.cpp new file mode 100644 index 00000000..c8aeb704 --- /dev/null +++ b/Engine/Source/Runtime/ECWorld/ParticleRibbonComponent.cpp @@ -0,0 +1,105 @@ +#include "Log/Log.h" +#include "ParticleRibbonComponent.h" +#include "Rendering/Utility/VertexLayoutUtility.h" +#include "Utilities/MeshUtils.hpp" + +#include + +namespace engine +{ +void ParticleRibbonComponent::Build() +{ + PaddingRibbonVertexBuffer(); + PaddingRibbonIndexBuffer(); +} + +void ParticleRibbonComponent::PaddingRibbonVertexBuffer() +{ + //vertexbuffer + constexpr int meshVertexCount = Particle::GetMeshVertexCount(); + //75 is from particle's MaxCount,There only padding once. + const int MAX_VERTEX_COUNT = 75 * meshVertexCount; + size_t vertexCount = MAX_VERTEX_COUNT; + uint32_t csVertexCount = MAX_VERTEX_COUNT; + //prePos Vertex format/layout + cd::VertexFormat m_pRibbonPrePosVertexFormat; + m_pRibbonPrePosVertexFormat.AddVertexAttributeLayout(cd::VertexAttributeType::Position, cd::GetAttributeValueType(), cd::Point::Size); + m_pRibbonPrePosVertexFormat.AddVertexAttributeLayout(cd::VertexAttributeType::BoneWeight, cd::AttributeValueType::Float, 1U); + bgfx::VertexLayout prePosLayout; + VertexLayoutUtility::CreateVertexLayout(prePosLayout, m_pRibbonPrePosVertexFormat.GetVertexAttributeLayouts()); + //remain Vertex format/layout + cd::VertexFormat m_pRibbonRemainVertexFormat; + m_pRibbonRemainVertexFormat.AddVertexAttributeLayout(cd::VertexAttributeType::Color, cd::GetAttributeValueType(), cd::Color::Size); + m_pRibbonRemainVertexFormat.AddVertexAttributeLayout(cd::VertexAttributeType::UV, cd::GetAttributeValueType(), cd::UV::Size); + bgfx::VertexLayout color_UV_Layout; + VertexLayoutUtility::CreateVertexLayout(color_UV_Layout, m_pRibbonRemainVertexFormat.GetVertexAttributeLayouts()); + + const uint32_t remainVertexFormatStride = m_pRibbonRemainVertexFormat.GetStride(); + + m_ribbonParticleRemainVertexBuffer.resize(vertexCount * remainVertexFormatStride); + + uint32_t currentRemainDataSize = 0U; + auto currentRemainDataPtr = m_ribbonParticleRemainVertexBuffer.data(); + + std::vector vertexDataBuffer; + vertexDataBuffer.resize(MAX_VERTEX_COUNT); + // pos color uv + // only a picture now + for (int i = 0; i < MAX_VERTEX_COUNT; i += meshVertexCount) + { + vertexDataBuffer[i] = { cd::Vec3f(0.0f,1.0f,0.0f),cd::Vec4f(1.0f,1.0f,1.0f,1.0f),cd::Vec2f(0.5f,0.5f) }; + vertexDataBuffer[i + 1] = { cd::Vec3f(0.0f,-1.0f,0.0f),cd::Vec4f(1.0f,1.0f,1.0f,1.0f),cd::Vec2f(0.5f,0.5f) }; + } + + for (int i = 0; i < MAX_VERTEX_COUNT; ++i) + { + std::memcpy(¤tRemainDataPtr[currentRemainDataSize], &vertexDataBuffer[i].color, sizeof(cd::Color)); + currentRemainDataSize += sizeof(cd::Color); + std::memcpy(¤tRemainDataPtr[currentRemainDataSize], &vertexDataBuffer[i].uv, sizeof(cd::UV)); + currentRemainDataSize += sizeof(cd::UV); + } + m_ribbonParticlePrePosVertexBufferHandle = bgfx::createDynamicVertexBuffer(csVertexCount, prePosLayout, BGFX_BUFFER_COMPUTE_READ_WRITE).idx; + const bgfx::Memory* pRibbonParticleRemainVBRef = bgfx::makeRef(m_ribbonParticleRemainVertexBuffer.data(), static_cast(m_ribbonParticleRemainVertexBuffer.size())); + m_ribbonParticleRemainVertexBufferHandle = bgfx::createVertexBuffer(pRibbonParticleRemainVBRef, color_UV_Layout).idx; +} + +void ParticleRibbonComponent::PaddingRibbonIndexBuffer() +{ + constexpr int meshVertexCount = Particle::GetMeshVertexCount();; + const bool useU16Index = meshVertexCount <= static_cast(std::numeric_limits::max()) + 1U; + const uint32_t indexTypeSize = useU16Index ? sizeof(uint16_t) : sizeof(uint32_t); + //TODO: 75 is from particle's MaxCount There only padding once. + const int MAX_VERTEX_COUNT = (75 - 1) * meshVertexCount; + int indexCountForOneRibbon = 6; + const uint32_t indicesCount = MAX_VERTEX_COUNT / meshVertexCount * indexCountForOneRibbon; + m_ribbonParticleIndexBuffer.resize(indicesCount * indexTypeSize); + /// +/* size_t indexTypeSize = sizeof(uint16_t); + m_particleIndexBuffer.resize(m_particleSystem.GetMaxCount() / 4 * 6 * indexTyp + eSize);*/ + uint32_t currentDataSize = 0U; + auto currentDataPtr = m_ribbonParticleIndexBuffer.data(); + + std::vector indexes; + + for (uint16_t i = 0; i < MAX_VERTEX_COUNT; i += meshVertexCount) + { + uint16_t vertexIndex = static_cast(i); + indexes.push_back(vertexIndex); + indexes.push_back(vertexIndex + 1); + indexes.push_back(vertexIndex + 2); + + indexes.push_back(vertexIndex + 2); + indexes.push_back(vertexIndex + 1); + indexes.push_back(vertexIndex + 3); + } + + for (const auto& index : indexes) + { + std::memcpy(¤tDataPtr[currentDataSize], &index, indexTypeSize); + currentDataSize += static_cast(indexTypeSize); + } + m_ribbonParticleIndexBufferHandle = bgfx::createIndexBuffer(bgfx::makeRef(m_ribbonParticleIndexBuffer.data(), static_cast(m_ribbonParticleIndexBuffer.size())), 0U).idx; +} + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/ECWorld/ParticleRibbonComponent.h b/Engine/Source/Runtime/ECWorld/ParticleRibbonComponent.h new file mode 100644 index 00000000..18baa54b --- /dev/null +++ b/Engine/Source/Runtime/ECWorld/ParticleRibbonComponent.h @@ -0,0 +1,61 @@ +#include "Base/Template.h" +#include "Core/StringCrc.h" +#include "Math/Vector.hpp" +#include "Math/Transform.hpp" +#include "Material/ShaderSchema.h" +#include "Material/MaterialType.h" +#include "ParticleSystem/ParticlePool.h" +#include "Scene/Mesh.h" +#include "Scene/Types.h" +#include "Scene/VertexFormat.h" + +namespace engine +{ + +class ParticleRibbonComponent final +{ +public: + static constexpr StringCrc GetClassName() + { + constexpr StringCrc className("ParticleRibbonComponent"); + return className; + } + + ParticleRibbonComponent() = default; + ParticleRibbonComponent(const ParticleRibbonComponent&) = default; + ParticleRibbonComponent& operator=(const ParticleRibbonComponent&) = default; + ParticleRibbonComponent(ParticleRibbonComponent&&) = default; + ParticleRibbonComponent& operator=(ParticleRibbonComponent&&) = default; + ~ParticleRibbonComponent() = default; + + void PaddingRibbonVertexBuffer(); + void PaddingRibbonIndexBuffer(); + + void Build(); + + uint16_t& GetRibbonParticlePrePosVertexBufferHandle() { return m_ribbonParticlePrePosVertexBufferHandle; } + uint16_t& GetRibbonParticleRemainVertexBufferHandle() { return m_ribbonParticleRemainVertexBufferHandle; } + uint16_t& GetRibbonParticleIndexBufferHandle() { return m_ribbonParticleIndexBufferHandle; } + + std::vector& GetRibbonPrePosVertexBuffer() { return m_ribbonParticlePrePosVertexBuffer; } + std::vector& GetRibbonRemainVertexBuffer() { return m_ribbonParticleRemainVertexBuffer; } + std::vector& GetRibbonIndexBuffer() { return m_ribbonParticleIndexBuffer; } + +private: + //particle vertex/index + struct VertexData + { + cd::Vec3f pos; + cd::Vec4f color; + cd::UV uv; + }; + + std::vector m_ribbonParticlePrePosVertexBuffer; + std::vector m_ribbonParticleRemainVertexBuffer; + std::vector m_ribbonParticleIndexBuffer; + uint16_t m_ribbonParticlePrePosVertexBufferHandle = UINT16_MAX; + uint16_t m_ribbonParticleRemainVertexBufferHandle = UINT16_MAX; + uint16_t m_ribbonParticleIndexBufferHandle = 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 a376556b..013f89fa 100644 --- a/Engine/Source/Runtime/ECWorld/SceneWorld.cpp +++ b/Engine/Source/Runtime/ECWorld/SceneWorld.cpp @@ -38,6 +38,7 @@ SceneWorld::SceneWorld() m_pSkinMeshComponentStorage = m_pWorld->Register(); m_pSkeletonComponentStorage = m_pWorld->Register(); m_pParticleEmitterComponentStorage = m_pWorld->Register(); + m_pParticleRibbonComponentStorage = m_pWorld->Register(); m_pParticleForceFieldComponentStorage = 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 7438439e..5dd64340 100644 --- a/Engine/Source/Runtime/ECWorld/SceneWorld.h +++ b/Engine/Source/Runtime/ECWorld/SceneWorld.h @@ -43,6 +43,7 @@ class SceneWorld DEFINE_COMPONENT_STORAGE_WITH_APIS(Sky); DEFINE_COMPONENT_STORAGE_WITH_APIS(StaticMesh); DEFINE_COMPONENT_STORAGE_WITH_APIS(ParticleEmitter); + DEFINE_COMPONENT_STORAGE_WITH_APIS(ParticleRibbon); DEFINE_COMPONENT_STORAGE_WITH_APIS(ParticleForceField); DEFINE_COMPONENT_STORAGE_WITH_APIS(Terrain); DEFINE_COMPONENT_STORAGE_WITH_APIS(Transform); @@ -103,6 +104,7 @@ class SceneWorld DeleteSkyComponent(entity); DeleteStaticMeshComponent(entity); DeleteParticleEmitterComponent(entity); + DeleteParticleRibbonComponent(entity); DeleteParticleForceFieldComponent(entity); DeleteTerrainComponent(entity); DeleteTransformComponent(entity); diff --git a/Engine/Source/Runtime/ParticleSystem/ParticlePool.h b/Engine/Source/Runtime/ParticleSystem/ParticlePool.h index 54bc1657..8079a220 100644 --- a/Engine/Source/Runtime/ParticleSystem/ParticlePool.h +++ b/Engine/Source/Runtime/ParticleSystem/ParticlePool.h @@ -23,7 +23,7 @@ class ParticlePool final int AllocateParticleIndex(); Particle& GetParticle(int index) { return m_particles[index]; } - int GetParticleCount() { return m_currentActiveCount; } + int GetParticleActiveCount() { return m_currentActiveCount; } int& GetParticleMaxCount() { return m_maxParticleCount; } void SetParticleMaxCount(int count) { m_maxParticleCount = count; } diff --git a/Engine/Source/Runtime/Rendering/ParticleRenderer.cpp b/Engine/Source/Runtime/Rendering/ParticleRenderer.cpp index 3295ad78..115e0cde 100644 --- a/Engine/Source/Runtime/Rendering/ParticleRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/ParticleRenderer.cpp @@ -7,6 +7,7 @@ #include "Log/Log.h" #include "Rendering/RenderContext.h" #include "Rendering/Resources/ShaderResource.h" +#include "../UniformDefines/U_Particle.sh" namespace engine { @@ -18,6 +19,8 @@ constexpr const char* particlePos = "u_particlePos"; constexpr const char* particleScale = "u_particleScale"; constexpr const char* shapeRange = "u_shapeRange"; constexpr const char* particleColor = "u_particleColor"; +constexpr const char* ribbonCount = "u_ribbonCount"; +constexpr const char* ribbonMaxPos = "u_ribbonMaxPos"; uint64_t state_tristrip = 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; @@ -25,22 +28,39 @@ BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA uint64_t state_lines = 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; +//Sprite Particle in EditorApp.cpp +constexpr const char* RibbonParticleCsProgram = "RibbonParticleCsProgram"; +constexpr const char* RibbonParticleProgram = "RibbonParticleProgram"; +constexpr const char* ParticleEmitterShapeProgram = "ParticleEmitterShapeProgram"; +constexpr const char* WO_BillboardParticleProgram = "WO_BillboardParticleProgram"; + +constexpr StringCrc RibbonParticleProgramCsCrc = StringCrc{ RibbonParticleCsProgram }; +constexpr StringCrc RibbonParticleProgramCrc = StringCrc{ RibbonParticleProgram }; + +constexpr StringCrc ParticleEmitterShapeProgramCrc = StringCrc{ ParticleEmitterShapeProgram }; +constexpr StringCrc WO_BillboardParticleProgramCrc = StringCrc{ WO_BillboardParticleProgram }; } void ParticleRenderer::Init() { - // TODO : ParticleRenderer should use material to manage ShaderResource instead of Renderer::AddShaderResource. - AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("ParticleProgram", "vs_particle", "fs_particle")); - AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("WO_BillboardParticleProgram", "vs_wo_billboardparticle", "fs_wo_billboardparticle")); - AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("ParticleEmitterShapeProgram", "vs_particleEmitterShape", "fs_particleEmitterShape")); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram(RibbonParticleCsProgram, "cs_particleRibbon", ShaderProgramType::Compute)); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram(RibbonParticleProgram, "vs_particleRibbon", "fs_particleRibbon")); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram(ParticleEmitterShapeProgram, "vs_particleEmitterShape", "fs_particleEmitterShape")); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram(WO_BillboardParticleProgram, "vs_wo_billboardparticle", "fs_wo_billboardparticle")); constexpr const char* particleTexture = "Textures/textures/Particle.png"; - m_particleTextureHandle = GetRenderContext()->CreateTexture(particleTexture); + constexpr const char* ribbonTexture = "Textures/textures/Particle.png"; + m_particleSpriteTextureHandle = GetRenderContext()->CreateTexture(particleTexture); + m_particleRibbonTextureHandle = GetRenderContext()->CreateTexture(ribbonTexture); + GetRenderContext()->CreateUniform("s_texColor", bgfx::UniformType::Sampler); + GetRenderContext()->CreateUniform("r_texColor", bgfx::UniformType::Sampler); GetRenderContext()->CreateUniform(particlePos, bgfx::UniformType::Vec4, 1); GetRenderContext()->CreateUniform(particleScale, bgfx::UniformType::Vec4, 1); GetRenderContext()->CreateUniform(shapeRange, bgfx::UniformType::Vec4, 1); GetRenderContext()->CreateUniform(particleColor, bgfx::UniformType::Vec4, 1); + GetRenderContext()->CreateUniform(ribbonCount, bgfx::UniformType::Vec4, 1); + GetRenderContext()->CreateUniform(ribbonMaxPos, bgfx::UniformType::Vec4, 300); bgfx::setViewName(GetViewID(), "ParticleRenderer"); } @@ -76,7 +96,16 @@ void ParticleRenderer::Render(float deltaTime) const cd::Transform& particleTransform = m_pCurrentSceneWorld->GetTransformComponent(entity)->GetTransform(); const cd::Quaternion& particleRotation = m_pCurrentSceneWorld->GetTransformComponent(entity)->GetTransform().GetRotation(); ParticleEmitterComponent* pEmitterComponent = m_pCurrentSceneWorld->GetParticleEmitterComponent(entity); - + ParticleRibbonComponent* pRibbonEmitterComponet = m_pCurrentSceneWorld->GetParticleRibbonComponent(entity); + MaterialComponent* pParticleMaterialComponet = m_pCurrentSceneWorld->GetMaterialComponent(entity); + //NOTE: This ShaderResource Not Used Just For Judge + const ShaderResource* pShaderResource = pParticleMaterialComponet->GetShaderResource(); + if (ResourceStatus::Ready != pShaderResource->GetStatus() && + ResourceStatus::Optimized != pShaderResource->GetStatus()) + { + continue; + } + const cd::Transform& pMainCameraTransform = m_pCurrentSceneWorld->GetTransformComponent(pMainCameraEntity)->GetTransform(); //const cd::Quaternion& cameraRotation = pMainCameraTransform.GetRotation(); //Not include particle attribute @@ -97,22 +126,8 @@ void ParticleRenderer::Render(float deltaTime) if (particleIndex != -1) { Particle& particle = pEmitterComponent->GetParticlePool().GetParticle(particleIndex); - if (pEmitterComponent->GetRandomPosState()) - { - particle.SetPos(particleTransform.GetTranslation()+ pEmitterComponent->GetRandormPos()); - } - else - { - particle.SetPos(particleTransform.GetTranslation()); - } - if (pEmitterComponent->GetRandomVelocityState()) - { - particle.SetSpeed(pEmitterComponent->GetEmitterVelocity()+ randomVelocity); - } - else - { - particle.SetSpeed(pEmitterComponent->GetEmitterVelocity()); - } + SetRandomPosState(particle, particleTransform.GetTranslation(), randomPos, pEmitterComponent->GetRandomPosState()); + SetRandomVelocityState(particle, pEmitterComponent->GetEmitterVelocity(), randomVelocity, pEmitterComponent->GetRandomVelocityState()); particle.SetRotationForceField(m_forcefieldRotationFoce); particle.SetRotationForceFieldRange(m_forcefieldRange); particle.SetAcceleration(pEmitterComponent->GetEmitterAcceleration()); @@ -157,26 +172,26 @@ void ParticleRenderer::Render(float deltaTime) constexpr StringCrc ParticleScaleCrc(particleScale); bgfx::setUniform(GetRenderContext()->GetUniform(ParticleScaleCrc), &particleTransform.GetScale(), 1); - constexpr StringCrc ParticleSampler("s_texColor"); - bgfx::setTexture(0, GetRenderContext()->GetUniform(ParticleSampler), m_particleTextureHandle); - bgfx::setVertexBuffer(0, bgfx::VertexBufferHandle{ pEmitterComponent->GetParticleVertexBufferHandle() }); - bgfx::setIndexBuffer(bgfx::IndexBufferHandle{ pEmitterComponent->GetParticleIndexBufferHandle() }); - - - bgfx::setInstanceDataBuffer(&idb); - - bgfx::setState(state_tristrip); - - if (pEmitterComponent->GetRenderMode() == engine::ParticleRenderMode::Mesh) + if (pEmitterComponent->GetEmitterParticleType() == engine::ParticleType::Sprite) { - constexpr StringCrc programHandleIndex{ "ParticleProgram" }; - GetRenderContext()->Submit(GetViewID(), programHandleIndex); + constexpr StringCrc ParticleSampler("s_texColor"); + bgfx::setTexture(0, GetRenderContext()->GetUniform(ParticleSampler), m_particleSpriteTextureHandle); + bgfx::setVertexBuffer(0, bgfx::VertexBufferHandle{ pEmitterComponent->GetSpriteParticleVertexBufferHandle() }); + bgfx::setIndexBuffer(bgfx::IndexBufferHandle{ pEmitterComponent->GetSpriteParticleIndexBufferHandle() }); } - else if (pEmitterComponent->GetRenderMode() == engine::ParticleRenderMode::Billboard) + else if (pEmitterComponent->GetEmitterParticleType() == engine::ParticleType::Ribbon) { - constexpr StringCrc programHandleIndex{ "WO_BillboardParticleProgram" }; - GetRenderContext()->Submit(GetViewID(), programHandleIndex); + constexpr StringCrc ribbonParticleSampler("r_texColor"); + bgfx::setTexture(1, GetRenderContext()->GetUniform(ribbonParticleSampler), m_particleRibbonTextureHandle); + bgfx::setVertexBuffer(0, bgfx::DynamicVertexBufferHandle{ pRibbonEmitterComponet->GetRibbonParticlePrePosVertexBufferHandle() }); + bgfx::setVertexBuffer(1, bgfx::VertexBufferHandle{ pRibbonEmitterComponet->GetRibbonParticleRemainVertexBufferHandle() }); + bgfx::setIndexBuffer(bgfx::IndexBufferHandle{ pRibbonEmitterComponet->GetRibbonParticleIndexBufferHandle() }); } + + bgfx::setState(state_tristrip); + bgfx::setInstanceDataBuffer(&idb); + + SetRenderMode(pEmitterComponent->GetRenderMode(), pEmitterComponent->GetEmitterParticleType(), pParticleMaterialComponet); } else { @@ -205,43 +220,115 @@ void ParticleRenderer::Render(float deltaTime) pitch, yaw, roll, pEmitterComponent->GetParticlePool().GetParticle(ii).GetPos().x(), pEmitterComponent->GetParticlePool().GetParticle(ii).GetPos().y(), pEmitterComponent->GetParticlePool().GetParticle(ii).GetPos().z()); } - bgfx::setTransform(mtx); - - constexpr StringCrc ParticleSampler("s_texColor"); - bgfx::setTexture(0, GetRenderContext()->GetUniform(ParticleSampler), m_particleTextureHandle); - bgfx::setVertexBuffer(0, bgfx::VertexBufferHandle{ pEmitterComponent->GetParticleVertexBufferHandle() }); - bgfx::setIndexBuffer(bgfx::IndexBufferHandle{ pEmitterComponent->GetParticleIndexBufferHandle() }); - bgfx::setState(state_tristrip); - - if (pEmitterComponent->GetRenderMode() == engine::ParticleRenderMode::Mesh) + if (pEmitterComponent->GetEmitterParticleType() == engine::ParticleType::Sprite) { - constexpr StringCrc programHandleIndex{ "ParticleProgram" }; - GetRenderContext()->Submit(GetViewID(), programHandleIndex); + constexpr StringCrc spriteParticleSampler("s_texColor"); + bgfx::setTexture(0, GetRenderContext()->GetUniform(spriteParticleSampler), m_particleSpriteTextureHandle); + bgfx::setVertexBuffer(0, bgfx::VertexBufferHandle{ pEmitterComponent->GetSpriteParticleVertexBufferHandle() }); + bgfx::setIndexBuffer(bgfx::IndexBufferHandle{ pEmitterComponent->GetSpriteParticleIndexBufferHandle() }); } - else if (pEmitterComponent->GetRenderMode() == engine::ParticleRenderMode::Billboard) + else if (pEmitterComponent->GetEmitterParticleType() == engine::ParticleType::Ribbon) { - constexpr StringCrc programHandleIndex{ "WO_BillboardParticleProgram" }; - GetRenderContext()->Submit(GetViewID(), programHandleIndex); + bgfx::setBuffer(PT_RIBBON_VERTEX_STAGE, bgfx::DynamicVertexBufferHandle{ pRibbonEmitterComponet->GetRibbonParticlePrePosVertexBufferHandle() }, bgfx::Access::ReadWrite); + + //ribbonCount Uinform + constexpr StringCrc ribbontCounts(ribbonCount); + cd::Vec4f allRibbonCount{ static_cast(pEmitterComponent->GetParticlePool().GetParticleMaxCount()* Particle::GetMeshVertexCount()), + pEmitterComponent->GetParticlePool().GetParticleMaxCount(), + 0, + 0}; + GetRenderContext()->FillUniform(ribbontCounts, &allRibbonCount, 1); + + //ribbonListUniform + cd::Vec4f ribbonPosList[300]{}; + for (int i = 0; i < 300; i++) + { + if (i >= pEmitterComponent->GetParticlePool().GetParticleMaxCount()) + { + ribbonPosList[i] = cd::Vec4f(0.0f,0.0f,0.0f,0.0f); + } + else + { + ribbonPosList[i] =cd::Vec4f(pEmitterComponent->GetParticlePool().GetParticle(i).GetPos().x(), + pEmitterComponent->GetParticlePool().GetParticle(i).GetPos().y(), + pEmitterComponent->GetParticlePool().GetParticle(i).GetPos().z() + , 0.0f); + } + } + constexpr StringCrc maxPosList(ribbonMaxPos); + GetRenderContext()->FillUniform(maxPosList, &ribbonPosList, 300); + GetRenderContext()->Dispatch(GetViewID(), RibbonParticleProgramCsCrc, 1U, 1U, 1U); + //pEmitterComponent->UpdateRibbonPosBuffer(); + constexpr StringCrc ribbonParticleSampler("r_texColor"); + bgfx::setTexture(1, GetRenderContext()->GetUniform(ribbonParticleSampler), m_particleRibbonTextureHandle); + bgfx::setVertexBuffer(0, bgfx::DynamicVertexBufferHandle{ pRibbonEmitterComponet->GetRibbonParticlePrePosVertexBufferHandle() }); + bgfx::setVertexBuffer(1, bgfx::VertexBufferHandle{ pRibbonEmitterComponet->GetRibbonParticleRemainVertexBufferHandle() }); + bgfx::setIndexBuffer(bgfx::IndexBufferHandle{ pRibbonEmitterComponet->GetRibbonParticleIndexBufferHandle() }); } + SetRenderMode(pEmitterComponent->GetRenderMode(), pEmitterComponent->GetEmitterParticleType(),pParticleMaterialComponet); } } - //pEmitterComponent->RePaddingShapeBuffer(); - //const bgfx::Memory* pParticleVertexBuffer = bgfx::makeRef(pEmitterComponent->GetEmitterShapeVertexBuffer().data(), static_cast(pEmitterComponent->GetEmitterShapeVertexBuffer().size())); - //const bgfx::Memory* pParticleIndexBuffer = bgfx::makeRef(pEmitterComponent->GetEmitterShapeIndexBuffer().data(), static_cast(pEmitterComponent->GetEmitterShapeIndexBuffer().size())); - //bgfx::update(bgfx::DynamicVertexBufferHandle{ pEmitterComponent->GetEmitterShapeVertexBufferHandle()}, 0, pParticleVertexBuffer); - //bgfx::update(bgfx::DynamicIndexBufferHandle{pEmitterComponent->GetEmitterShapeIndexBufferHandle()}, 0, pParticleIndexBuffer); constexpr StringCrc emitShapeRangeCrc(shapeRange); bgfx::setUniform(GetRenderContext()->GetUniform(emitShapeRangeCrc), &pEmitterComponent->GetEmitterShapeRange(), 1); bgfx::setTransform(m_pCurrentSceneWorld->GetTransformComponent(entity)->GetWorldMatrix().begin()); - bgfx::setVertexBuffer(1, bgfx::VertexBufferHandle{ pEmitterComponent->GetEmitterShapeVertexBufferHandle() }); + bgfx::setVertexBuffer(0, bgfx::VertexBufferHandle{ pEmitterComponent->GetEmitterShapeVertexBufferHandle() }); bgfx::setIndexBuffer(bgfx::IndexBufferHandle{ pEmitterComponent->GetEmitterShapeIndexBufferHandle() }); bgfx::setState(state_lines); - constexpr StringCrc programHandleIndex{ "ParticleEmitterShapeProgram" }; - GetRenderContext()->Submit(GetViewID(), programHandleIndex); + GetRenderContext()->Submit(GetViewID(), ParticleEmitterShapeProgramCrc); + } +} + +void ParticleRenderer::SetRenderMode(engine::ParticleRenderMode& rendermode, engine::ParticleType type, engine::MaterialComponent* shaderFeature_MaterialCompoent) +{ + if (rendermode == engine::ParticleRenderMode::Mesh) + { + if (type == engine::ParticleType::Sprite) + { + const ShaderResource* pShaderResource = shaderFeature_MaterialCompoent->GetShaderResource(); + GetRenderContext()->Submit(GetViewID(), pShaderResource->GetHandle()); + } + else if (type == engine::ParticleType::Ribbon) + { + GetRenderContext()->Submit(GetViewID(), RibbonParticleProgramCrc); + } + } + else if (rendermode == engine::ParticleRenderMode::Billboard) + { + if (type == engine::ParticleType::Sprite) + { + GetRenderContext()->Submit(GetViewID(), WO_BillboardParticleProgramCrc); + } + else if (type == engine::ParticleType::Ribbon) + { + //GetRenderContext()->Submit(GetViewID(), WO_BillboardParticleProgram); + } + } +} + +void ParticleRenderer::SetRandomPosState(engine::Particle& particle, cd::Vec3f value, cd::Vec3f randomvalue, bool state) +{ + if (state) + { + particle.SetPos(value + randomvalue); + } + else + { + particle.SetPos(value); + } +} +void ParticleRenderer::SetRandomVelocityState(engine::Particle& particle, cd::Vec3f value, cd::Vec3f randomvalue, bool state) +{ + if (state) + { + particle.SetSpeed(value + randomvalue); + } + else + { + particle.SetSpeed(value); } } diff --git a/Engine/Source/Runtime/Rendering/ParticleRenderer.h b/Engine/Source/Runtime/Rendering/ParticleRenderer.h index 4ce854d1..465c551f 100644 --- a/Engine/Source/Runtime/Rendering/ParticleRenderer.h +++ b/Engine/Source/Runtime/Rendering/ParticleRenderer.h @@ -7,6 +7,7 @@ #include "ECWorld/TransformComponent.h" #include "RenderContext.h" #include "Rendering/Utility/VertexLayoutUtility.h" + namespace engine { @@ -25,9 +26,14 @@ class ParticleRenderer final : public Renderer float getRandomValue(float min, float max) { return min + static_cast(rand()) / (RAND_MAX / (max - min)); } void SetForceFieldRotationForce(ParticleForceFieldComponent* forcefield) { m_forcefieldRotationFoce = forcefield->GetRotationForce(); } void SetForceFieldRange(ParticleForceFieldComponent* forcefield ,cd::Vec3f scale) { m_forcefieldRange = forcefield->GetForceFieldRange()*scale; } + + void SetRenderMode(engine::ParticleRenderMode& rendermode, engine::ParticleType type, engine::MaterialComponent* materialcomponent); + void SetRandomPosState(engine::Particle& particle, cd::Vec3f value, cd::Vec3f randomvalue, bool state); + void SetRandomVelocityState(engine::Particle& particle, cd::Vec3f value, cd::Vec3f randomvalue, bool state); private: SceneWorld* m_pCurrentSceneWorld = nullptr; - bgfx::TextureHandle m_particleTextureHandle; + bgfx::TextureHandle m_particleSpriteTextureHandle; + bgfx::TextureHandle m_particleRibbonTextureHandle; ParticleType m_currentType = ParticleType::Sprite; bool m_forcefieldRotationFoce = false; diff --git a/Engine/Source/ThirdParty/AssetPipeline b/Engine/Source/ThirdParty/AssetPipeline index 489ec0fb..08f18bee 160000 --- a/Engine/Source/ThirdParty/AssetPipeline +++ b/Engine/Source/ThirdParty/AssetPipeline @@ -1 +1 @@ -Subproject commit 489ec0fb9c11318c2ca8888bc234119d4d92a493 +Subproject commit 08f18beeaa7e344315632c8dcebcbea478529f43