diff --git a/Assets/Scenes/Scene2.shade b/Assets/Scenes/Scene2.shade index d284d4ea..4f925833 100644 --- a/Assets/Scenes/Scene2.shade +++ b/Assets/Scenes/Scene2.shade @@ -1,3 +1,4 @@ +- NavData: 0 - EID: 0 Name: Default IsActive: true @@ -170,8 +171,13 @@ Angular Ranges And Offset: {x: 6.19999981, y: 1.10000002, z: 0, w: 0.100000001} Rotation Speed: 0.0309999995 Rotation Decay: 0.0199999996 - Texture Asset ID: 63456868 + Texture Asset ID: 0 + Custom Vertex Shader Asset ID: 44202416 + Custom Fragment Shader Asset ID: 42315398 Custom Update Shader Asset ID: 0 - Color Tint: {x: 1, y: 0, z: 0, w: 1} + Color Tint: {x: 0.46696043, y: 1, z: 0, w: 1} + Color Tint Range: {x: 1, y: 0, z: 0, w: 0} + Color Decay: {x: -1, y: -1, z: -1, w: 0} + Acceleration: {x: 0, y: 0, z: 0} IsActive: true Scripts: ~ \ No newline at end of file diff --git a/Assets/Shaders/ParticleEmit_CS.glsl b/Assets/Shaders/ParticleEmit_CS.glsl index 7b6e60be..e3cf2977 100644 --- a/Assets/Shaders/ParticleEmit_CS.glsl +++ b/Assets/Shaders/ParticleEmit_CS.glsl @@ -14,6 +14,8 @@ struct EmitterParameters float rotationDecay; vec4 lifeAndSizeRange; // min life, max life, min size, max size vec4 colorTint; + vec4 colorTintRange; + vec4 colorDecay; float sizeDecay; uint textureIndex; float padding[2]; @@ -27,6 +29,7 @@ struct ParticleData vec4 acceleration; vec4 scaleAndDecay; vec4 colorTint; + vec4 colorDecay; float life; uint textureIndex; }; @@ -175,9 +178,18 @@ void main() particle.scaleAndDecay.y = particleSize; particle.scaleAndDecay.z = emitterParams.data.sizeDecay; particle.scaleAndDecay.w = emitterParams.data.sizeDecay; + particle.colorDecay = emitterParams.data.colorDecay; + float randRange = rand(seed) * 2.0f - 1.0f; + // Set particle color tint - particle.colorTint = emitterParams.data.colorTint; + particle.colorTint = emitterParams.data.colorTint + vec4 (randRange * emitterParams.data.colorTintRange.x, + randRange * emitterParams.data.colorTintRange.y, + randRange * emitterParams.data.colorTintRange.z, + randRange * emitterParams.data.colorTintRange.w); + + // 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 f0e7b191..16b1d366 100644 Binary files a/Assets/Shaders/ParticleEmit_CS.shshaderb and b/Assets/Shaders/ParticleEmit_CS.shshaderb differ diff --git a/Assets/Shaders/ParticleRounded_FS.glsl b/Assets/Shaders/ParticleRounded_FS.glsl new file mode 100644 index 00000000..6de4dc8b --- /dev/null +++ b/Assets/Shaders/ParticleRounded_FS.glsl @@ -0,0 +1,27 @@ +#version 460 core +#extension GL_EXT_nonuniform_qualifier : require + +layout (location = 0) out vec4 fragColor; + +layout (set = 0, binding = 1) uniform sampler2D textures[]; // for textures (global) + +// between shader stages +layout(location = 0) in struct +{ + vec2 uv; // location = 0 +} In; + +// material stuff +layout(location = 1) flat in struct +{ + uint textureIndex; + vec4 color; +} InFlat; + +void main () +{ + fragColor = vec4 (texture(textures [nonuniformEXT(InFlat.textureIndex)], In.uv)) * InFlat.color; + + if (fragColor.a < 0.01f) + discard; +} diff --git a/Assets/Shaders/ParticleRounded_FS.shshaderb b/Assets/Shaders/ParticleRounded_FS.shshaderb new file mode 100644 index 00000000..59049d0c Binary files /dev/null and b/Assets/Shaders/ParticleRounded_FS.shshaderb differ diff --git a/Assets/Shaders/ParticleRounded_FS.shshaderb.shmeta b/Assets/Shaders/ParticleRounded_FS.shshaderb.shmeta new file mode 100644 index 00000000..b5720806 --- /dev/null +++ b/Assets/Shaders/ParticleRounded_FS.shshaderb.shmeta @@ -0,0 +1,3 @@ +Name: ParticleRounded_FS +ID: 42315398 +Type: 2 diff --git a/Assets/Shaders/ParticleRounded_VS.glsl b/Assets/Shaders/ParticleRounded_VS.glsl new file mode 100644 index 00000000..414648e7 --- /dev/null +++ b/Assets/Shaders/ParticleRounded_VS.glsl @@ -0,0 +1,107 @@ +#version 460 core + +struct GenericData +{ + //! Delta time + float dt; + + //! Elapsed time of the application + float elapsedTime; + + //! Viewport width of the scene (excluding imgui, that means smaller than window) + uint viewportWidth; + + //! Ditto but for height + uint viewportHeight; +}; + +struct ParticleData +{ + vec4 position; + vec4 orientationSpeedDecay; + vec4 velocity; + vec4 acceleration; + vec4 scaleAndDecay; + vec4 colorTint; + vec4 colorDecay; + float life; + uint textureIndex; +}; + +layout (set = 0, binding = 0) uniform GenericDataBuffer +{ + GenericData data; +} genericDataBuffer; + + +layout(set = 1, binding = 0) uniform CameraData +{ + vec4 position; + mat4 vpMat; + mat4 viewMat; + mat4 projMat; +} cameraData; + +// output buffer not needed +layout (std430, set = 2, binding = 2) coherent restrict buffer ParticlesOutputBuffer +{ + ParticleData data[]; +} outputParticles; + +layout (std430, set = 2, binding = 4) coherent restrict buffer IndicesData +{ + uint indices[]; +}; + +// between shader stages +layout(location = 0) out struct +{ + vec2 uv; // location = 0 +} Out; + +// material stuff +layout(location = 1) out struct +{ + uint textureIndex; // location = 1 + vec4 color; // location = 2 +} OutFlat; + +vec2 CreateQuad (in uint vertexID) +{ + uint b = 1 << vertexID; + return vec2 ((0x3 & b) != 0, (0x9 & b) != 0); +} + +void main() +{ + // Create a quad and its texture coordinates + Out.uv = CreateQuad (gl_VertexIndex); + vec3 vertexPos = vec3 (Out.uv - vec2(0.5f), 0.0f); + vertexPos.y *= 0.5f; + + ParticleData particle = outputParticles.data[indices[gl_InstanceIndex]]; + + vec3 normalized = normalize (vec3 (particle.velocity.xyz)); + float pitch = acos (dot (normalized.xyz, normalize (vec3 (normalized.x, 0.0f, normalized.z)))); + + float angle = pitch; + // float angle = atan (normalized.y, normalized.x); + vec2 particleScaleData = particle.scaleAndDecay.xy; // x and y + + mat3 rotate = mat3 (1.0f); + rotate[0][0] = cos(angle); + rotate[0][1] = sin(angle); + rotate[1][0] = -sin(angle); + rotate[1][1] = cos(angle); + + vec3 particlePos = rotate * vertexPos; + + vec3 viewRight = normalize (vec3 (cameraData.viewMat[0][0], cameraData.viewMat[1][0], cameraData.viewMat[2][0])); + vec3 viewUp = normalize(vec3 (cameraData.viewMat[0][1], cameraData.viewMat[1][1], cameraData.viewMat[2][1])); + + 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/ParticleRounded_VS.shshaderb b/Assets/Shaders/ParticleRounded_VS.shshaderb new file mode 100644 index 00000000..0b2d07da Binary files /dev/null and b/Assets/Shaders/ParticleRounded_VS.shshaderb differ diff --git a/Assets/Shaders/ParticleRounded_VS.shshaderb.shmeta b/Assets/Shaders/ParticleRounded_VS.shshaderb.shmeta new file mode 100644 index 00000000..68577bd3 --- /dev/null +++ b/Assets/Shaders/ParticleRounded_VS.shshaderb.shmeta @@ -0,0 +1,3 @@ +Name: ParticleRounded_VS +ID: 44202416 +Type: 2 diff --git a/Assets/Shaders/ParticleUpdateGrowThenShrink_CS.glsl b/Assets/Shaders/ParticleUpdateGrowThenShrink_CS.glsl index 0c9600f5..b3dae84b 100644 --- a/Assets/Shaders/ParticleUpdateGrowThenShrink_CS.glsl +++ b/Assets/Shaders/ParticleUpdateGrowThenShrink_CS.glsl @@ -18,6 +18,7 @@ struct ParticleData vec4 acceleration; vec4 scaleAndDecay; vec4 colorTint; + vec4 colorDecay; float life; uint textureIndex; }; diff --git a/Assets/Shaders/ParticleUpdateRandomAcc_CS.glsl b/Assets/Shaders/ParticleUpdateRandomAcc_CS.glsl index bf500255..ea51b08c 100644 --- a/Assets/Shaders/ParticleUpdateRandomAcc_CS.glsl +++ b/Assets/Shaders/ParticleUpdateRandomAcc_CS.glsl @@ -17,6 +17,8 @@ struct ParticleData vec4 velocity; vec4 acceleration; vec4 scaleAndDecay; + vec4 colorTint; + vec4 colorDecay; float life; uint textureIndex; }; diff --git a/Assets/Shaders/ParticleUpdateRandomColor_CS.glsl b/Assets/Shaders/ParticleUpdateRandomColor_CS.glsl index 91c17eb5..012c6009 100644 --- a/Assets/Shaders/ParticleUpdateRandomColor_CS.glsl +++ b/Assets/Shaders/ParticleUpdateRandomColor_CS.glsl @@ -18,6 +18,7 @@ struct ParticleData vec4 acceleration; vec4 scaleAndDecay; vec4 colorTint; + vec4 colorDecay; float life; uint textureIndex; }; diff --git a/Assets/Shaders/ParticleUpdate_CS.glsl b/Assets/Shaders/ParticleUpdate_CS.glsl index 1f5384ec..d9b8b31b 100644 --- a/Assets/Shaders/ParticleUpdate_CS.glsl +++ b/Assets/Shaders/ParticleUpdate_CS.glsl @@ -18,6 +18,7 @@ struct ParticleData vec4 acceleration; vec4 scaleAndDecay; vec4 colorTint; + vec4 colorDecay; float life; uint textureIndex; }; @@ -126,6 +127,7 @@ void main() particle.orientationSpeedDecay.x += particle.orientationSpeedDecay.y; particle.scaleAndDecay.x *= particle.scaleAndDecay.z; particle.scaleAndDecay.y *= particle.scaleAndDecay.w; + particle.colorTint -= particle.colorDecay * genericDataBuffer.data.dt; if (particle.orientationSpeedDecay.y > 0.0f) { diff --git a/Assets/Shaders/ParticleUpdate_CS.shshaderb b/Assets/Shaders/ParticleUpdate_CS.shshaderb index e7a3ec64..45e17306 100644 Binary files a/Assets/Shaders/ParticleUpdate_CS.shshaderb and b/Assets/Shaders/ParticleUpdate_CS.shshaderb differ diff --git a/Assets/Shaders/Particle_VS.glsl b/Assets/Shaders/Particle_VS.glsl index b5b6f13e..362b1508 100644 --- a/Assets/Shaders/Particle_VS.glsl +++ b/Assets/Shaders/Particle_VS.glsl @@ -15,7 +15,6 @@ struct GenericData uint viewportHeight; }; - struct ParticleData { vec4 position; @@ -24,6 +23,7 @@ struct ParticleData vec4 acceleration; vec4 scaleAndDecay; vec4 colorTint; + vec4 colorDecay; float life; uint textureIndex; }; diff --git a/Assets/Shaders/Particle_VS.shshaderb b/Assets/Shaders/Particle_VS.shshaderb index 2ba7a729..0c18fff5 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 961e321a..7bb5c552 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -903,6 +903,26 @@ namespace SHADE comp->SetColorTint(val); }); + SHEditorWidgets::DragVec4("Color Decay", {"x", "y", "z", "w"}, + [comp = component]() + { + return comp->GetColorDecay(); + }, + [comp = component](SHVec4 const& val) + { + comp->SetColorDecay(val); + }); + + SHEditorWidgets::DragVec4("Color Tint Range", { "x", "y", "z", "w" }, + [comp = component]() + { + return comp->GetColorTintRange(); + }, + [comp = component](SHVec4 const& val) + { + comp->SetColorTintRange(val); + }); + SHEditorWidgets::DragInt("Texture Index", [comp = component]() @@ -984,6 +1004,88 @@ namespace SHADE } + SHEditorWidgets::InputText("Custom Vertex Shader", + [comp = component]() + { + auto customShader = comp->GetCustomVertexShader(); + + if (customShader) + return customShader->GetName(); + else + return std::string{}; + + }, + [comp = component](std::string const& text) + { + }, {}, ImGuiSliderFlags_ReadOnly); + + if (SHDragDrop::BeginTarget()) + { + if (AssetID* payload = SHDragDrop::AcceptPayload(SHDragDrop::DRAG_RESOURCE)) + { + Handle shaderModule = SHResourceManager::LoadOrGet(*payload); + + if (shaderModule) + { + component->SetCustomVertexShader(shaderModule); + component->SetCustomVertexShaderAssetID(*payload); + } + else + { + SHLOG_WARNING("[] Attempted to load invalid shader! Custom vertex shader for particles not set. "); + } + + SHDragDrop::EndTarget(); + } + } + ImGui::SameLine(); + if (ImGui::Button("Reset")) + { + component->SetCustomVertexShader({}); + component->SetCustomVertexShaderAssetID(INVALID_ASSET_ID); + } + + + SHEditorWidgets::InputText("Custom Fragment Shader", + [comp = component]() + { + auto customShader = comp->GetCustomFragmentShader(); + + if (customShader) + return customShader->GetName(); + else + return std::string{}; + + }, + [comp = component](std::string const& text) + { + }, {}, ImGuiSliderFlags_ReadOnly); + + if (SHDragDrop::BeginTarget()) + { + if (AssetID* payload = SHDragDrop::AcceptPayload(SHDragDrop::DRAG_RESOURCE)) + { + Handle shaderModule = SHResourceManager::LoadOrGet(*payload); + + if (shaderModule) + { + component->SetCustomFragmentShader(shaderModule); + component->SetCustomFragmentShaderAssetID(*payload); + } + else + { + SHLOG_WARNING("[] Attempted to load invalid shader! Custom fragment shader for particles not set. "); + } + + SHDragDrop::EndTarget(); + } + } + ImGui::SameLine(); + if (ImGui::Button("Reset")) + { + component->SetCustomFragmentShader({}); + component->SetCustomFragmentShaderAssetID(INVALID_ASSET_ID); + } SHEditorWidgets::CheckBox("Is Passive", [comp = component]() {return comp->GetPassive(); }, [comp = component](bool flag) {comp->SetPassive(flag); }); diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp index 74eb3727..392e18a5 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.cpp @@ -124,6 +124,16 @@ namespace SHADE customUpdateShaderID = id; } + void SHParticleEmitterComponent::SetCustomVertexShaderAssetID(AssetID id) noexcept + { + customVertexShaderID = id; + } + + void SHParticleEmitterComponent::SetCustomFragmentShaderAssetID(AssetID id) noexcept + { + customFragmentShaderID = id; + } + void SHParticleEmitterComponent::SetMinSize(float size) noexcept { cpuEmitterData.lifeAndSizeRange.z = size; @@ -139,6 +149,16 @@ namespace SHADE cpuEmitterData.sizeDecayMult = decay; } + void SHParticleEmitterComponent::SetCustomVertexShader(Handle shaderModule) noexcept + { + customVertexShader = shaderModule; + } + + void SHParticleEmitterComponent::SetCustomFragmentShader(Handle shaderModule) noexcept + { + customFragmentShader = shaderModule; + } + void SHParticleEmitterComponent::SetCustomUpdateShader(Handle shaderModule) noexcept { customUpdateShader = shaderModule; @@ -156,11 +176,45 @@ namespace SHADE cpuEmitterData.colorTint.z = tint.z; } + void SHParticleEmitterComponent::SetColorDecayRGB(SHVec3 const& decay) noexcept + { + cpuEmitterData.colorDecay.x = decay.x; + cpuEmitterData.colorDecay.y = decay.y; + cpuEmitterData.colorDecay.z = decay.z; + } + + void SHParticleEmitterComponent::SetColorDecayAlpha(float alpha) noexcept + { + cpuEmitterData.colorDecay.w = alpha; + } + void SHParticleEmitterComponent::SetColorTintAlpha(float alpha) noexcept { cpuEmitterData.colorTint.w = alpha; } + void SHParticleEmitterComponent::SetColorTintRange(SHVec4 const& tintRange) noexcept + { + cpuEmitterData.colorTintRange = tintRange; + } + + void SHParticleEmitterComponent::SetColorTintRangeRGB(SHVec3 const& tintRange) noexcept + { + cpuEmitterData.colorTintRange.x = tintRange.x; + cpuEmitterData.colorTintRange.y = tintRange.y; + cpuEmitterData.colorTintRange.z = tintRange.z; + } + + void SHParticleEmitterComponent::SetColorTintRangeAlpha(float alpha) noexcept + { + cpuEmitterData.colorTintRange.w = alpha; + } + + void SHParticleEmitterComponent::SetColorDecay(SHVec4 const& decay) noexcept + { + cpuEmitterData.colorDecay = decay; + } + uint32_t SHParticleEmitterComponent::GetEmissionCount(void) const noexcept { return emissionCount; @@ -242,6 +296,16 @@ namespace SHADE return customUpdateShaderID; } + AssetID SHParticleEmitterComponent::GetCustomVertexShaderAssetID(void) const noexcept + { + return customVertexShaderID; + } + + AssetID SHParticleEmitterComponent::GetCustomFragmentShaderAssetID(void) const noexcept + { + return customFragmentShaderID; + } + float SHParticleEmitterComponent::GetMinSize(void) const noexcept { return cpuEmitterData.lifeAndSizeRange.z; @@ -263,6 +327,16 @@ namespace SHADE return customUpdateShader; } + Handle SHParticleEmitterComponent::GetCustomVertexShader(void) const noexcept + { + return customVertexShader; + } + + Handle SHParticleEmitterComponent::GetCustomFragmentShader(void) const noexcept + { + return customFragmentShader; + } + SHVec4 const& SHParticleEmitterComponent::GetColorTint(void) const noexcept { return cpuEmitterData.colorTint; @@ -273,9 +347,39 @@ namespace SHADE return SHVec3 (cpuEmitterData.colorTint.x, cpuEmitterData.colorTint.y, cpuEmitterData.colorTint.z); } + SHVec3 SHParticleEmitterComponent::GetColorDecayRGB(void) const noexcept + { + return SHVec3(cpuEmitterData.colorDecay.x, cpuEmitterData.colorDecay.y, cpuEmitterData.colorDecay.z); + } + + float SHParticleEmitterComponent::GetColorDecayAlpha(void) const noexcept + { + return cpuEmitterData.colorDecay.w; + } + float SHParticleEmitterComponent::GetColorTintAlpha(void) const noexcept { return cpuEmitterData.colorTint.w; } + SHVec4 const& SHParticleEmitterComponent::GetColorTintRange(void) const noexcept + { + return cpuEmitterData.colorTintRange; + } + + SHVec3 SHParticleEmitterComponent::GetColorTintRangeRGB(void) const noexcept + { + return SHVec3(cpuEmitterData.colorTintRange.x, cpuEmitterData.colorTintRange.y, cpuEmitterData.colorTintRange.z); + } + + float SHParticleEmitterComponent::GetColorTintRangeAlpha(void) const noexcept + { + return cpuEmitterData.colorTintRange.w; + } + + SHVec4 const& SHParticleEmitterComponent::GetColorDecay(void) const noexcept + { + return cpuEmitterData.colorDecay; + } + } \ 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 47791c44..d32ac2fc 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h @@ -46,6 +46,12 @@ namespace SHADE //! Color tint to assign to particles SHVec4 colorTint; + //! Color tint range to assign to particles + SHVec4 colorTintRange; + + //! Color decay for particle + SHVec4 colorDecay; + //! Size decay for particles float sizeDecayMult; @@ -77,6 +83,9 @@ namespace SHADE //! Color tinting for particle SHVec4 colorTint; + //! Color tinting for particle + SHVec4 colorDecay; + //! Life of the particle float life; @@ -106,7 +115,7 @@ namespace SHADE Handle particleData; //! Freelist data - Handle freelistData; + Handle freelistData; //! Indices data Handle indicesData; @@ -124,6 +133,16 @@ namespace SHADE //! Internally the system will bind this pipeline when it detects that this is not a null handle Handle customUpdatePipeline; + //! Custom vertex shader + Handle customVertexShader; + + //! Custom fragment shader + Handle customFragmentShader; + + //! Custom graphics pipeline for drawing particles (created + //! from the VS and FS above). + Handle customGraphicsPipeline; + //! Emitter's data on the CPU side. To be copied to GPU. GPUEmitterStruct cpuEmitterData; @@ -145,6 +164,12 @@ namespace SHADE //! Custom update shaders, similarly with textures, will be identified through their AssetID AssetID customUpdateShaderID; + //! Custom vertex shaders, similarly with textures, will be identified through their AssetID + AssetID customVertexShaderID; + + //! Custom fragment shaders, similarly with textures, will be identified through their AssetID + AssetID customFragmentShaderID; + public: void OnCreate(void) override final; void OnDestroy(void) override final; @@ -168,41 +193,63 @@ namespace SHADE void SetMinSize (float size) noexcept; void SetMaxSize (float size) noexcept; void SetSizeDecayMult (float decay) noexcept; + void SetCustomVertexShader (Handle shaderModule) noexcept; + void SetCustomFragmentShader (Handle shaderModule) noexcept; void SetCustomUpdateShader (Handle shaderModule) noexcept; void SetColorTint (SHVec4 tint) noexcept; void SetColorTintRGB (SHVec3 tint) noexcept; void SetColorTintAlpha (float alpha) noexcept; + void SetColorTintRange (SHVec4 const& tintRange) noexcept; + void SetColorTintRangeRGB (SHVec3 const& tintRange) noexcept; + void SetColorTintRangeAlpha (float alpha) noexcept; - uint32_t GetEmissionCount (void) const noexcept; - bool GetPassive (void) const noexcept; - float GetEmissionInterval (void) const noexcept; - 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; - SHVec3 GetAcceleration (void) const noexcept; - float GetMinSpeed (void) const noexcept; - float GetMaxSpeed (void) const noexcept; - float GetRotationSpeed (void) const noexcept; - float GetRotationDecay (void) const noexcept; - uint32_t GetTextureIndex (void) const noexcept; - float GetMinSize (void) const noexcept; - 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; + void SetColorDecay (SHVec4 const& decay) noexcept; + void SetColorDecayRGB (SHVec3 const& decay) noexcept; + void SetColorDecayAlpha (float alpha) noexcept; + + uint32_t GetEmissionCount (void) const noexcept; + bool GetPassive (void) const noexcept; + float GetEmissionInterval (void) const noexcept; + 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; + SHVec3 GetAcceleration (void) const noexcept; + float GetMinSpeed (void) const noexcept; + float GetMaxSpeed (void) const noexcept; + float GetRotationSpeed (void) const noexcept; + float GetRotationDecay (void) const noexcept; + uint32_t GetTextureIndex (void) const noexcept; + float GetMinSize (void) const noexcept; + float GetMaxSize (void) const noexcept; + float GetSizeDecayMult (void) const noexcept; + Handle GetCustomUpdateShader (void) const noexcept; + Handle GetCustomVertexShader (void) const noexcept; + Handle GetCustomFragmentShader (void) const noexcept; + SHVec4 const& GetColorTint (void) const noexcept; + SHVec3 GetColorTintRGB (void) const noexcept; + float GetColorTintAlpha (void) const noexcept; + SHVec4 const& GetColorTintRange (void) const noexcept; + SHVec3 GetColorTintRangeRGB (void) const noexcept; + float GetColorTintRangeAlpha (void) const noexcept; + SHVec4 const& GetColorDecay (void) const noexcept; + SHVec3 GetColorDecayRGB (void) const noexcept; + float GetColorDecayAlpha (void) const noexcept; /*-----------------------------------------------------------------------*/ /* NON-INTERFACE FUNCTIONS */ /*-----------------------------------------------------------------------*/ void SetTextureAssetID(AssetID id) noexcept; void SetCustomUpdateShaderAssetID(AssetID id) noexcept; + void SetCustomVertexShaderAssetID(AssetID id) noexcept; + void SetCustomFragmentShaderAssetID (AssetID id) noexcept; AssetID GetTextureAssetID(void) const noexcept; AssetID GetCustomUpdateShaderAssetID(void) const noexcept; + AssetID GetCustomVertexShaderAssetID(void) const noexcept; + AssetID GetCustomFragmentShaderAssetID(void) const noexcept; + friend class SHParticleSubSystem; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.cpp index d99832a5..92405264 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.cpp @@ -268,10 +268,73 @@ namespace SHADE return customUpdatePipelineCache.at (customUpdateShader).customPipeline; } - void SHParticleSubSystem::Init(Handle device, Handle inDescPool, Handle compatibleRenderpass, Handle subpass, Handle VS, Handle FS, Handle emitCS, Handle defaultUpdateCS) noexcept + Handle SHParticleSubSystem::GetCustomGraphicsPipeline(Handle customVS, Handle customFS) noexcept + { + if (!customVS || !customFS) + return {}; + + if (!customGraphicsPipelineCache.contains(std::make_pair(customVS, customFS))) + { + SHPipelineLayoutParams plParams + { + .shaderModules = {customVS, customFS}, + .predefinedDescSetLayouts = SHGraphicsPredefinedData::GetSystemData(SHGraphicsPredefinedData::SystemType::PARTICLE_RENEDERING).descSetLayouts + }; + + auto pipelineLayout = logicalDevice->CreatePipelineLayout(plParams); + auto newPipeline = logicalDevice->CreateGraphicsPipeline(pipelineLayout, nullptr, renderpass, subpass); + + SHColorBlendState colorBlendState{}; + colorBlendState.logic_op_enable = VK_FALSE; + colorBlendState.logic_op = vk::LogicOp::eCopy; + + auto const& subpassColorReferences = subpass->GetColorAttachmentReferences(); + colorBlendState.attachments.reserve(subpassColorReferences.size()); + + + for (auto& att : subpassColorReferences) + { + colorBlendState.attachments.push_back(vk::PipelineColorBlendAttachmentState + { + .blendEnable = SHVkUtil::IsBlendCompatible(subpass->GetFormatFromAttachmentReference(att.attachment)), + .srcColorBlendFactor = vk::BlendFactor::eSrcAlpha, + .dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha, + .colorBlendOp = vk::BlendOp::eAdd, + .srcAlphaBlendFactor = vk::BlendFactor::eSrcAlpha, + .dstAlphaBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha, + .alphaBlendOp = vk::BlendOp::eAdd, + .colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA, + } + ); + } + + newPipeline->GetPipelineState().SetColorBlenState(colorBlendState); + + // Sets the input assembly state for rendering particles + SHInputAssemblyState inputAssemblyState{}; + inputAssemblyState.topology = vk::PrimitiveTopology::eTriangleFan; + newPipeline->GetPipelineState().SetInputAssemblyState(inputAssemblyState); + + newPipeline->ConstructPipeline(); + + if (!newPipeline) + return {}; + + auto customUpdateShaderData = CustomPipeline{ newPipeline, pipelineLayout }; + + customGraphicsPipelineCache.emplace(std::make_pair(customVS, customFS), customUpdateShaderData); + } + + return customGraphicsPipelineCache.at(std::make_pair(customVS, customFS)).customPipeline; + + } + + void SHParticleSubSystem::Init(Handle device, Handle inDescPool, Handle compatibleRenderpass, Handle compatibleSubpass, Handle VS, Handle FS, Handle emitCS, Handle defaultUpdateCS) noexcept { descPool = inDescPool; logicalDevice = device; + renderpass = compatibleRenderpass; + subpass = compatibleSubpass; /*-----------------------------------------------------------------------*/ /* INITIALIZE ALL PIPELINES */ @@ -499,12 +562,22 @@ namespace SHADE auto& emitters = SHComponentManager::GetDense(); auto const& mappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::PARTICLE_RENEDERING); - // bind the pipeline for updating - cmdBuffer->BindPipeline(renderingPipelineData.pipeline); - // TODO: Issue barrier for output particle data. Semaphore should also be issued outside in SHGraphicsSystem for (auto& emitter : emitters) { + if (emitter.customVertexShader && emitter.customFragmentShader) + { + if (!emitter.customGraphicsPipeline) + emitter.customGraphicsPipeline = GetCustomGraphicsPipeline(emitter.customVertexShader, emitter.customFragmentShader); + + cmdBuffer->BindPipeline(emitter.customGraphicsPipeline); + } + else + { + // bind the pipeline for updating + cmdBuffer->BindPipeline(renderingPipelineData.pipeline); + } + if (emitter.isActive) { // bind the descriptor sets required for emitting particles diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.h index a0675da6..2288a5bb 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.h @@ -82,7 +82,14 @@ namespace SHADE //! Desc pool for particle component desc set allocation Handle descPool; + //! Renderpass the system draws its particles in + Handle renderpass; + + //! Subpass the system draws its particles in + Handle subpass; + std::unordered_map, CustomPipeline> customUpdatePipelineCache; + std::unordered_map, Handle>, CustomPipeline> customGraphicsPipelineCache; void InitializeComponent (SHParticleEmitterComponent& comp) noexcept; @@ -92,10 +99,11 @@ namespace SHADE void PreparePrePostUpdateBarriers (std::vector& preUpdateBarriers, std::vector& postUpdateBarriers, SHParticleEmitterComponent const& emitter, uint32_t const EMITTER_INDEX, uint32_t const FRAME_INDEX) noexcept; - Handle GetCustomUpdatePipeline (Handle customUpdateShader) noexcept; + Handle GetCustomUpdatePipeline(Handle customUpdateShader) noexcept; + Handle GetCustomGraphicsPipeline(Handle customVS, Handle customFS) noexcept; public: - void Init(Handle device, Handle inDescPool, Handle compatibleRenderpass, Handle subpass, Handle VS, Handle FS, Handle emitCS, Handle defaultUpdateCS) noexcept; + void Init(Handle device, Handle inDescPool, Handle compatibleRenderpass, Handle compatibleSubpass, Handle VS, Handle FS, Handle emitCS, Handle defaultUpdateCS) noexcept; void Run(Handle cmdBuffer, uint32_t frameIndex, Handle waitFence = {}) noexcept; void ResetInstanceCounts (Handle cmdBuffer, uint32_t frameIndex) noexcept; diff --git a/SHADE_Engine/src/Serialization/SHYAMLConverters.h b/SHADE_Engine/src/Serialization/SHYAMLConverters.h index de57e45d..0df15b5b 100644 --- a/SHADE_Engine/src/Serialization/SHYAMLConverters.h +++ b/SHADE_Engine/src/Serialization/SHYAMLConverters.h @@ -518,8 +518,12 @@ namespace YAML static constexpr std::string_view ROTATION_SPEED_TAG = "Rotation Speed"; 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_VERTEX_SHADER_ASSET_ID_TAG = "Custom Vertex Shader Asset ID"; + static constexpr std::string_view CUSTOM_FRAGMENT_SHADER_ASSET_ID_TAG = "Custom Fragment Shader 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 constexpr std::string_view COLOR_TINT_RANGE_TAG = "Color Tint Range"; + static constexpr std::string_view COLOR_DECAY_TAG = "Color Decay"; static constexpr std::string_view ACCELERATION_TAG = "Acceleration"; static YAML::Node encode(SHParticleEmitterComponent const& rhs) @@ -539,8 +543,12 @@ namespace YAML node[ROTATION_SPEED_TAG.data()] = rhs.GetRotationSpeed(); node[ROTATION_DECAY_TAG.data()] = rhs.GetRotationDecay(); node[TEXTURE_ASSET_ID_TAG.data()] = rhs.GetTextureAssetID(); + node[CUSTOM_VERTEX_SHADER_ASSET_ID_TAG.data()] = rhs.GetCustomVertexShaderAssetID(); + node[CUSTOM_FRAGMENT_SHADER_ASSET_ID_TAG.data()] = rhs.GetCustomFragmentShaderAssetID(); node[CUSTOM_UPDATE_SHADER_ASSET_ID_TAG.data()] = rhs.GetCustomUpdateShaderAssetID(); node[COLOR_TINT_TAG.data()] = rhs.GetColorTint(); + node[COLOR_TINT_RANGE_TAG.data()] = rhs.GetColorTintRange(); + node[COLOR_DECAY_TAG.data()] = rhs.GetColorDecay(); node[ACCELERATION_TAG.data()] = rhs.GetAcceleration(); return node; @@ -591,6 +599,12 @@ namespace YAML if (node[COLOR_TINT_TAG.data()].IsDefined()) rhs.SetColorTint(node[COLOR_TINT_TAG.data()].as()); + if (node[COLOR_TINT_RANGE_TAG.data()].IsDefined()) + rhs.SetColorTintRange(node[COLOR_TINT_RANGE_TAG.data()].as()); + + if (node[COLOR_DECAY_TAG.data()].IsDefined()) + rhs.SetColorDecay(node[COLOR_DECAY_TAG.data()].as()); + if (node[ACCELERATION_TAG.data()].IsDefined()) rhs.SetAcceleration(node[ACCELERATION_TAG.data()].as()); @@ -624,6 +638,31 @@ namespace YAML rhs.SetCustomUpdateShader(shaderModule); rhs.SetCustomUpdateShaderAssetID(id); } + + if (node[CUSTOM_VERTEX_SHADER_ASSET_ID_TAG.data()].IsDefined()) + { + AssetID id = node[CUSTOM_VERTEX_SHADER_ASSET_ID_TAG.data()].as(); + + Handle shaderModule = SHResourceManager::LoadOrGet(id); + SHResourceManager::FinaliseChanges(); + //gfxSystem->BuildTextures(); + + rhs.SetCustomVertexShader(shaderModule); + rhs.SetCustomVertexShaderAssetID(id); + } + + if (node[CUSTOM_FRAGMENT_SHADER_ASSET_ID_TAG.data()].IsDefined()) + { + AssetID id = node[CUSTOM_FRAGMENT_SHADER_ASSET_ID_TAG.data()].as(); + + Handle shaderModule = SHResourceManager::LoadOrGet(id); + SHResourceManager::FinaliseChanges(); + //gfxSystem->BuildTextures(); + + rhs.SetCustomFragmentShader(shaderModule); + rhs.SetCustomFragmentShaderAssetID(id); + } + return true; }