From 4d145bbc43e27007303862a32a22dd9499caf866 Mon Sep 17 00:00:00 2001 From: Brandon Mak Date: Thu, 30 Mar 2023 19:15:03 +0800 Subject: [PATCH] Added support for custom VS and FS for particles --- Assets/Scenes/Scene2.shade | 8 +- Assets/Shaders/ParticleRounded_FS.glsl | 27 +++++ Assets/Shaders/ParticleRounded_FS.shshaderb | Bin 0 -> 1513 bytes .../ParticleRounded_FS.shshaderb.shmeta | 3 + Assets/Shaders/ParticleRounded_VS.glsl | 107 ++++++++++++++++++ Assets/Shaders/ParticleRounded_VS.shshaderb | Bin 0 -> 7377 bytes .../ParticleRounded_VS.shshaderb.shmeta | 3 + .../Inspector/SHEditorComponentView.hpp | 82 ++++++++++++++ .../Particles/SHParticleEmitterComponent.cpp | 40 +++++++ .../Particles/SHParticleEmitterComponent.h | 81 ++++++++----- .../Particles/SHParticleSubSystem.cpp | 81 ++++++++++++- .../MiddleEnd/Particles/SHParticleSubSystem.h | 12 +- .../src/Serialization/SHYAMLConverters.h | 29 +++++ 13 files changed, 436 insertions(+), 37 deletions(-) create mode 100644 Assets/Shaders/ParticleRounded_FS.glsl create mode 100644 Assets/Shaders/ParticleRounded_FS.shshaderb create mode 100644 Assets/Shaders/ParticleRounded_FS.shshaderb.shmeta create mode 100644 Assets/Shaders/ParticleRounded_VS.glsl create mode 100644 Assets/Shaders/ParticleRounded_VS.shshaderb create mode 100644 Assets/Shaders/ParticleRounded_VS.shshaderb.shmeta diff --git a/Assets/Scenes/Scene2.shade b/Assets/Scenes/Scene2.shade index 6e794990..4f925833 100644 --- a/Assets/Scenes/Scene2.shade +++ b/Assets/Scenes/Scene2.shade @@ -172,10 +172,12 @@ Rotation Speed: 0.0309999995 Rotation Decay: 0.0199999996 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: 0, y: 1, z: 0.56387639, w: 1} - Color Tint Range: {x: 0.5, y: 0.5, z: 0.5, w: 0} - Color Decay: {x: 0, y: 0, z: 0, w: 0} + 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/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 0000000000000000000000000000000000000000..59049d0c1cc9d068cc27942f802b250d3523f06c GIT binary patch literal 1513 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 literal 0 HcmV?d00001 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/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 2858b2af..7bb5c552 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -1004,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 f7ccc2ed..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; @@ -276,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; @@ -297,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; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h index f43ebefb..d32ac2fc 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleEmitterComponent.h @@ -115,7 +115,7 @@ namespace SHADE Handle particleData; //! Freelist data - Handle freelistData; + Handle freelistData; //! Indices data Handle indicesData; @@ -133,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; @@ -154,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; @@ -177,6 +193,8 @@ 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; @@ -189,42 +207,49 @@ namespace SHADE 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; - 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; + 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 a1c185aa..0df15b5b 100644 --- a/SHADE_Engine/src/Serialization/SHYAMLConverters.h +++ b/SHADE_Engine/src/Serialization/SHYAMLConverters.h @@ -518,6 +518,8 @@ 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"; @@ -541,6 +543,8 @@ 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(); @@ -634,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; }