diff --git a/Editor/resources/Shaders/deferred.shader b/Editor/resources/Shaders/deferred.shader index a501e086..cb0d755a 100644 --- a/Editor/resources/Shaders/deferred.shader +++ b/Editor/resources/Shaders/deferred.shader @@ -38,6 +38,7 @@ uniform sampler2D m_Albedo; uniform sampler2D m_Material; uniform sampler2D m_Normal; uniform sampler2D m_SSAO; +uniform sampler2D m_Emissive; // Lights const int MaxLight = 32; @@ -223,10 +224,21 @@ void main() // Convert from [0, 1] to [-1, 1]. vec3 albedo = texture(m_Albedo, UV).rgb; vec3 normal = texture(m_Normal, UV).rgb * 2.0 - 1.0; - float metallic = texture(m_Material, UV).r; - float roughness = texture(m_Material, UV).b; - float ao = texture(m_Material, UV).g; - float ssao = texture(m_SSAO, UV).r; + + vec4 materialSample = texture(m_Material, UV); + float metallic = materialSample.r; + float ao = materialSample.g; + float roughness = materialSample.b; + float unlit = materialSample.a; + float ssao = texture(m_SSAO, UV).r; + float emissive = texture(m_Emissive, UV).r; + + if (unlit > 0.1f) + { + FragColor = vec4(albedo * ssao * emissive, 1.0); + return; + } + vec3 N = normal; vec3 V = normalize(u_EyePosition - worldPos); vec3 R = reflect(-V, N); @@ -240,6 +252,7 @@ void main() vec3 fog = vec3(0.0); float shadow = 0.0f; + if (true) { vec3 L = normalize(u_DirectionalLight.Direction); diff --git a/Editor/resources/Shaders/gbuffer.shader b/Editor/resources/Shaders/gbuffer.shader index 6b0a7aa7..e2200c8e 100644 --- a/Editor/resources/Shaders/gbuffer.shader +++ b/Editor/resources/Shaders/gbuffer.shader @@ -40,6 +40,7 @@ layout(location = 0) out vec4 gAlbedo; layout(location = 1) out vec4 gNormal; layout(location = 2) out vec4 gMaterial; layout(location = 3) out int gEntityID; +layout(location = 4) out float gEmissive; in vec3 FragPos; in vec2 UV; @@ -67,6 +68,7 @@ layout(std140, binding = 32) uniform u_MaterialUniform int u_HasNormal; // 56 byte int u_HasDisplacement; // 60 byte int u_Unlit; + float u_Emissive; }; void main() @@ -77,10 +79,10 @@ void main() normal = texture(m_Normal, UV).rgb; normal = normal * 2.0 - 1.0; normal = TBN * normalize(normal); - gNormal = vec4(normal / 2.0 + 0.5, 1.0); + gNormal = vec4(normal / 2.0 + 0.5, 1.0f); // Albedo - gAlbedo = vec4(m_AlbedoColor, 1.0); + gAlbedo = vec4(m_AlbedoColor, 1.0f); if (u_HasAlbedo == 1) { vec4 albedoSample = texture(m_Albedo, UV); @@ -106,10 +108,12 @@ void main() if (u_HasRoughness == 1) finalRoughness = texture(m_Roughness, UV).r; - gMaterial = vec4(0, 0, 0, 1); + gMaterial = vec4(0, 0, 0, u_Unlit); gMaterial.r = finalMetalness; gMaterial.g = finalAO; gMaterial.b = finalRoughness; gEntityID = int(u_EntityID); + + gEmissive = u_Emissive; } \ No newline at end of file diff --git a/Editor/resources/Shaders/gbuffer_skinned.shader b/Editor/resources/Shaders/gbuffer_skinned.shader index 4712d27d..8e5bf133 100644 --- a/Editor/resources/Shaders/gbuffer_skinned.shader +++ b/Editor/resources/Shaders/gbuffer_skinned.shader @@ -65,6 +65,7 @@ layout(location = 0) out vec4 gAlbedo; layout(location = 1) out vec4 gNormal; layout(location = 2) out vec4 gMaterial; layout(location = 3) out int gEntityID; +layout(location = 4) out float gEmissive; in vec3 FragPos; in vec2 UV; @@ -92,6 +93,7 @@ layout(std140, binding = 32) uniform u_MaterialUniform int u_HasNormal; // 56 byte int u_HasDisplacement; // 60 byte int u_Unlit; + float u_Emissive; }; void main() @@ -102,10 +104,10 @@ void main() normal = texture(m_Normal, UV).rgb; normal = normal * 2.0 - 1.0; normal = TBN * normalize(normal); - gNormal = vec4(normal / 2.0 + 0.5, 1.0); + gNormal = vec4(normal / 2.0 + 0.5, 1.0f); // Albedo - gAlbedo = vec4(m_AlbedoColor, 1.0); + gAlbedo = vec4(m_AlbedoColor, 1.0f); if (u_HasAlbedo == 1) { vec4 albedoSample = texture(m_Albedo, UV); @@ -131,10 +133,11 @@ void main() if (u_HasRoughness == 1) finalRoughness = texture(m_Roughness, UV).r; - gMaterial = vec4(0, 0, 0, 1); + gMaterial = vec4(0, 0, 0, u_Unlit); gMaterial.r = finalMetalness; gMaterial.g = finalAO; gMaterial.b = finalRoughness; gEntityID = int(u_EntityID); + gEmissive = u_Emissive; } \ No newline at end of file diff --git a/Editor/src/ComponentsPanel/ParticleEmitterPanel.h b/Editor/src/ComponentsPanel/ParticleEmitterPanel.h index 04900ec9..3043dfb6 100644 --- a/Editor/src/ComponentsPanel/ParticleEmitterPanel.h +++ b/Editor/src/ComponentsPanel/ParticleEmitterPanel.h @@ -5,10 +5,15 @@ #include #include #include +#include "MaterialEditor.h" +#include +#include class ParticleEmitterPanel : ComponentPanel { public: + Scope _modelInspector; + ParticleEmitterPanel() {} void Draw(Nuake::Entity entity) override @@ -30,6 +35,50 @@ public: ImGui::TableNextColumn(); ComponentTableReset(component.ParticleColor, Nuake::Vector4(1, 1, 1, 1)); } + + ImGui::TableNextColumn(); + { + ImGui::Text("Particle Material"); + ImGui::TableNextColumn(); + + std::string label = "Empty"; + if (!component.ParticleMaterial->Path.empty()) + { + label = component.ParticleMaterial->Path; + } + + if (ImGui::Button(label.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0))) + { + + } + + if (ImGui::BeginDragDropTarget()) + { + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Material")) + { + char* file = (char*)payload->Data; + std::string fullPath = std::string(file, 256); + + fullPath = Nuake::FileSystem::AbsoluteToRelative(fullPath); + + Ref material = Nuake::ResourceLoader::LoadMaterial(fullPath); + component.ParticleMaterial = material; + } + ImGui::EndDragDropTarget(); + } + + //std::string childId = "materialEditorParticle"; + //ImGui::BeginChild(childId.c_str(), ImVec2(0, 0), false); + //{ + // MaterialEditor editor; + // editor.Draw(component.ParticleMaterial); + //} + //ImGui::EndChild(); + + ImGui::TableNextColumn(); + ComponentTableReset(component.ParticleColor, Nuake::Vector4(1, 1, 1, 1)); + } + ImGui::TableNextColumn(); { ImGui::Text("Amount"); @@ -40,6 +89,26 @@ public: ComponentTableReset(component.Amount, 10.0f); } ImGui::TableNextColumn(); + { + ImGui::Text("Particle Size"); + ImGui::TableNextColumn(); + + ImGuiHelper::DrawVec3("##particleSize", &component.ParticleScale); + + ImGui::TableNextColumn(); + ComponentTableReset(component.ParticleScale, Nuake::Vector3(0.1, 0.1, 0.1)); + } + ImGui::TableNextColumn(); + { + ImGui::Text("Global Space"); + ImGui::TableNextColumn(); + + ImGui::Checkbox("##globalSpace", &component.GlobalSpace); + + ImGui::TableNextColumn(); + ComponentTableReset(component.GlobalSpace, false); + } + ImGui::TableNextColumn(); { ImGui::Text("Rate"); ImGui::TableNextColumn(); diff --git a/Nuake/src/Core/String.cpp b/Nuake/src/Core/String.cpp index db6be8a3..90c183a1 100644 --- a/Nuake/src/Core/String.cpp +++ b/Nuake/src/Core/String.cpp @@ -15,11 +15,13 @@ namespace Nuake return false; } - bool String::EndsWith(const std::string& string, const std::string& end) + bool String::EndsWith(const std::string& string, const std::string_view& end) { if (string.length() >= end.length()) { - return (0 == string.compare(string.length() - end.length(), end.length(), end)); + bool result = string.ends_with(end); + + return result; } return false; diff --git a/Nuake/src/Core/String.h b/Nuake/src/Core/String.h index c3b55e17..8d06e3ef 100644 --- a/Nuake/src/Core/String.h +++ b/Nuake/src/Core/String.h @@ -12,7 +12,7 @@ namespace Nuake { public: static bool BeginsWith(const std::string& string, const std::string& begin); - static bool EndsWith(const std::string& string, const std::string& end); + static bool EndsWith(const std::string& string, const std::string_view& end); static bool IsDigit(const char& character); static std::string RemoveWhiteSpace(const std::string& string); static std::string Sanitize(const std::string& keyword); diff --git a/Nuake/src/Rendering/Platforms/OGLRendererAPI.cpp b/Nuake/src/Rendering/Platforms/OGLRendererAPI.cpp index cf04dae0..8044f1b1 100644 --- a/Nuake/src/Rendering/Platforms/OGLRendererAPI.cpp +++ b/Nuake/src/Rendering/Platforms/OGLRendererAPI.cpp @@ -119,6 +119,7 @@ namespace Nuake { case RendererEnum::STATIC_DRAW: return GL_STATIC_DRAW; case RendererEnum::DYNAMIC_DRAW: return GL_DYNAMIC_DRAW; case RendererEnum::STREAM_DRAW: return GL_STREAM_DRAW; + case RendererEnum::BLENDING: return GL_BLEND; } return 0; diff --git a/Nuake/src/Rendering/Platforms/RendererAPI.h b/Nuake/src/Rendering/Platforms/RendererAPI.h index ea27a392..ee74b12a 100644 --- a/Nuake/src/Rendering/Platforms/RendererAPI.h +++ b/Nuake/src/Rendering/Platforms/RendererAPI.h @@ -9,7 +9,7 @@ namespace Nuake { ELEMENT_ARRAY_BUFFER, TRIANGLES, LINES, DEPTH_ATTACHMENT, COLOR_ATTACHMENT0, COLOR_ATTACHMENT1, - DEPTH_TEST, FACE_CULL, + DEPTH_TEST, FACE_CULL, BLENDING, STATIC_DRAW, DYNAMIC_DRAW, STREAM_DRAW }; diff --git a/Nuake/src/Rendering/SceneRenderer.cpp b/Nuake/src/Rendering/SceneRenderer.cpp index 95422edf..997ec862 100644 --- a/Nuake/src/Rendering/SceneRenderer.cpp +++ b/Nuake/src/Rendering/SceneRenderer.cpp @@ -16,10 +16,11 @@ namespace Nuake const auto defaultResolution = Vector2(1920, 1080); mGBuffer = CreateScope(false, defaultResolution); mGBuffer->SetTexture(CreateRef(defaultResolution, GL_DEPTH_COMPONENT), GL_DEPTH_ATTACHMENT); - mGBuffer->SetTexture(CreateRef(defaultResolution, GL_RGB), GL_COLOR_ATTACHMENT0); - mGBuffer->SetTexture(CreateRef(defaultResolution, GL_RGB), GL_COLOR_ATTACHMENT1); - mGBuffer->SetTexture(CreateRef(defaultResolution, GL_RGB), GL_COLOR_ATTACHMENT2); + mGBuffer->SetTexture(CreateRef(defaultResolution, GL_RGB), GL_COLOR_ATTACHMENT0); // Albedo + mGBuffer->SetTexture(CreateRef(defaultResolution, GL_RGB), GL_COLOR_ATTACHMENT1); // + mGBuffer->SetTexture(CreateRef(defaultResolution, GL_RGBA), GL_COLOR_ATTACHMENT2); // Material + unlit mGBuffer->SetTexture(CreateRef(defaultResolution, GL_RED_INTEGER, GL_R32I, GL_INT), GL_COLOR_ATTACHMENT3); + mGBuffer->SetTexture(CreateRef(defaultResolution, GL_RED, GL_R16F, GL_FLOAT), GL_COLOR_ATTACHMENT4); // Emissive mShadingBuffer = CreateScope(true, defaultResolution); mShadingBuffer->SetTexture(CreateRef(defaultResolution, GL_RGB, GL_RGB16F, GL_FLOAT)); @@ -306,6 +307,8 @@ namespace Nuake mGBuffer->Bind(); mGBuffer->Clear(); { + RenderCommand::Disable(RendererEnum::BLENDING); + // Init RenderCommand::Enable(RendererEnum::FACE_CULL); Shader* gBufferShader = ShaderManager::GetShader("resources/Shaders/gbuffer.shader"); @@ -349,6 +352,7 @@ namespace Nuake Renderer::Flush(gBufferShader, false); RenderCommand::Disable(RendererEnum::FACE_CULL); + // Sprites auto spriteView = scene.m_Registry.view(); for (auto& e : spriteView) @@ -399,17 +403,27 @@ namespace Nuake particleTransform = glm::inverse(mView); // Translation - const Vector3& particleGlobalPosition = transform.GetGlobalPosition() + p.Position; + Vector3 particleGlobalPosition; + if (emitterComponent.GlobalSpace) + { + particleGlobalPosition = p.Position; + } + else + { + particleGlobalPosition = Vector3(initialTransform[3]) + p.Position; + } particleTransform[3] = Vector4(particleGlobalPosition, 1.0f); // Scale - particleTransform = glm::scale(particleTransform, transform.GetGlobalScale()); + particleTransform = glm::scale(particleTransform, emitterComponent.ParticleScale); Renderer::QuadMesh->GetMaterial()->data.u_HasAlbedo = 0; Renderer::QuadMesh->GetMaterial()->data.m_AlbedoColor = p.Color; Renderer::SubmitMesh(Renderer::QuadMesh, particleTransform, (uint32_t)e); } + Renderer::QuadMesh->SetMaterial(emitterComponent.ParticleMaterial); + Renderer::Flush(gBufferShader, false); Renderer::QuadMesh->GetMaterial()->data.m_AlbedoColor = oldColor; } @@ -446,6 +460,8 @@ namespace Nuake } } } + + RenderCommand::Enable(RendererEnum::BLENDING); } void SceneRenderer::ShadingPass(Scene& scene) @@ -494,11 +510,13 @@ namespace Nuake mGBuffer->GetTexture(GL_COLOR_ATTACHMENT0)->Bind(6); mGBuffer->GetTexture(GL_COLOR_ATTACHMENT1)->Bind(7); mGBuffer->GetTexture(GL_COLOR_ATTACHMENT2)->Bind(8); + mGBuffer->GetTexture(GL_COLOR_ATTACHMENT4)->Bind(10); shadingShader->SetUniform1i("m_Depth", 5); shadingShader->SetUniform1i("m_Albedo", 6); shadingShader->SetUniform1i("m_Normal", 7); shadingShader->SetUniform1i("m_Material", 8); + shadingShader->SetUniform1i("m_Emissive", 10); RenderCommand::Disable(RendererEnum::FACE_CULL); diff --git a/Nuake/src/Rendering/Textures/Material.h b/Nuake/src/Rendering/Textures/Material.h index bd6c73e6..94f295d9 100644 --- a/Nuake/src/Rendering/Textures/Material.h +++ b/Nuake/src/Rendering/Textures/Material.h @@ -26,6 +26,7 @@ namespace Nuake int u_HasNormal; int u_HasDisplacement; int u_Unlit; + float u_Emissive; }; class Material : ISerializable, public Resource @@ -50,7 +51,8 @@ namespace Nuake 0.5f, // u_AOValue 0, // u_HasNormal 0, // u_HasDisplacement - 0 + 0, // unlit + 1.0f // emissive }; } public: @@ -114,15 +116,47 @@ namespace Nuake json Serialize() override { BEGIN_SERIALIZE(); + + j["UUID"] = static_cast(ID); + j["HasAlbedo"] = this->HasAlbedo(); if (HasAlbedo()) { j["Albedo"] = this->m_Albedo->Serialize(); } + Vector3 AlbedoColor = data.m_AlbedoColor; + SERIALIZE_VEC3(AlbedoColor); + + SERIALIZE_VAL_LBL("Emissive", data.u_Emissive); + SERIALIZE_VAL_LBL("AOValue", data.u_AOValue); + SERIALIZE_VAL_LBL("MetalnessValue", data.u_MetalnessValue); + SERIALIZE_VAL_LBL("RoughnessValue", data.u_RoughnessValue); + SERIALIZE_VAL_LBL("Unlit", data.u_Unlit); + j["HasAO"] = this->HasAO(); + if (HasAO()) + { + j["AO"] = m_AO->Serialize(); + } + j["HasMetalness"] = this->HasMetalness(); + if(HasMetalness()) + { + j["Metalness"] = m_Metalness->Serialize(); + } + j["HasRoughness"] = this->HasRoughness(); + if (HasRoughness()) + { + j["Roughness"] = m_Roughness->Serialize(); + } + j["HasNormal"] = this->HasNormal(); + if (HasNormal()) + { + j["Normal"] = m_Normal->Serialize(); + } + j["HasDisplacement"] = this->HasDisplacement(); END_SERIALIZE(); @@ -130,6 +164,7 @@ namespace Nuake bool Deserialize(const json& j) override { + if (j.contains("Path")) { Path = FileSystem::RelativeToAbsolute(j["Path"]); @@ -149,6 +184,36 @@ namespace Nuake SetAlbedo(albedoTexture); } + if (j.contains("AlbedoColor")) + { + DESERIALIZE_VEC3(j["AlbedoColor"], data.m_AlbedoColor); + } + + if (j.contains("Emissive")) + { + data.u_Emissive = j["Emissive"]; + } + + if (j.contains("MetalnessValue")) + { + data.u_MetalnessValue = j["MetalnessValue"]; + } + + if (j.contains("RoughnessValue")) + { + data.u_RoughnessValue = j["RoughnessValue"]; + } + + if (j.contains("AOValue")) + { + data.u_AOValue = j["AOValue"]; + } + + if (j.contains("Unlit")) + { + data.u_Unlit = j["Unlit"]; + } + if (j.contains("Normal")) { const std::string absolutePath = FileSystem::RelativeToAbsolute(j["Normal"]["Path"]); diff --git a/Nuake/src/Resource/Serializable.h b/Nuake/src/Resource/Serializable.h index 5d243f59..423e25bb 100644 --- a/Nuake/src/Resource/Serializable.h +++ b/Nuake/src/Resource/Serializable.h @@ -8,16 +8,16 @@ using json = nlohmann::json; #define SERIALIZE_VAL(v) j[#v] = this->v; #define SERIALIZE_VEC2(v) \ - j[#v]["x"] = this->v.x; \ - j[#v]["y"] = this->v.y; + j[#v]["x"] = v.x; \ + j[#v]["y"] = v.y; #define SERIALIZE_VEC3(v) \ SERIALIZE_VEC2(v) \ - j[#v]["z"] = this->v.z; + j[#v]["z"] = v.z; #define SERIALIZE_VEC4(v) \ SERIALIZE_VEC3(v) \ - j[#v]["w"] = this->v.w; + j[#v]["w"] = v.w; #define DESERIALIZE_VAL(p) \ if(j.contains(#p)) \ diff --git a/Nuake/src/Scene/Components/ParticleEmitterComponent.cpp b/Nuake/src/Scene/Components/ParticleEmitterComponent.cpp index e89b1b9a..1a04f189 100644 --- a/Nuake/src/Scene/Components/ParticleEmitterComponent.cpp +++ b/Nuake/src/Scene/Components/ParticleEmitterComponent.cpp @@ -6,12 +6,17 @@ namespace Nuake { BEGIN_SERIALIZE(); SERIALIZE_VEC4(ParticleColor); + SERIALIZE_VEC3(ParticleScale); SERIALIZE_VAL(Amount); SERIALIZE_VAL(Life); SERIALIZE_VAL(Rate); SERIALIZE_VEC3(Gravity); SERIALIZE_VAL(GravityRandom); SERIALIZE_VAL(Radius); + SERIALIZE_VAL(GlobalSpace); + + SERIALIZE_OBJECT(ParticleMaterial); + END_SERIALIZE(); } @@ -25,6 +30,20 @@ namespace Nuake Rate = j["Rate"]; } DESERIALIZE_VEC3(j["Gravity"], Gravity); + if (j.contains("ParticleScale")) + { + DESERIALIZE_VEC3(j["ParticleScale"], ParticleScale); + } + if (j.contains("GlobalSpace")) + { + DESERIALIZE_VAL(GlobalSpace); + } + if (j.contains("ParticleMaterial")) + { + Ref newMaterial = CreateRef(); + newMaterial->Deserialize(j["ParticleMaterial"]); + ParticleMaterial = newMaterial; + } GravityRandom = j["GravityRandom"]; Radius = j["Radius"]; return true; diff --git a/Nuake/src/Scene/Components/ParticleEmitterComponent.h b/Nuake/src/Scene/Components/ParticleEmitterComponent.h index 1e9f3763..5b3e802e 100644 --- a/Nuake/src/Scene/Components/ParticleEmitterComponent.h +++ b/Nuake/src/Scene/Components/ParticleEmitterComponent.h @@ -14,10 +14,15 @@ namespace Nuake ParticleEmitterComponent() = default; ~ParticleEmitterComponent() = default; + Ref ParticleMaterial = CreateRef(); + Color ParticleColor; float Amount; float Life = 1.0f; float Rate = 0.0f; + Vector3 ParticleScale = Vector3(0.1, 0.1, 0.1); + + bool GlobalSpace = false; Vector3 Gravity; float GravityRandom; diff --git a/Nuake/src/Scene/Components/SpriteComponent.cpp b/Nuake/src/Scene/Components/SpriteComponent.cpp index bedb5b77..2f384db1 100644 --- a/Nuake/src/Scene/Components/SpriteComponent.cpp +++ b/Nuake/src/Scene/Components/SpriteComponent.cpp @@ -31,7 +31,7 @@ namespace Nuake SpriteMesh = CreateRef(); SpriteMesh->AddSurface(quadVertices, { 0, 1, 2, 3, 4, 5 }); - auto& material = MaterialManager::Get()->GetMaterial(FileSystem::Root + SpritePath); + auto material = MaterialManager::Get()->GetMaterial(FileSystem::Root + SpritePath); SpriteMesh->SetMaterial(material); return true; diff --git a/Nuake/src/Scene/Systems/ParticleEmitter.cpp b/Nuake/src/Scene/Systems/ParticleEmitter.cpp index 2fb47244..546cff31 100644 --- a/Nuake/src/Scene/Systems/ParticleEmitter.cpp +++ b/Nuake/src/Scene/Systems/ParticleEmitter.cpp @@ -13,6 +13,11 @@ namespace Nuake } + void ParticleEmitter::SetGlobalOrigin(const Vector3& origin) + { + GlobalOrigin = origin; + } + void ParticleEmitter::SpawnParticle() { const bool canSpawnParticle = Particles.size() < Amount; @@ -23,11 +28,16 @@ namespace Nuake if (Rate == 0.0f || RateTimer > Rate) { - const auto initialPosition = Vector3(m_Random(m_MT), m_Random(m_MT), m_Random(m_MT)); + auto initialPosition = Vector3(m_Random(m_MT), m_Random(m_MT), m_Random(m_MT)); const auto initialVelocity = Vector3(); const auto initialColor = ParticleColor; const float initialLife = Life; + if (IsGlobalSpace) + { + initialPosition = initialPosition + GlobalOrigin; + } + Particles.push_back({ initialPosition, initialVelocity, diff --git a/Nuake/src/Scene/Systems/ParticleEmitter.h b/Nuake/src/Scene/Systems/ParticleEmitter.h index f7d8609a..4e72253d 100644 --- a/Nuake/src/Scene/Systems/ParticleEmitter.h +++ b/Nuake/src/Scene/Systems/ParticleEmitter.h @@ -22,6 +22,9 @@ namespace Nuake float Rate = 0.0f; Color ParticleColor; + bool IsGlobalSpace = false; + Vector3 GlobalOrigin; + private: float RateTimer = 0.0f; std::mt19937 m_MT; @@ -33,6 +36,8 @@ namespace Nuake ParticleEmitter(); ~ParticleEmitter() = default; + void SetGlobalOrigin(const Vector3& origin); + void SpawnParticle(); void Update(Timestep ts); diff --git a/Nuake/src/Scene/Systems/ParticleSystem.cpp b/Nuake/src/Scene/Systems/ParticleSystem.cpp index a23a45e9..d27dc628 100644 --- a/Nuake/src/Scene/Systems/ParticleSystem.cpp +++ b/Nuake/src/Scene/Systems/ParticleSystem.cpp @@ -34,6 +34,8 @@ namespace Nuake emitter.SetRadius(emitterComponent.Radius); emitter.Life = emitterComponent.Life; emitter.Rate = emitterComponent.Rate; + emitter.IsGlobalSpace = emitterComponent.GlobalSpace; + emitter.GlobalOrigin = transformComponent.GetGlobalTransform()[3]; // Spawn particle if possible emitterComponent.Emitter.SpawnParticle();