diff --git a/Assets/Scenes/Scene2.shade b/Assets/Scenes/Scene2.shade index b4d7abbd..d284d4ea 100644 --- a/Assets/Scenes/Scene2.shade +++ b/Assets/Scenes/Scene2.shade @@ -172,5 +172,6 @@ Rotation Decay: 0.0199999996 Texture Asset ID: 63456868 Custom Update Shader Asset ID: 0 + Color Tint: {x: 1, y: 0, z: 0, w: 1} IsActive: true Scripts: ~ \ No newline at end of file diff --git a/Assets/Shaders/ParticleEmit_CS.glsl b/Assets/Shaders/ParticleEmit_CS.glsl index 45cea313..43ed335d 100644 --- a/Assets/Shaders/ParticleEmit_CS.glsl +++ b/Assets/Shaders/ParticleEmit_CS.glsl @@ -12,6 +12,7 @@ struct EmitterParameters float rotationSpeed; float rotationDecay; vec4 lifeAndSizeRange; // min life, max life, min size, max size + vec4 colorTint; float sizeDecay; uint textureIndex; float padding[2]; @@ -24,6 +25,7 @@ struct ParticleData vec4 velocity; vec4 acceleration; vec4 scaleAndDecay; + vec4 colorTint; float life; uint textureIndex; }; @@ -166,11 +168,14 @@ void main() float particleSize = map (rand(seed), 0.0f, 1.0f, emitterParams.data.lifeAndSizeRange.z, emitterParams.data.lifeAndSizeRange.w); - // Set size of particle + // Set size of and size decay of particle particle.scaleAndDecay.x = particleSize; particle.scaleAndDecay.y = particleSize; particle.scaleAndDecay.z = emitterParams.data.sizeDecay; particle.scaleAndDecay.w = emitterParams.data.sizeDecay; + + // Set particle color tint + particle.colorTint = emitterParams.data.colorTint; // Set the texture for the particle particle.textureIndex = emitterParams.data.textureIndex; diff --git a/Assets/Shaders/ParticleEmit_CS.shshaderb b/Assets/Shaders/ParticleEmit_CS.shshaderb index b003ba77..dea78edc 100644 Binary files a/Assets/Shaders/ParticleEmit_CS.shshaderb and b/Assets/Shaders/ParticleEmit_CS.shshaderb differ diff --git a/Assets/Shaders/ParticleUpdate_CS.glsl b/Assets/Shaders/ParticleUpdate_CS.glsl index 43d4893d..1f5384ec 100644 --- a/Assets/Shaders/ParticleUpdate_CS.glsl +++ b/Assets/Shaders/ParticleUpdate_CS.glsl @@ -17,6 +17,7 @@ struct ParticleData vec4 velocity; vec4 acceleration; vec4 scaleAndDecay; + vec4 colorTint; float life; uint textureIndex; }; diff --git a/Assets/Shaders/ParticleUpdate_CS.shshaderb b/Assets/Shaders/ParticleUpdate_CS.shshaderb index 63a79d5a..e7a3ec64 100644 Binary files a/Assets/Shaders/ParticleUpdate_CS.shshaderb and b/Assets/Shaders/ParticleUpdate_CS.shshaderb differ diff --git a/Assets/Shaders/Particle_FS.glsl b/Assets/Shaders/Particle_FS.glsl index 243baa2e..69bc224b 100644 --- a/Assets/Shaders/Particle_FS.glsl +++ b/Assets/Shaders/Particle_FS.glsl @@ -15,12 +15,13 @@ layout(location = 0) in struct layout(location = 1) flat in struct { uint textureIndex; + vec4 color; } InFlat; void main () { - fragColor = vec4 (texture(textures [nonuniformEXT(InFlat.textureIndex)], In.uv)); + fragColor = vec4 (texture(textures [nonuniformEXT(InFlat.textureIndex)], In.uv)) * InFlat.color; if (fragColor.a < 0.01f) discard; } diff --git a/Assets/Shaders/Particle_FS.shshaderb b/Assets/Shaders/Particle_FS.shshaderb index edd2dd6b..59049d0c 100644 Binary files a/Assets/Shaders/Particle_FS.shshaderb and b/Assets/Shaders/Particle_FS.shshaderb differ diff --git a/Assets/Shaders/Particle_VS.glsl b/Assets/Shaders/Particle_VS.glsl index 5004cea1..b5b6f13e 100644 --- a/Assets/Shaders/Particle_VS.glsl +++ b/Assets/Shaders/Particle_VS.glsl @@ -23,6 +23,7 @@ struct ParticleData vec4 velocity; vec4 acceleration; vec4 scaleAndDecay; + vec4 colorTint; float life; uint textureIndex; }; @@ -62,6 +63,7 @@ layout(location = 0) out struct layout(location = 1) out struct { uint textureIndex; // location = 1 + vec4 color; // location = 2 } OutFlat; vec2 CreateQuad (in uint vertexID) @@ -96,6 +98,7 @@ void main() particlePos = particle.position.xyz + (viewRight * particlePos.x * particleScaleData.x) + (viewUp * particlePos.y * particleScaleData.y); OutFlat.textureIndex = particle.textureIndex; + OutFlat.color = particle.colorTint; gl_Position = cameraData.vpMat * vec4(particlePos, 1.0f); } \ No newline at end of file diff --git a/Assets/Shaders/Particle_VS.shshaderb b/Assets/Shaders/Particle_VS.shshaderb index 0a9be96d..2ba7a729 100644 Binary files a/Assets/Shaders/Particle_VS.shshaderb and b/Assets/Shaders/Particle_VS.shshaderb differ diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 2edadbbc..421aec6d 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -883,6 +883,17 @@ namespace SHADE comp->SetRotationDecay(val); }); + SHEditorWidgets::ColorPicker("Color Tint", + [comp = component]() + { + return comp->GetColorTint(); + }, + [comp = component](SHVec4 const& val) + { + comp->SetColorTint(val); + }); + + SHEditorWidgets::DragInt("Texture Index", [comp = component]() { diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp index 5454cf31..fcdb20da 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp @@ -52,6 +52,18 @@ namespace SHADE } + void SHParticleEmitterComponent::SetAngularRanges(SHVec2 const& ranges) noexcept + { + cpuEmitterData.angularRangesAndOffsets.x = ranges.x; + cpuEmitterData.angularRangesAndOffsets.y = ranges.y; + } + + void SHParticleEmitterComponent::SetAngularOffsets(SHVec2 const& offsets) noexcept + { + cpuEmitterData.angularRangesAndOffsets.z = offsets.x; + cpuEmitterData.angularRangesAndOffsets.w = offsets.y; + } + void SHParticleEmitterComponent::SetMinSpeed(float speed) noexcept { cpuEmitterData.minSpeed = speed; @@ -107,6 +119,23 @@ namespace SHADE customUpdateShader = shaderModule; } + void SHParticleEmitterComponent::SetColorTint(SHVec4 tint) noexcept + { + cpuEmitterData.colorTint = tint; + } + + void SHParticleEmitterComponent::SetColorTintRGB(SHVec3 tint) noexcept + { + cpuEmitterData.colorTint.x = tint.x; + cpuEmitterData.colorTint.y = tint.y; + cpuEmitterData.colorTint.z = tint.z; + } + + void SHParticleEmitterComponent::SetColorTintAlpha(float alpha) noexcept + { + cpuEmitterData.colorTint.w = alpha; + } + uint32_t SHParticleEmitterComponent::GetEmissionCount(void) const noexcept { return emissionCount; @@ -138,6 +167,16 @@ namespace SHADE return cpuEmitterData.angularRangesAndOffsets; } + SHVec2 SHParticleEmitterComponent::GetAngularRanges(void) const noexcept + { + return SHVec2{cpuEmitterData.angularRangesAndOffsets.x, cpuEmitterData.angularRangesAndOffsets.y}; + } + + SHVec2 SHParticleEmitterComponent::GetAngularOffsets(void) const noexcept + { + return {cpuEmitterData.angularRangesAndOffsets.z, cpuEmitterData.angularRangesAndOffsets.w }; + } + float SHParticleEmitterComponent::GetMinSpeed(void) const noexcept { return cpuEmitterData.minSpeed; @@ -194,4 +233,19 @@ namespace SHADE return customUpdateShader; } + SHVec4 const& SHParticleEmitterComponent::GetColorTint(void) const noexcept + { + return cpuEmitterData.colorTint; + } + + SHVec3 SHParticleEmitterComponent::GetColorTintRGB(void) const noexcept + { + return SHVec3 (cpuEmitterData.colorTint.x, cpuEmitterData.colorTint.y, cpuEmitterData.colorTint.z); + } + + float SHParticleEmitterComponent::GetColorTintAlpha(void) const noexcept + { + return cpuEmitterData.colorTint.w; + } + } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h index d9c26666..e5360e85 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h @@ -1,5 +1,6 @@ #pragma once +#include "SH_API.h" #include "Resource/SHHandle.h" #include "Math/Vector/SHVec2.h" #include "Math/Vector/SHVec4.h" @@ -15,7 +16,7 @@ namespace SHADE class SHVkShaderModule; class SHVkPipeline; - class SHParticleEmitterComponent : public SHComponent + class SH_API SHParticleEmitterComponent : public SHComponent { private: @@ -24,7 +25,7 @@ namespace SHADE //! Angular ranges of emission SHVec4 angularRangesAndOffsets; - //! minimum starting velocity + //! minimum starting velocity float minSpeed; //! Maximum starting velocity @@ -39,6 +40,9 @@ namespace SHADE //! Spawn lifetime and size range (min and max) SHVec4 lifeAndSizeRange; + //! Color tint to assign to particles + SHVec4 colorTint; + //! Size decay for particles float sizeDecayMult; @@ -67,6 +71,9 @@ namespace SHADE //! x scale, x scale decay, y scale and y scale decay SHVec4 scaleAndDecay; + //! Color tinting for particle + SHVec4 colorTint; + //! Life of the particle float life; @@ -147,6 +154,8 @@ namespace SHADE void SetMinLife (float val) noexcept; void SetMaxLife (float val) noexcept; void SetAngularRangesAndOffsets (SHVec4 const& ranges) noexcept; + void SetAngularRanges (SHVec2 const& ranges) noexcept; + void SetAngularOffsets (SHVec2 const& offsets) noexcept; void SetMinSpeed (float speed) noexcept; void SetMaxSpeed (float speed) noexcept; void SetRotationSpeed (float speed) noexcept; @@ -156,6 +165,9 @@ namespace SHADE void SetMaxSize (float size) noexcept; void SetSizeDecayMult (float decay) noexcept; void SetCustomUpdateShader (Handle shaderModule) noexcept; + void SetColorTint (SHVec4 tint) noexcept; + void SetColorTintRGB (SHVec3 tint) noexcept; + void SetColorTintAlpha (float alpha) noexcept; uint32_t GetEmissionCount (void) const noexcept; bool GetPassive (void) const noexcept; @@ -163,6 +175,8 @@ namespace SHADE float GetMinLife (void) const noexcept; float GetMaxLife (void) const noexcept; SHVec4 const& GetAngularRangesAndOffsets (void) const noexcept; + SHVec2 GetAngularRanges (void) const noexcept; + SHVec2 GetAngularOffsets (void) const noexcept; float GetMinSpeed (void) const noexcept; float GetMaxSpeed (void) const noexcept; float GetRotationSpeed (void) const noexcept; @@ -172,6 +186,9 @@ namespace SHADE float GetMaxSize (void) const noexcept; float GetSizeDecayMult (void) const noexcept; Handle GetCustomUpdateShader (void) const noexcept; + SHVec4 const& GetColorTint (void) const noexcept; + SHVec3 GetColorTintRGB (void) const noexcept; + float GetColorTintAlpha (void) const noexcept; /*-----------------------------------------------------------------------*/ /* NON-INTERFACE FUNCTIONS */ diff --git a/SHADE_Engine/src/Serialization/SHYAMLConverters.h b/SHADE_Engine/src/Serialization/SHYAMLConverters.h index 2550388e..923037d1 100644 --- a/SHADE_Engine/src/Serialization/SHYAMLConverters.h +++ b/SHADE_Engine/src/Serialization/SHYAMLConverters.h @@ -519,6 +519,7 @@ namespace YAML static constexpr std::string_view ROTATION_DECAY_TAG = "Rotation Decay"; static constexpr std::string_view TEXTURE_ASSET_ID_TAG = "Texture Asset ID"; static constexpr std::string_view CUSTOM_UPDATE_SHADER_ASSET_ID_TAG = "Custom Update Shader Asset ID"; + static constexpr std::string_view COLOR_TINT_TAG = "Color Tint"; static YAML::Node encode(SHParticleEmitterComponent const& rhs) { @@ -538,6 +539,7 @@ namespace YAML node[ROTATION_DECAY_TAG.data()] = rhs.GetRotationDecay(); node[TEXTURE_ASSET_ID_TAG.data()] = rhs.GetTextureAssetID(); node[CUSTOM_UPDATE_SHADER_ASSET_ID_TAG.data()] = rhs.GetCustomUpdateShaderAssetID(); + node[COLOR_TINT_TAG.data()] = rhs.GetColorTint(); return node; } @@ -581,6 +583,8 @@ namespace YAML if (node[ROTATION_DECAY_TAG.data()].IsDefined()) rhs.SetRotationDecay(node[ROTATION_DECAY_TAG.data()].as()); + if (node[COLOR_TINT_TAG.data()].IsDefined()) + rhs.SetColorTint(node[COLOR_TINT_TAG.data()].as()); if (node[TEXTURE_ASSET_ID_TAG.data()].IsDefined()) { diff --git a/SHADE_Managed/src/Components/ParticleEmitter.cxx b/SHADE_Managed/src/Components/ParticleEmitter.cxx new file mode 100644 index 00000000..a5bbf350 --- /dev/null +++ b/SHADE_Managed/src/Components/ParticleEmitter.cxx @@ -0,0 +1,170 @@ +#include "SHpch.h" + +#include "ParticleEmitter.hxx" + + +namespace SHADE +{ + ParticleEmitter::ParticleEmitter(Entity entity) + :Component(entity) + { + + } + + void ParticleEmitter::Emit() + { + GetNativeComponent()->Emit(); + } + + + float ParticleEmitter::EmissionInterval::get() + { + return (GetNativeComponent()->GetEmissionInterval()); + } + + void ParticleEmitter::EmissionInterval::set(float val) + { + GetNativeComponent()->SetEmissionInterval(val); + } + + bool ParticleEmitter::IsPassive::get() + { + return (GetNativeComponent()->GetPassive()); + } + + void ParticleEmitter::IsPassive::set(bool val) + { + GetNativeComponent()->SetPassive(val); + } + + float ParticleEmitter::MinLife::get() + { + return (GetNativeComponent()->GetMinLife()); + } + + void ParticleEmitter::MinLife::set(float val) + { + GetNativeComponent()->SetMinLife(val); + } + + float ParticleEmitter::MaxLife::get() + { + return (GetNativeComponent()->GetMaxLife()); + } + + void ParticleEmitter::MaxLife::set(float val) + { + GetNativeComponent()->SetMaxLife(val); + } + + Vector2 ParticleEmitter::AngularRanges::get() + { + return Convert::ToCLI(GetNativeComponent()->GetAngularRanges()); + } + + void ParticleEmitter::AngularRanges::set(Vector2 val) + { + GetNativeComponent()->SetAngularRanges(Convert::ToNative(val)); + } + + Vector2 ParticleEmitter::AngularOffsets::get() + { + return Convert::ToCLI(GetNativeComponent()->GetAngularOffsets()); + } + + void ParticleEmitter::AngularOffsets::set(Vector2 val) + { + GetNativeComponent()->SetAngularOffsets(Convert::ToNative(val)); + } + + float ParticleEmitter::MinSpeed::get() + { + return GetNativeComponent()->GetMinSpeed(); + } + + void ParticleEmitter::MinSpeed::set(float val) + { + GetNativeComponent()->SetMinSpeed(val); + } + + float ParticleEmitter::MaxSpeed::get() + { + return GetNativeComponent()->GetMinSpeed(); + } + + void ParticleEmitter::MaxSpeed::set(float val) + { + GetNativeComponent()->SetMaxSpeed(val); + } + + float ParticleEmitter::RotationSpeed::get() + { + return GetNativeComponent()->GetRotationSpeed(); + } + + void ParticleEmitter::RotationSpeed::set(float val) + { + GetNativeComponent()->SetRotationSpeed(val); + } + + float ParticleEmitter::RotationDecay::get() + { + return GetNativeComponent()->GetRotationDecay(); + } + + void ParticleEmitter::RotationDecay::set(float val) + { + GetNativeComponent()->SetRotationDecay(val); + } + + float ParticleEmitter::MinSize::get() + { + return GetNativeComponent()->GetMinSize(); + } + + void ParticleEmitter::MinSize::set(float val) + { + GetNativeComponent()->SetMinSize(val); + } + + float ParticleEmitter::MaxSize::get() + { + return GetNativeComponent()->GetMaxSize(); + } + + void ParticleEmitter::MaxSize::set(float val) + { + GetNativeComponent()->SetMaxSize(val); + } + + float ParticleEmitter::SizeDecayMult::get() + { + return GetNativeComponent()->GetSizeDecayMult(); + } + + void ParticleEmitter::SizeDecayMult::set(float val) + { + GetNativeComponent()->SetSizeDecayMult(val); + } + + Vector3 ParticleEmitter::ColorTintRGB::get() + { + return Convert::ToCLI(GetNativeComponent()->GetColorTintRGB()); + } + + void ParticleEmitter::ColorTintRGB::set(Vector3 val) + { + GetNativeComponent()->SetColorTintRGB (Convert::ToNative (val)); + } + + float ParticleEmitter::ColorTintAlpha::get() + { + return GetNativeComponent()->GetColorTintAlpha(); + } + + void ParticleEmitter::ColorTintAlpha::set(float val) + { + GetNativeComponent()->SetColorTintAlpha(val); + } + +} \ No newline at end of file diff --git a/SHADE_Managed/src/Components/ParticleEmitter.hxx b/SHADE_Managed/src/Components/ParticleEmitter.hxx new file mode 100644 index 00000000..686d0a83 --- /dev/null +++ b/SHADE_Managed/src/Components/ParticleEmitter.hxx @@ -0,0 +1,115 @@ +#pragma once + +// Project Includes +#include "Components/Component.hxx" +#include "Math/Vector2.hxx" +#include "Math/Vector3.hxx" +#include "Math/Quaternion.hxx" +// External Dependencies +#include "Camera/SHCameraComponent.h" +#include "Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h" + +namespace SHADE +{ + public ref class ParticleEmitter : public Component + { + internal: + ParticleEmitter(Entity entity); + + public: + + property bool IsPassive + { + bool get(); + void set(bool val); + } + + property float EmissionInterval + { + float get(); + void set(float val); + } + + property float MinLife + { + float get(); + void set(float val); + } + + property float MaxLife + { + float get(); + void set(float val); + } + + property Vector2 AngularRanges + { + Vector2 get(); + void set(Vector2 val); + } + + property Vector2 AngularOffsets + { + Vector2 get(); + void set(Vector2 val); + } + + property float MinSpeed + { + float get(); + void set(float val); + } + + property float MaxSpeed + { + float get(); + void set(float val); + } + + property float RotationSpeed + { + float get(); + void set(float val); + } + + property float RotationDecay + { + float get(); + void set(float val); + } + + property float MinSize + { + float get(); + void set(float val); + } + + property float MaxSize + { + float get(); + void set(float val); + } + + property float SizeDecayMult + { + float get(); + void set(float val); + } + + property Vector3 ColorTintRGB + { + Vector3 get(); + void set(Vector3 val); + } + + property float ColorTintAlpha + { + float get(); + void set (float val); + } + + void Emit(); + + + }; +} \ No newline at end of file