diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 9a331c5a..18b44bc7 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -433,6 +433,8 @@ add_library(XCEngine STATIC ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/VisibleRenderItem.h ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/VisibleRenderObject.h ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/BuiltinPassContract.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/RenderMaterialResolve.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/RenderMaterialStateUtils.h ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/RenderSceneUtility.h ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/RenderPass.h ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/RenderSceneExtractor.h diff --git a/engine/include/XCEngine/Rendering/RenderMaterialResolve.h b/engine/include/XCEngine/Rendering/RenderMaterialResolve.h new file mode 100644 index 00000000..3eceb7cc --- /dev/null +++ b/engine/include/XCEngine/Rendering/RenderMaterialResolve.h @@ -0,0 +1,246 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include + +namespace XCEngine { +namespace Rendering { + +struct BuiltinForwardMaterialData { + Math::Vector4 baseColorFactor = Math::Vector4::One(); +}; + +struct MaterialConstantLayoutView { + const Resources::MaterialConstantFieldDesc* fields = nullptr; + size_t count = 0; + size_t size = 0; + + bool IsValid() const { + return fields != nullptr && count > 0 && size > 0; + } +}; + +struct MaterialConstantPayloadView { + const void* data = nullptr; + size_t size = 0; + MaterialConstantLayoutView layout = {}; + + bool IsValid() const { + return data != nullptr && size > 0 && layout.IsValid() && layout.size == size; + } +}; + +inline const Resources::ShaderPropertyDesc* FindShaderPropertyBySemantic( + const Resources::Material* material, + const Containers::String& semantic) { + if (material == nullptr || material->GetShader() == nullptr) { + return nullptr; + } + + const Containers::String normalizedSemantic = NormalizeBuiltinPassMetadataValue(semantic); + for (const Resources::ShaderPropertyDesc& property : material->GetShader()->GetProperties()) { + if (NormalizeBuiltinPassMetadataValue(property.semantic) == normalizedSemantic) { + return &property; + } + } + + return nullptr; +} + +inline Math::Vector4 ResolveBuiltinBaseColorFactor(const Resources::Material* material) { + if (material == nullptr) { + return Math::Vector4::One(); + } + + if (const Resources::ShaderPropertyDesc* property = FindShaderPropertyBySemantic(material, "BaseColor")) { + if (material->HasProperty(property->name) && + (property->type == Resources::ShaderPropertyType::Color || + property->type == Resources::ShaderPropertyType::Vector)) { + return material->GetFloat4(property->name); + } + } + + static const char* kBaseColorPropertyNames[] = { + "baseColor", + "_BaseColor", + "color", + "_Color" + }; + + for (const char* propertyName : kBaseColorPropertyNames) { + if (material->HasProperty(Containers::String(propertyName))) { + return material->GetFloat4(Containers::String(propertyName)); + } + } + + Math::Vector4 baseColor = Math::Vector4::One(); + static const char* kOpacityPropertyNames[] = { + "opacity", + "_Opacity", + "alpha", + "_Alpha" + }; + for (const char* propertyName : kOpacityPropertyNames) { + if (material->HasProperty(Containers::String(propertyName))) { + baseColor.w = material->GetFloat(Containers::String(propertyName)); + break; + } + } + + return baseColor; +} + +inline const Resources::Texture* ResolveBuiltinBaseColorTexture(const Resources::Material* material) { + if (material == nullptr) { + return nullptr; + } + + if (const Resources::ShaderPropertyDesc* property = FindShaderPropertyBySemantic(material, "BaseColorTexture")) { + const Resources::ResourceHandle textureHandle = material->GetTexture(property->name); + if (textureHandle.Get() != nullptr && textureHandle->IsValid()) { + return textureHandle.Get(); + } + } + + static const char* kTextureNames[] = { + "baseColorTexture", + "_BaseColorTexture", + "_MainTex", + "albedoTexture", + "mainTexture", + "texture" + }; + + for (const char* textureName : kTextureNames) { + const Resources::ResourceHandle textureHandle = + material->GetTexture(Containers::String(textureName)); + if (textureHandle.Get() != nullptr && textureHandle->IsValid()) { + return textureHandle.Get(); + } + } + + return nullptr; +} + +inline BuiltinForwardMaterialData BuildBuiltinForwardMaterialData(const Resources::Material* material) { + BuiltinForwardMaterialData data = {}; + data.baseColorFactor = ResolveBuiltinBaseColorFactor(material); + return data; +} + +inline MaterialConstantPayloadView ResolveSchemaMaterialConstantPayload(const Resources::Material* material) { + if (material == nullptr || material->GetShader() == nullptr) { + return {}; + } + + const Containers::Array& constantLayout = material->GetConstantLayout(); + const Containers::Array& constantBufferData = material->GetConstantBufferData(); + if (constantLayout.Empty() || constantBufferData.Empty()) { + return {}; + } + + MaterialConstantLayoutView layoutView = {}; + layoutView.fields = constantLayout.Data(); + layoutView.count = constantLayout.Size(); + layoutView.size = constantBufferData.Size(); + + return { constantBufferData.Data(), constantBufferData.Size(), layoutView }; +} + +inline const Resources::Material* ResolveMaterial( + const Components::MeshRendererComponent* meshRenderer, + const Resources::Mesh* mesh, + Core::uint32 materialIndex) { + if (meshRenderer != nullptr && materialIndex < meshRenderer->GetMaterialCount()) { + if (const Resources::Material* material = meshRenderer->GetMaterial(materialIndex)) { + return material; + } + } + + if (mesh != nullptr && materialIndex < mesh->GetMaterials().Size()) { + if (const Resources::Material* material = mesh->GetMaterials()[materialIndex]) { + return material; + } + } + + if (meshRenderer != nullptr && meshRenderer->GetMaterialCount() > 0) { + if (const Resources::Material* material = meshRenderer->GetMaterial(0)) { + return material; + } + } + + if (mesh != nullptr && mesh->GetMaterials().Size() > 0) { + return mesh->GetMaterials()[0]; + } + + return nullptr; +} + +inline const Resources::Material* ResolveMaterial(const VisibleRenderItem& visibleItem) { + if (visibleItem.material != nullptr) { + return visibleItem.material; + } + + return ResolveMaterial(visibleItem.meshRenderer, visibleItem.mesh, visibleItem.materialIndex); +} + +inline Core::int32 ResolveMaterialRenderQueue(const Resources::Material* material) { + return material != nullptr + ? material->GetRenderQueue() + : static_cast(Resources::MaterialRenderQueue::Geometry); +} + +inline bool IsTransparentRenderQueue(Core::int32 renderQueue) { + return renderQueue >= static_cast(Resources::MaterialRenderQueue::Transparent); +} + +inline bool MatchesBuiltinPass(const Resources::Material* material, BuiltinMaterialPass pass) { + if (material == nullptr) { + return pass == BuiltinMaterialPass::ForwardLit; + } + + const Containers::String shaderPass = material->GetShaderPass(); + const Containers::String lightMode = material->GetTag("LightMode"); + const bool hasMaterialShaderPass = !NormalizeBuiltinPassMetadataValue(shaderPass).Empty(); + const bool hasMaterialLightMode = !NormalizeBuiltinPassMetadataValue(lightMode).Empty(); + if (hasMaterialShaderPass || hasMaterialLightMode) { + if (hasMaterialShaderPass && + !MatchesBuiltinPassName(shaderPass, pass)) { + return false; + } + if (hasMaterialLightMode && + !MatchesBuiltinPassName(lightMode, pass)) { + return false; + } + return true; + } + + const Resources::Shader* shader = material->GetShader(); + if (shader != nullptr) { + bool shaderHasExplicitBuiltinMetadata = false; + for (const Resources::ShaderPass& shaderPassEntry : shader->GetPasses()) { + if (ShaderPassMatchesBuiltinPass(shaderPassEntry, pass)) { + return true; + } + + if (ShaderPassHasExplicitBuiltinMetadata(shaderPassEntry)) { + shaderHasExplicitBuiltinMetadata = true; + } + } + + if (shaderHasExplicitBuiltinMetadata) { + return false; + } + } + + return pass == BuiltinMaterialPass::ForwardLit; +} + +} // namespace Rendering +} // namespace XCEngine diff --git a/engine/include/XCEngine/Rendering/RenderMaterialStateUtils.h b/engine/include/XCEngine/Rendering/RenderMaterialStateUtils.h new file mode 100644 index 00000000..9bb215ff --- /dev/null +++ b/engine/include/XCEngine/Rendering/RenderMaterialStateUtils.h @@ -0,0 +1,178 @@ +#pragma once + +#include +#include + +namespace XCEngine { +namespace Rendering { + +inline RHI::CullMode ToRHICullMode(Resources::MaterialCullMode mode) { + switch (mode) { + case Resources::MaterialCullMode::Front: + return RHI::CullMode::Front; + case Resources::MaterialCullMode::Back: + return RHI::CullMode::Back; + case Resources::MaterialCullMode::None: + default: + return RHI::CullMode::None; + } +} + +inline RHI::ComparisonFunc ToRHIComparisonFunc(Resources::MaterialComparisonFunc func) { + switch (func) { + case Resources::MaterialComparisonFunc::Never: + return RHI::ComparisonFunc::Never; + case Resources::MaterialComparisonFunc::Equal: + return RHI::ComparisonFunc::Equal; + case Resources::MaterialComparisonFunc::LessEqual: + return RHI::ComparisonFunc::LessEqual; + case Resources::MaterialComparisonFunc::Greater: + return RHI::ComparisonFunc::Greater; + case Resources::MaterialComparisonFunc::NotEqual: + return RHI::ComparisonFunc::NotEqual; + case Resources::MaterialComparisonFunc::GreaterEqual: + return RHI::ComparisonFunc::GreaterEqual; + case Resources::MaterialComparisonFunc::Always: + return RHI::ComparisonFunc::Always; + case Resources::MaterialComparisonFunc::Less: + default: + return RHI::ComparisonFunc::Less; + } +} + +inline RHI::BlendFactor ToRHIBlendFactor(Resources::MaterialBlendFactor factor) { + switch (factor) { + case Resources::MaterialBlendFactor::Zero: + return RHI::BlendFactor::Zero; + case Resources::MaterialBlendFactor::SrcColor: + return RHI::BlendFactor::SrcColor; + case Resources::MaterialBlendFactor::InvSrcColor: + return RHI::BlendFactor::InvSrcColor; + case Resources::MaterialBlendFactor::SrcAlpha: + return RHI::BlendFactor::SrcAlpha; + case Resources::MaterialBlendFactor::InvSrcAlpha: + return RHI::BlendFactor::InvSrcAlpha; + case Resources::MaterialBlendFactor::DstAlpha: + return RHI::BlendFactor::DstAlpha; + case Resources::MaterialBlendFactor::InvDstAlpha: + return RHI::BlendFactor::InvDstAlpha; + case Resources::MaterialBlendFactor::DstColor: + return RHI::BlendFactor::DstColor; + case Resources::MaterialBlendFactor::InvDstColor: + return RHI::BlendFactor::InvDstColor; + case Resources::MaterialBlendFactor::SrcAlphaSat: + return RHI::BlendFactor::SrcAlphaSat; + case Resources::MaterialBlendFactor::BlendFactor: + return RHI::BlendFactor::BlendFactor; + case Resources::MaterialBlendFactor::InvBlendFactor: + return RHI::BlendFactor::InvBlendFactor; + case Resources::MaterialBlendFactor::Src1Color: + return RHI::BlendFactor::Src1Color; + case Resources::MaterialBlendFactor::InvSrc1Color: + return RHI::BlendFactor::InvSrc1Color; + case Resources::MaterialBlendFactor::Src1Alpha: + return RHI::BlendFactor::Src1Alpha; + case Resources::MaterialBlendFactor::InvSrc1Alpha: + return RHI::BlendFactor::InvSrc1Alpha; + case Resources::MaterialBlendFactor::One: + default: + return RHI::BlendFactor::One; + } +} + +inline RHI::BlendOp ToRHIBlendOp(Resources::MaterialBlendOp op) { + switch (op) { + case Resources::MaterialBlendOp::Subtract: + return RHI::BlendOp::Subtract; + case Resources::MaterialBlendOp::ReverseSubtract: + return RHI::BlendOp::ReverseSubtract; + case Resources::MaterialBlendOp::Min: + return RHI::BlendOp::Min; + case Resources::MaterialBlendOp::Max: + return RHI::BlendOp::Max; + case Resources::MaterialBlendOp::Add: + default: + return RHI::BlendOp::Add; + } +} + +inline RHI::RasterizerDesc BuildRasterizerState(const Resources::Material* material) { + RHI::RasterizerDesc desc = {}; + desc.fillMode = static_cast(RHI::FillMode::Solid); + desc.cullMode = static_cast(RHI::CullMode::None); + desc.frontFace = static_cast(RHI::FrontFace::CounterClockwise); + desc.depthClipEnable = true; + + if (material != nullptr) { + const Resources::MaterialRenderState& renderState = material->GetRenderState(); + desc.cullMode = static_cast(ToRHICullMode(renderState.cullMode)); + } + + return desc; +} + +inline RHI::BlendDesc BuildBlendState(const Resources::Material* material) { + RHI::BlendDesc desc = {}; + if (material != nullptr) { + const Resources::MaterialRenderState& renderState = material->GetRenderState(); + desc.blendEnable = renderState.blendEnable; + desc.srcBlend = static_cast(ToRHIBlendFactor(renderState.srcBlend)); + desc.dstBlend = static_cast(ToRHIBlendFactor(renderState.dstBlend)); + desc.srcBlendAlpha = static_cast(ToRHIBlendFactor(renderState.srcBlendAlpha)); + desc.dstBlendAlpha = static_cast(ToRHIBlendFactor(renderState.dstBlendAlpha)); + desc.blendOp = static_cast(ToRHIBlendOp(renderState.blendOp)); + desc.blendOpAlpha = static_cast(ToRHIBlendOp(renderState.blendOpAlpha)); + desc.colorWriteMask = renderState.colorWriteMask; + } + + return desc; +} + +inline RHI::DepthStencilStateDesc BuildDepthStencilState(const Resources::Material* material) { + RHI::DepthStencilStateDesc desc = {}; + desc.depthTestEnable = true; + desc.depthWriteEnable = true; + desc.depthFunc = static_cast(RHI::ComparisonFunc::Less); + desc.stencilEnable = false; + + if (material != nullptr) { + const Resources::MaterialRenderState& renderState = material->GetRenderState(); + desc.depthTestEnable = renderState.depthTestEnable; + desc.depthWriteEnable = renderState.depthWriteEnable; + desc.depthFunc = static_cast(ToRHIComparisonFunc(renderState.depthFunc)); + } + + return desc; +} + +inline void ApplyMaterialRenderState(const Resources::Material* material, RHI::GraphicsPipelineDesc& pipelineDesc) { + pipelineDesc.rasterizerState = BuildRasterizerState(material); + pipelineDesc.blendState = BuildBlendState(material); + pipelineDesc.depthStencilState = BuildDepthStencilState(material); +} + +struct MaterialRenderStateHash { + size_t operator()(const Resources::MaterialRenderState& state) const noexcept { + size_t hash = 2166136261u; + auto combine = [&hash](size_t value) { + hash ^= value + 0x9e3779b9u + (hash << 6) + (hash >> 2); + }; + + combine(static_cast(state.blendEnable)); + combine(static_cast(state.srcBlend)); + combine(static_cast(state.dstBlend)); + combine(static_cast(state.srcBlendAlpha)); + combine(static_cast(state.dstBlendAlpha)); + combine(static_cast(state.blendOp)); + combine(static_cast(state.blendOpAlpha)); + combine(static_cast(state.colorWriteMask)); + combine(static_cast(state.depthTestEnable)); + combine(static_cast(state.depthWriteEnable)); + combine(static_cast(state.depthFunc)); + combine(static_cast(state.cullMode)); + return hash; + } +}; + +} // namespace Rendering +} // namespace XCEngine diff --git a/engine/include/XCEngine/Rendering/RenderMaterialUtility.h b/engine/include/XCEngine/Rendering/RenderMaterialUtility.h index 55579ab9..6c5e0fa3 100644 --- a/engine/include/XCEngine/Rendering/RenderMaterialUtility.h +++ b/engine/include/XCEngine/Rendering/RenderMaterialUtility.h @@ -1,419 +1,5 @@ #pragma once -#include -#include -#include -#include -#include #include -#include - -#include -#include -#include -#include -#include - -namespace XCEngine { -namespace Rendering { - -struct BuiltinForwardMaterialData { - Math::Vector4 baseColorFactor = Math::Vector4::One(); -}; - -struct MaterialConstantLayoutView { - const Resources::MaterialConstantFieldDesc* fields = nullptr; - size_t count = 0; - size_t size = 0; - - bool IsValid() const { - return fields != nullptr && count > 0 && size > 0; - } -}; - -struct MaterialConstantPayloadView { - const void* data = nullptr; - size_t size = 0; - MaterialConstantLayoutView layout = {}; - - bool IsValid() const { - return data != nullptr && size > 0 && layout.IsValid() && layout.size == size; - } -}; - -inline const Resources::ShaderPropertyDesc* FindShaderPropertyBySemantic( - const Resources::Material* material, - const Containers::String& semantic) { - if (material == nullptr || material->GetShader() == nullptr) { - return nullptr; - } - - const Containers::String normalizedSemantic = NormalizeBuiltinPassMetadataValue(semantic); - for (const Resources::ShaderPropertyDesc& property : material->GetShader()->GetProperties()) { - if (NormalizeBuiltinPassMetadataValue(property.semantic) == normalizedSemantic) { - return &property; - } - } - - return nullptr; -} - -inline Math::Vector4 ResolveBuiltinBaseColorFactor(const Resources::Material* material) { - if (material == nullptr) { - return Math::Vector4::One(); - } - - if (const Resources::ShaderPropertyDesc* property = FindShaderPropertyBySemantic(material, "BaseColor")) { - if (material->HasProperty(property->name) && - (property->type == Resources::ShaderPropertyType::Color || - property->type == Resources::ShaderPropertyType::Vector)) { - return material->GetFloat4(property->name); - } - } - - static const char* kBaseColorPropertyNames[] = { - "baseColor", - "_BaseColor", - "color", - "_Color" - }; - - for (const char* propertyName : kBaseColorPropertyNames) { - if (material->HasProperty(Containers::String(propertyName))) { - return material->GetFloat4(Containers::String(propertyName)); - } - } - - Math::Vector4 baseColor = Math::Vector4::One(); - static const char* kOpacityPropertyNames[] = { - "opacity", - "_Opacity", - "alpha", - "_Alpha" - }; - for (const char* propertyName : kOpacityPropertyNames) { - if (material->HasProperty(Containers::String(propertyName))) { - baseColor.w = material->GetFloat(Containers::String(propertyName)); - break; - } - } - - return baseColor; -} - -inline const Resources::Texture* ResolveBuiltinBaseColorTexture(const Resources::Material* material) { - if (material == nullptr) { - return nullptr; - } - - if (const Resources::ShaderPropertyDesc* property = FindShaderPropertyBySemantic(material, "BaseColorTexture")) { - const Resources::ResourceHandle textureHandle = material->GetTexture(property->name); - if (textureHandle.Get() != nullptr && textureHandle->IsValid()) { - return textureHandle.Get(); - } - } - - static const char* kTextureNames[] = { - "baseColorTexture", - "_BaseColorTexture", - "_MainTex", - "albedoTexture", - "mainTexture", - "texture" - }; - - for (const char* textureName : kTextureNames) { - const Resources::ResourceHandle textureHandle = - material->GetTexture(Containers::String(textureName)); - if (textureHandle.Get() != nullptr && textureHandle->IsValid()) { - return textureHandle.Get(); - } - } - - return nullptr; -} - -inline BuiltinForwardMaterialData BuildBuiltinForwardMaterialData(const Resources::Material* material) { - BuiltinForwardMaterialData data = {}; - data.baseColorFactor = ResolveBuiltinBaseColorFactor(material); - return data; -} - -inline MaterialConstantPayloadView ResolveSchemaMaterialConstantPayload(const Resources::Material* material) { - if (material == nullptr || material->GetShader() == nullptr) { - return {}; - } - - const Containers::Array& constantLayout = material->GetConstantLayout(); - const Containers::Array& constantBufferData = material->GetConstantBufferData(); - if (constantLayout.Empty() || constantBufferData.Empty()) { - return {}; - } - - MaterialConstantLayoutView layoutView = {}; - layoutView.fields = constantLayout.Data(); - layoutView.count = constantLayout.Size(); - layoutView.size = constantBufferData.Size(); - - return { constantBufferData.Data(), constantBufferData.Size(), layoutView }; -} - -inline const Resources::Material* ResolveMaterial( - const Components::MeshRendererComponent* meshRenderer, - const Resources::Mesh* mesh, - Core::uint32 materialIndex) { - if (meshRenderer != nullptr && materialIndex < meshRenderer->GetMaterialCount()) { - if (const Resources::Material* material = meshRenderer->GetMaterial(materialIndex)) { - return material; - } - } - - if (mesh != nullptr && materialIndex < mesh->GetMaterials().Size()) { - if (const Resources::Material* material = mesh->GetMaterials()[materialIndex]) { - return material; - } - } - - if (meshRenderer != nullptr && meshRenderer->GetMaterialCount() > 0) { - if (const Resources::Material* material = meshRenderer->GetMaterial(0)) { - return material; - } - } - - if (mesh != nullptr && mesh->GetMaterials().Size() > 0) { - return mesh->GetMaterials()[0]; - } - - return nullptr; -} - -inline const Resources::Material* ResolveMaterial(const VisibleRenderItem& visibleItem) { - if (visibleItem.material != nullptr) { - return visibleItem.material; - } - - return ResolveMaterial(visibleItem.meshRenderer, visibleItem.mesh, visibleItem.materialIndex); -} - -inline Core::int32 ResolveMaterialRenderQueue(const Resources::Material* material) { - return material != nullptr - ? material->GetRenderQueue() - : static_cast(Resources::MaterialRenderQueue::Geometry); -} - -inline bool IsTransparentRenderQueue(Core::int32 renderQueue) { - return renderQueue >= static_cast(Resources::MaterialRenderQueue::Transparent); -} - -inline bool MatchesBuiltinPass(const Resources::Material* material, BuiltinMaterialPass pass) { - if (material == nullptr) { - return pass == BuiltinMaterialPass::ForwardLit; - } - - const Containers::String shaderPass = material->GetShaderPass(); - const Containers::String lightMode = material->GetTag("LightMode"); - const bool hasMaterialShaderPass = !NormalizeBuiltinPassMetadataValue(shaderPass).Empty(); - const bool hasMaterialLightMode = !NormalizeBuiltinPassMetadataValue(lightMode).Empty(); - if (hasMaterialShaderPass || hasMaterialLightMode) { - if (hasMaterialShaderPass && - !MatchesBuiltinPassName(shaderPass, pass)) { - return false; - } - if (hasMaterialLightMode && - !MatchesBuiltinPassName(lightMode, pass)) { - return false; - } - return true; - } - - const Resources::Shader* shader = material->GetShader(); - if (shader != nullptr) { - bool shaderHasExplicitBuiltinMetadata = false; - for (const Resources::ShaderPass& shaderPassEntry : shader->GetPasses()) { - if (ShaderPassMatchesBuiltinPass(shaderPassEntry, pass)) { - return true; - } - - if (ShaderPassHasExplicitBuiltinMetadata(shaderPassEntry)) { - shaderHasExplicitBuiltinMetadata = true; - } - } - - if (shaderHasExplicitBuiltinMetadata) { - return false; - } - } - - return pass == BuiltinMaterialPass::ForwardLit; -} - -inline RHI::CullMode ToRHICullMode(Resources::MaterialCullMode mode) { - switch (mode) { - case Resources::MaterialCullMode::Front: - return RHI::CullMode::Front; - case Resources::MaterialCullMode::Back: - return RHI::CullMode::Back; - case Resources::MaterialCullMode::None: - default: - return RHI::CullMode::None; - } -} - -inline RHI::ComparisonFunc ToRHIComparisonFunc(Resources::MaterialComparisonFunc func) { - switch (func) { - case Resources::MaterialComparisonFunc::Never: - return RHI::ComparisonFunc::Never; - case Resources::MaterialComparisonFunc::Equal: - return RHI::ComparisonFunc::Equal; - case Resources::MaterialComparisonFunc::LessEqual: - return RHI::ComparisonFunc::LessEqual; - case Resources::MaterialComparisonFunc::Greater: - return RHI::ComparisonFunc::Greater; - case Resources::MaterialComparisonFunc::NotEqual: - return RHI::ComparisonFunc::NotEqual; - case Resources::MaterialComparisonFunc::GreaterEqual: - return RHI::ComparisonFunc::GreaterEqual; - case Resources::MaterialComparisonFunc::Always: - return RHI::ComparisonFunc::Always; - case Resources::MaterialComparisonFunc::Less: - default: - return RHI::ComparisonFunc::Less; - } -} - -inline RHI::BlendFactor ToRHIBlendFactor(Resources::MaterialBlendFactor factor) { - switch (factor) { - case Resources::MaterialBlendFactor::Zero: - return RHI::BlendFactor::Zero; - case Resources::MaterialBlendFactor::SrcColor: - return RHI::BlendFactor::SrcColor; - case Resources::MaterialBlendFactor::InvSrcColor: - return RHI::BlendFactor::InvSrcColor; - case Resources::MaterialBlendFactor::SrcAlpha: - return RHI::BlendFactor::SrcAlpha; - case Resources::MaterialBlendFactor::InvSrcAlpha: - return RHI::BlendFactor::InvSrcAlpha; - case Resources::MaterialBlendFactor::DstAlpha: - return RHI::BlendFactor::DstAlpha; - case Resources::MaterialBlendFactor::InvDstAlpha: - return RHI::BlendFactor::InvDstAlpha; - case Resources::MaterialBlendFactor::DstColor: - return RHI::BlendFactor::DstColor; - case Resources::MaterialBlendFactor::InvDstColor: - return RHI::BlendFactor::InvDstColor; - case Resources::MaterialBlendFactor::SrcAlphaSat: - return RHI::BlendFactor::SrcAlphaSat; - case Resources::MaterialBlendFactor::BlendFactor: - return RHI::BlendFactor::BlendFactor; - case Resources::MaterialBlendFactor::InvBlendFactor: - return RHI::BlendFactor::InvBlendFactor; - case Resources::MaterialBlendFactor::Src1Color: - return RHI::BlendFactor::Src1Color; - case Resources::MaterialBlendFactor::InvSrc1Color: - return RHI::BlendFactor::InvSrc1Color; - case Resources::MaterialBlendFactor::Src1Alpha: - return RHI::BlendFactor::Src1Alpha; - case Resources::MaterialBlendFactor::InvSrc1Alpha: - return RHI::BlendFactor::InvSrc1Alpha; - case Resources::MaterialBlendFactor::One: - default: - return RHI::BlendFactor::One; - } -} - -inline RHI::BlendOp ToRHIBlendOp(Resources::MaterialBlendOp op) { - switch (op) { - case Resources::MaterialBlendOp::Subtract: - return RHI::BlendOp::Subtract; - case Resources::MaterialBlendOp::ReverseSubtract: - return RHI::BlendOp::ReverseSubtract; - case Resources::MaterialBlendOp::Min: - return RHI::BlendOp::Min; - case Resources::MaterialBlendOp::Max: - return RHI::BlendOp::Max; - case Resources::MaterialBlendOp::Add: - default: - return RHI::BlendOp::Add; - } -} - -inline RHI::RasterizerDesc BuildRasterizerState(const Resources::Material* material) { - RHI::RasterizerDesc desc = {}; - desc.fillMode = static_cast(RHI::FillMode::Solid); - desc.cullMode = static_cast(RHI::CullMode::None); - desc.frontFace = static_cast(RHI::FrontFace::CounterClockwise); - desc.depthClipEnable = true; - - if (material != nullptr) { - const Resources::MaterialRenderState& renderState = material->GetRenderState(); - desc.cullMode = static_cast(ToRHICullMode(renderState.cullMode)); - } - - return desc; -} - -inline RHI::BlendDesc BuildBlendState(const Resources::Material* material) { - RHI::BlendDesc desc = {}; - if (material != nullptr) { - const Resources::MaterialRenderState& renderState = material->GetRenderState(); - desc.blendEnable = renderState.blendEnable; - desc.srcBlend = static_cast(ToRHIBlendFactor(renderState.srcBlend)); - desc.dstBlend = static_cast(ToRHIBlendFactor(renderState.dstBlend)); - desc.srcBlendAlpha = static_cast(ToRHIBlendFactor(renderState.srcBlendAlpha)); - desc.dstBlendAlpha = static_cast(ToRHIBlendFactor(renderState.dstBlendAlpha)); - desc.blendOp = static_cast(ToRHIBlendOp(renderState.blendOp)); - desc.blendOpAlpha = static_cast(ToRHIBlendOp(renderState.blendOpAlpha)); - desc.colorWriteMask = renderState.colorWriteMask; - } - - return desc; -} - -inline RHI::DepthStencilStateDesc BuildDepthStencilState(const Resources::Material* material) { - RHI::DepthStencilStateDesc desc = {}; - desc.depthTestEnable = true; - desc.depthWriteEnable = true; - desc.depthFunc = static_cast(RHI::ComparisonFunc::Less); - desc.stencilEnable = false; - - if (material != nullptr) { - const Resources::MaterialRenderState& renderState = material->GetRenderState(); - desc.depthTestEnable = renderState.depthTestEnable; - desc.depthWriteEnable = renderState.depthWriteEnable; - desc.depthFunc = static_cast(ToRHIComparisonFunc(renderState.depthFunc)); - } - - return desc; -} - -inline void ApplyMaterialRenderState(const Resources::Material* material, RHI::GraphicsPipelineDesc& pipelineDesc) { - pipelineDesc.rasterizerState = BuildRasterizerState(material); - pipelineDesc.blendState = BuildBlendState(material); - pipelineDesc.depthStencilState = BuildDepthStencilState(material); -} - -struct MaterialRenderStateHash { - size_t operator()(const Resources::MaterialRenderState& state) const noexcept { - size_t hash = 2166136261u; - auto combine = [&hash](size_t value) { - hash ^= value + 0x9e3779b9u + (hash << 6) + (hash >> 2); - }; - - combine(static_cast(state.blendEnable)); - combine(static_cast(state.srcBlend)); - combine(static_cast(state.dstBlend)); - combine(static_cast(state.srcBlendAlpha)); - combine(static_cast(state.dstBlendAlpha)); - combine(static_cast(state.blendOp)); - combine(static_cast(state.blendOpAlpha)); - combine(static_cast(state.colorWriteMask)); - combine(static_cast(state.depthTestEnable)); - combine(static_cast(state.depthWriteEnable)); - combine(static_cast(state.depthFunc)); - combine(static_cast(state.cullMode)); - return hash; - } -}; - -} // namespace Rendering -} // namespace XCEngine +#include +#include