rendering: formalize unity-style shader pass contracts
This commit is contained in:
@@ -11,9 +11,9 @@ namespace XCEngine {
|
||||
namespace Resources {
|
||||
|
||||
constexpr Core::uint32 kTextureArtifactSchemaVersion = 1;
|
||||
constexpr Core::uint32 kMaterialArtifactSchemaVersion = 3;
|
||||
constexpr Core::uint32 kMaterialArtifactSchemaVersion = 4;
|
||||
constexpr Core::uint32 kMeshArtifactSchemaVersion = 2;
|
||||
constexpr Core::uint32 kShaderArtifactSchemaVersion = 3;
|
||||
constexpr Core::uint32 kShaderArtifactSchemaVersion = 4;
|
||||
constexpr Core::uint32 kUIDocumentArtifactSchemaVersion = 2;
|
||||
|
||||
struct TextureArtifactHeader {
|
||||
@@ -46,7 +46,7 @@ struct MeshArtifactHeader {
|
||||
};
|
||||
|
||||
struct MaterialArtifactFileHeader {
|
||||
char magic[8] = { 'X', 'C', 'M', 'A', 'T', '0', '3', '\0' };
|
||||
char magic[8] = { 'X', 'C', 'M', 'A', 'T', '0', '4', '\0' };
|
||||
Core::uint32 schemaVersion = kMaterialArtifactSchemaVersion;
|
||||
};
|
||||
|
||||
@@ -58,10 +58,20 @@ struct MaterialArtifactHeaderV2 {
|
||||
Core::uint32 textureBindingCount = 0;
|
||||
};
|
||||
|
||||
struct MaterialArtifactHeaderV3 {
|
||||
Core::int32 renderQueue = static_cast<Core::int32>(MaterialRenderQueue::Geometry);
|
||||
MaterialRenderState renderState = {};
|
||||
Core::uint32 tagCount = 0;
|
||||
Core::uint32 keywordCount = 0;
|
||||
Core::uint32 propertyCount = 0;
|
||||
Core::uint32 textureBindingCount = 0;
|
||||
};
|
||||
|
||||
struct MaterialArtifactHeader {
|
||||
Core::int32 renderQueue = static_cast<Core::int32>(MaterialRenderQueue::Geometry);
|
||||
MaterialRenderState renderState = {};
|
||||
Core::uint32 tagCount = 0;
|
||||
Core::uint32 hasRenderStateOverride = 0;
|
||||
Core::uint32 keywordCount = 0;
|
||||
Core::uint32 propertyCount = 0;
|
||||
Core::uint32 textureBindingCount = 0;
|
||||
@@ -73,7 +83,7 @@ struct MaterialPropertyArtifact {
|
||||
};
|
||||
|
||||
struct ShaderArtifactFileHeader {
|
||||
char magic[8] = { 'X', 'C', 'S', 'H', 'D', '0', '3', '\0' };
|
||||
char magic[8] = { 'X', 'C', 'S', 'H', 'D', '0', '4', '\0' };
|
||||
Core::uint32 schemaVersion = kShaderArtifactSchemaVersion;
|
||||
};
|
||||
|
||||
@@ -95,6 +105,15 @@ struct ShaderPassArtifactHeader {
|
||||
Core::uint32 variantCount = 0;
|
||||
};
|
||||
|
||||
struct ShaderPassArtifactHeaderV4 {
|
||||
Core::uint32 tagCount = 0;
|
||||
Core::uint32 resourceCount = 0;
|
||||
Core::uint32 keywordDeclarationCount = 0;
|
||||
Core::uint32 variantCount = 0;
|
||||
Core::uint32 hasFixedFunctionState = 0;
|
||||
MaterialRenderState fixedFunctionState = {};
|
||||
};
|
||||
|
||||
struct ShaderPropertyArtifact {
|
||||
Core::uint32 propertyType = 0;
|
||||
};
|
||||
|
||||
@@ -115,6 +115,155 @@ inline bool TryBuildBuiltinPassResourceBindingPlan(
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void AppendBuiltinPassResourceBinding(
|
||||
Containers::Array<Resources::ShaderResourceBindingDesc>& bindings,
|
||||
const char* name,
|
||||
Resources::ShaderResourceType type,
|
||||
Core::uint32 set,
|
||||
Core::uint32 binding,
|
||||
const char* semantic) {
|
||||
Resources::ShaderResourceBindingDesc desc = {};
|
||||
desc.name = name;
|
||||
desc.type = type;
|
||||
desc.set = set;
|
||||
desc.binding = binding;
|
||||
desc.semantic = semantic;
|
||||
bindings.PushBack(desc);
|
||||
}
|
||||
|
||||
inline bool TryBuildImplicitBuiltinPassResourceBindings(
|
||||
const Resources::ShaderPass& shaderPass,
|
||||
Containers::Array<Resources::ShaderResourceBindingDesc>& outBindings) {
|
||||
outBindings.Clear();
|
||||
|
||||
if (ShaderPassMatchesBuiltinPass(shaderPass, BuiltinMaterialPass::ForwardLit)) {
|
||||
AppendBuiltinPassResourceBinding(
|
||||
outBindings,
|
||||
"PerObjectConstants",
|
||||
Resources::ShaderResourceType::ConstantBuffer,
|
||||
0u,
|
||||
0u,
|
||||
"PerObject");
|
||||
AppendBuiltinPassResourceBinding(
|
||||
outBindings,
|
||||
"LightingConstants",
|
||||
Resources::ShaderResourceType::ConstantBuffer,
|
||||
1u,
|
||||
0u,
|
||||
"Lighting");
|
||||
AppendBuiltinPassResourceBinding(
|
||||
outBindings,
|
||||
"MaterialConstants",
|
||||
Resources::ShaderResourceType::ConstantBuffer,
|
||||
2u,
|
||||
0u,
|
||||
"Material");
|
||||
AppendBuiltinPassResourceBinding(
|
||||
outBindings,
|
||||
"ShadowReceiverConstants",
|
||||
Resources::ShaderResourceType::ConstantBuffer,
|
||||
3u,
|
||||
0u,
|
||||
"ShadowReceiver");
|
||||
AppendBuiltinPassResourceBinding(
|
||||
outBindings,
|
||||
"BaseColorTexture",
|
||||
Resources::ShaderResourceType::Texture2D,
|
||||
4u,
|
||||
0u,
|
||||
"BaseColorTexture");
|
||||
AppendBuiltinPassResourceBinding(
|
||||
outBindings,
|
||||
"LinearClampSampler",
|
||||
Resources::ShaderResourceType::Sampler,
|
||||
5u,
|
||||
0u,
|
||||
"LinearClampSampler");
|
||||
AppendBuiltinPassResourceBinding(
|
||||
outBindings,
|
||||
"ShadowMapTexture",
|
||||
Resources::ShaderResourceType::Texture2D,
|
||||
6u,
|
||||
0u,
|
||||
"ShadowMapTexture");
|
||||
AppendBuiltinPassResourceBinding(
|
||||
outBindings,
|
||||
"ShadowMapSampler",
|
||||
Resources::ShaderResourceType::Sampler,
|
||||
7u,
|
||||
0u,
|
||||
"ShadowMapSampler");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ShaderPassMatchesBuiltinPass(shaderPass, BuiltinMaterialPass::Unlit) ||
|
||||
ShaderPassMatchesBuiltinPass(shaderPass, BuiltinMaterialPass::DepthOnly) ||
|
||||
ShaderPassMatchesBuiltinPass(shaderPass, BuiltinMaterialPass::ShadowCaster)) {
|
||||
AppendBuiltinPassResourceBinding(
|
||||
outBindings,
|
||||
"PerObjectConstants",
|
||||
Resources::ShaderResourceType::ConstantBuffer,
|
||||
0u,
|
||||
0u,
|
||||
"PerObject");
|
||||
AppendBuiltinPassResourceBinding(
|
||||
outBindings,
|
||||
"MaterialConstants",
|
||||
Resources::ShaderResourceType::ConstantBuffer,
|
||||
1u,
|
||||
0u,
|
||||
"Material");
|
||||
AppendBuiltinPassResourceBinding(
|
||||
outBindings,
|
||||
"BaseColorTexture",
|
||||
Resources::ShaderResourceType::Texture2D,
|
||||
2u,
|
||||
0u,
|
||||
"BaseColorTexture");
|
||||
AppendBuiltinPassResourceBinding(
|
||||
outBindings,
|
||||
"LinearClampSampler",
|
||||
Resources::ShaderResourceType::Sampler,
|
||||
3u,
|
||||
0u,
|
||||
"LinearClampSampler");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ShaderPassMatchesBuiltinPass(shaderPass, BuiltinMaterialPass::ObjectId)) {
|
||||
AppendBuiltinPassResourceBinding(
|
||||
outBindings,
|
||||
"PerObjectConstants",
|
||||
Resources::ShaderResourceType::ConstantBuffer,
|
||||
0u,
|
||||
0u,
|
||||
"PerObject");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool TryBuildBuiltinPassResourceBindingPlan(
|
||||
const Resources::ShaderPass& shaderPass,
|
||||
BuiltinPassResourceBindingPlan& outPlan,
|
||||
Containers::String* outError = nullptr) {
|
||||
if (!shaderPass.resources.Empty()) {
|
||||
return TryBuildBuiltinPassResourceBindingPlan(shaderPass.resources, outPlan, outError);
|
||||
}
|
||||
|
||||
Containers::Array<Resources::ShaderResourceBindingDesc> implicitBindings;
|
||||
if (!TryBuildImplicitBuiltinPassResourceBindings(shaderPass, implicitBindings)) {
|
||||
if (outError != nullptr) {
|
||||
*outError = "Builtin pass does not declare explicit bindings and no implicit contract is available";
|
||||
}
|
||||
outPlan = {};
|
||||
return false;
|
||||
}
|
||||
|
||||
return TryBuildBuiltinPassResourceBindingPlan(implicitBindings, outPlan, outError);
|
||||
}
|
||||
|
||||
inline RHI::DescriptorType ToBuiltinPassDescriptorType(Resources::ShaderResourceType type) {
|
||||
switch (type) {
|
||||
case Resources::ShaderResourceType::ConstantBuffer:
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <XCEngine/RHI/RHITypes.h>
|
||||
#include <XCEngine/Resources/Material/Material.h>
|
||||
#include <XCEngine/Resources/Shader/Shader.h>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
@@ -96,59 +97,74 @@ inline RHI::BlendOp ToRHIBlendOp(Resources::MaterialBlendOp op) {
|
||||
}
|
||||
}
|
||||
|
||||
inline RHI::RasterizerDesc BuildRasterizerState(const Resources::Material* material) {
|
||||
inline Resources::MaterialRenderState ResolveEffectiveRenderState(
|
||||
const Resources::ShaderPass* shaderPass,
|
||||
const Resources::Material* material) {
|
||||
Resources::MaterialRenderState renderState = {};
|
||||
|
||||
if (shaderPass != nullptr && shaderPass->hasFixedFunctionState) {
|
||||
renderState = shaderPass->fixedFunctionState;
|
||||
} else if (material != nullptr) {
|
||||
renderState = material->GetRenderState();
|
||||
}
|
||||
|
||||
if (material != nullptr && material->HasRenderStateOverride()) {
|
||||
renderState = material->GetRenderState();
|
||||
}
|
||||
|
||||
return renderState;
|
||||
}
|
||||
|
||||
inline RHI::RasterizerDesc BuildRasterizerState(const Resources::MaterialRenderState& renderState) {
|
||||
RHI::RasterizerDesc desc = {};
|
||||
desc.fillMode = static_cast<uint32_t>(RHI::FillMode::Solid);
|
||||
desc.cullMode = static_cast<uint32_t>(RHI::CullMode::None);
|
||||
desc.frontFace = static_cast<uint32_t>(RHI::FrontFace::CounterClockwise);
|
||||
desc.depthClipEnable = true;
|
||||
|
||||
if (material != nullptr) {
|
||||
const Resources::MaterialRenderState& renderState = material->GetRenderState();
|
||||
desc.cullMode = static_cast<uint32_t>(ToRHICullMode(renderState.cullMode));
|
||||
}
|
||||
desc.cullMode = static_cast<uint32_t>(ToRHICullMode(renderState.cullMode));
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
inline RHI::BlendDesc BuildBlendState(const Resources::Material* material) {
|
||||
inline RHI::BlendDesc BuildBlendState(const Resources::MaterialRenderState& renderState) {
|
||||
RHI::BlendDesc desc = {};
|
||||
if (material != nullptr) {
|
||||
const Resources::MaterialRenderState& renderState = material->GetRenderState();
|
||||
desc.blendEnable = renderState.blendEnable;
|
||||
desc.srcBlend = static_cast<uint32_t>(ToRHIBlendFactor(renderState.srcBlend));
|
||||
desc.dstBlend = static_cast<uint32_t>(ToRHIBlendFactor(renderState.dstBlend));
|
||||
desc.srcBlendAlpha = static_cast<uint32_t>(ToRHIBlendFactor(renderState.srcBlendAlpha));
|
||||
desc.dstBlendAlpha = static_cast<uint32_t>(ToRHIBlendFactor(renderState.dstBlendAlpha));
|
||||
desc.blendOp = static_cast<uint32_t>(ToRHIBlendOp(renderState.blendOp));
|
||||
desc.blendOpAlpha = static_cast<uint32_t>(ToRHIBlendOp(renderState.blendOpAlpha));
|
||||
desc.colorWriteMask = renderState.colorWriteMask;
|
||||
}
|
||||
desc.blendEnable = renderState.blendEnable;
|
||||
desc.srcBlend = static_cast<uint32_t>(ToRHIBlendFactor(renderState.srcBlend));
|
||||
desc.dstBlend = static_cast<uint32_t>(ToRHIBlendFactor(renderState.dstBlend));
|
||||
desc.srcBlendAlpha = static_cast<uint32_t>(ToRHIBlendFactor(renderState.srcBlendAlpha));
|
||||
desc.dstBlendAlpha = static_cast<uint32_t>(ToRHIBlendFactor(renderState.dstBlendAlpha));
|
||||
desc.blendOp = static_cast<uint32_t>(ToRHIBlendOp(renderState.blendOp));
|
||||
desc.blendOpAlpha = static_cast<uint32_t>(ToRHIBlendOp(renderState.blendOpAlpha));
|
||||
desc.colorWriteMask = renderState.colorWriteMask;
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
inline RHI::DepthStencilStateDesc BuildDepthStencilState(const Resources::Material* material) {
|
||||
inline RHI::DepthStencilStateDesc BuildDepthStencilState(const Resources::MaterialRenderState& renderState) {
|
||||
RHI::DepthStencilStateDesc desc = {};
|
||||
desc.depthTestEnable = true;
|
||||
desc.depthWriteEnable = true;
|
||||
desc.depthFunc = static_cast<uint32_t>(RHI::ComparisonFunc::Less);
|
||||
desc.depthTestEnable = renderState.depthTestEnable;
|
||||
desc.depthWriteEnable = renderState.depthWriteEnable;
|
||||
desc.depthFunc = static_cast<uint32_t>(ToRHIComparisonFunc(renderState.depthFunc));
|
||||
desc.stencilEnable = false;
|
||||
|
||||
if (material != nullptr) {
|
||||
const Resources::MaterialRenderState& renderState = material->GetRenderState();
|
||||
desc.depthTestEnable = renderState.depthTestEnable;
|
||||
desc.depthWriteEnable = renderState.depthWriteEnable;
|
||||
desc.depthFunc = static_cast<uint32_t>(ToRHIComparisonFunc(renderState.depthFunc));
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
inline void ApplyRenderState(const Resources::MaterialRenderState& renderState, RHI::GraphicsPipelineDesc& pipelineDesc) {
|
||||
pipelineDesc.rasterizerState = BuildRasterizerState(renderState);
|
||||
pipelineDesc.blendState = BuildBlendState(renderState);
|
||||
pipelineDesc.depthStencilState = BuildDepthStencilState(renderState);
|
||||
}
|
||||
|
||||
inline void ApplyMaterialRenderState(const Resources::Material* material, RHI::GraphicsPipelineDesc& pipelineDesc) {
|
||||
pipelineDesc.rasterizerState = BuildRasterizerState(material);
|
||||
pipelineDesc.blendState = BuildBlendState(material);
|
||||
pipelineDesc.depthStencilState = BuildDepthStencilState(material);
|
||||
ApplyRenderState(ResolveEffectiveRenderState(nullptr, material), pipelineDesc);
|
||||
}
|
||||
|
||||
inline void ApplyResolvedRenderState(
|
||||
const Resources::ShaderPass* shaderPass,
|
||||
const Resources::Material* material,
|
||||
RHI::GraphicsPipelineDesc& pipelineDesc) {
|
||||
ApplyRenderState(ResolveEffectiveRenderState(shaderPass, material), pipelineDesc);
|
||||
}
|
||||
|
||||
struct MaterialRenderStateHash {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <XCEngine/Core/Asset/AssetRef.h>
|
||||
#include <XCEngine/Core/Asset/ResourceHandle.h>
|
||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
||||
#include <XCEngine/Resources/Material/MaterialRenderState.h>
|
||||
#include <XCEngine/Resources/Texture/Texture.h>
|
||||
#include <XCEngine/Resources/Shader/Shader.h>
|
||||
#include <XCEngine/Core/Containers/HashMap.h>
|
||||
@@ -25,87 +26,6 @@ enum class MaterialRenderQueue : Core::int32 {
|
||||
Overlay = 4000
|
||||
};
|
||||
|
||||
enum class MaterialCullMode : Core::uint8 {
|
||||
None = 0,
|
||||
Front = 1,
|
||||
Back = 2
|
||||
};
|
||||
|
||||
enum class MaterialComparisonFunc : Core::uint8 {
|
||||
Never = 0,
|
||||
Less = 1,
|
||||
Equal = 2,
|
||||
LessEqual = 3,
|
||||
Greater = 4,
|
||||
NotEqual = 5,
|
||||
GreaterEqual = 6,
|
||||
Always = 7
|
||||
};
|
||||
|
||||
enum class MaterialBlendOp : Core::uint8 {
|
||||
Add = 0,
|
||||
Subtract = 1,
|
||||
ReverseSubtract = 2,
|
||||
Min = 3,
|
||||
Max = 4
|
||||
};
|
||||
|
||||
enum class MaterialBlendFactor : Core::uint8 {
|
||||
Zero = 0,
|
||||
One = 1,
|
||||
SrcColor = 2,
|
||||
InvSrcColor = 3,
|
||||
SrcAlpha = 4,
|
||||
InvSrcAlpha = 5,
|
||||
DstAlpha = 6,
|
||||
InvDstAlpha = 7,
|
||||
DstColor = 8,
|
||||
InvDstColor = 9,
|
||||
SrcAlphaSat = 10,
|
||||
BlendFactor = 11,
|
||||
InvBlendFactor = 12,
|
||||
Src1Color = 13,
|
||||
InvSrc1Color = 14,
|
||||
Src1Alpha = 15,
|
||||
InvSrc1Alpha = 16
|
||||
};
|
||||
|
||||
struct MaterialRenderState {
|
||||
bool blendEnable = false;
|
||||
MaterialBlendFactor srcBlend = MaterialBlendFactor::One;
|
||||
MaterialBlendFactor dstBlend = MaterialBlendFactor::Zero;
|
||||
MaterialBlendFactor srcBlendAlpha = MaterialBlendFactor::One;
|
||||
MaterialBlendFactor dstBlendAlpha = MaterialBlendFactor::Zero;
|
||||
MaterialBlendOp blendOp = MaterialBlendOp::Add;
|
||||
MaterialBlendOp blendOpAlpha = MaterialBlendOp::Add;
|
||||
Core::uint8 colorWriteMask = 0xF;
|
||||
|
||||
bool depthTestEnable = true;
|
||||
bool depthWriteEnable = true;
|
||||
MaterialComparisonFunc depthFunc = MaterialComparisonFunc::Less;
|
||||
|
||||
MaterialCullMode cullMode = MaterialCullMode::None;
|
||||
|
||||
bool operator==(const MaterialRenderState& other) const {
|
||||
return blendEnable == other.blendEnable &&
|
||||
srcBlend == other.srcBlend &&
|
||||
dstBlend == other.dstBlend &&
|
||||
srcBlendAlpha == other.srcBlendAlpha &&
|
||||
dstBlendAlpha == other.dstBlendAlpha &&
|
||||
blendOp == other.blendOp &&
|
||||
blendOpAlpha == other.blendOpAlpha &&
|
||||
colorWriteMask == other.colorWriteMask &&
|
||||
depthTestEnable == other.depthTestEnable &&
|
||||
depthWriteEnable == other.depthWriteEnable &&
|
||||
depthFunc == other.depthFunc &&
|
||||
cullMode == other.cullMode;
|
||||
}
|
||||
|
||||
bool operator!=(const MaterialRenderState& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
enum class MaterialPropertyType {
|
||||
Float, Float2, Float3, Float4,
|
||||
Int, Int2, Int3, Int4,
|
||||
@@ -179,6 +99,8 @@ public:
|
||||
|
||||
void SetRenderState(const MaterialRenderState& renderState);
|
||||
const MaterialRenderState& GetRenderState() const { return m_renderState; }
|
||||
bool HasRenderStateOverride() const { return m_hasRenderStateOverride; }
|
||||
void SetRenderStateOverrideEnabled(bool enabled);
|
||||
|
||||
void SetShaderPass(const Containers::String& shaderPass);
|
||||
const Containers::String& GetShaderPass() const { return m_shaderPass; }
|
||||
@@ -256,6 +178,7 @@ private:
|
||||
ResourceHandle<class Shader> m_shader;
|
||||
Core::int32 m_renderQueue = static_cast<Core::int32>(MaterialRenderQueue::Geometry);
|
||||
MaterialRenderState m_renderState;
|
||||
bool m_hasRenderStateOverride = false;
|
||||
Containers::String m_shaderPass;
|
||||
Containers::Array<MaterialTagEntry> m_tags;
|
||||
ShaderKeywordSet m_keywordSet;
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/Core/Types.h>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Resources {
|
||||
|
||||
enum class MaterialCullMode : Core::uint8 {
|
||||
None = 0,
|
||||
Front = 1,
|
||||
Back = 2
|
||||
};
|
||||
|
||||
enum class MaterialComparisonFunc : Core::uint8 {
|
||||
Never = 0,
|
||||
Less = 1,
|
||||
Equal = 2,
|
||||
LessEqual = 3,
|
||||
Greater = 4,
|
||||
NotEqual = 5,
|
||||
GreaterEqual = 6,
|
||||
Always = 7
|
||||
};
|
||||
|
||||
enum class MaterialBlendOp : Core::uint8 {
|
||||
Add = 0,
|
||||
Subtract = 1,
|
||||
ReverseSubtract = 2,
|
||||
Min = 3,
|
||||
Max = 4
|
||||
};
|
||||
|
||||
enum class MaterialBlendFactor : Core::uint8 {
|
||||
Zero = 0,
|
||||
One = 1,
|
||||
SrcColor = 2,
|
||||
InvSrcColor = 3,
|
||||
SrcAlpha = 4,
|
||||
InvSrcAlpha = 5,
|
||||
DstAlpha = 6,
|
||||
InvDstAlpha = 7,
|
||||
DstColor = 8,
|
||||
InvDstColor = 9,
|
||||
SrcAlphaSat = 10,
|
||||
BlendFactor = 11,
|
||||
InvBlendFactor = 12,
|
||||
Src1Color = 13,
|
||||
InvSrc1Color = 14,
|
||||
Src1Alpha = 15,
|
||||
InvSrc1Alpha = 16
|
||||
};
|
||||
|
||||
struct MaterialRenderState {
|
||||
bool blendEnable = false;
|
||||
MaterialBlendFactor srcBlend = MaterialBlendFactor::One;
|
||||
MaterialBlendFactor dstBlend = MaterialBlendFactor::Zero;
|
||||
MaterialBlendFactor srcBlendAlpha = MaterialBlendFactor::One;
|
||||
MaterialBlendFactor dstBlendAlpha = MaterialBlendFactor::Zero;
|
||||
MaterialBlendOp blendOp = MaterialBlendOp::Add;
|
||||
MaterialBlendOp blendOpAlpha = MaterialBlendOp::Add;
|
||||
Core::uint8 colorWriteMask = 0xF;
|
||||
|
||||
bool depthTestEnable = true;
|
||||
bool depthWriteEnable = true;
|
||||
MaterialComparisonFunc depthFunc = MaterialComparisonFunc::Less;
|
||||
|
||||
MaterialCullMode cullMode = MaterialCullMode::None;
|
||||
|
||||
bool operator==(const MaterialRenderState& other) const {
|
||||
return blendEnable == other.blendEnable &&
|
||||
srcBlend == other.srcBlend &&
|
||||
dstBlend == other.dstBlend &&
|
||||
srcBlendAlpha == other.srcBlendAlpha &&
|
||||
dstBlendAlpha == other.dstBlendAlpha &&
|
||||
blendOp == other.blendOp &&
|
||||
blendOpAlpha == other.blendOpAlpha &&
|
||||
colorWriteMask == other.colorWriteMask &&
|
||||
depthTestEnable == other.depthTestEnable &&
|
||||
depthWriteEnable == other.depthWriteEnable &&
|
||||
depthFunc == other.depthFunc &&
|
||||
cullMode == other.cullMode;
|
||||
}
|
||||
|
||||
bool operator!=(const MaterialRenderState& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Resources
|
||||
} // namespace XCEngine
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <XCEngine/Core/Asset/IResource.h>
|
||||
#include <XCEngine/Core/Containers/Array.h>
|
||||
#include <XCEngine/Core/Types.h>
|
||||
#include <XCEngine/Resources/Material/MaterialRenderState.h>
|
||||
#include <XCEngine/Resources/Shader/ShaderKeywordTypes.h>
|
||||
|
||||
namespace XCEngine {
|
||||
@@ -97,6 +98,8 @@ struct ShaderStageVariant {
|
||||
|
||||
struct ShaderPass {
|
||||
Containers::String name;
|
||||
bool hasFixedFunctionState = false;
|
||||
MaterialRenderState fixedFunctionState;
|
||||
Containers::Array<ShaderPassTagEntry> tags;
|
||||
Containers::Array<ShaderResourceBindingDesc> resources;
|
||||
Containers::Array<ShaderKeywordDeclaration> keywordDeclarations;
|
||||
@@ -138,6 +141,8 @@ public:
|
||||
void ClearProperties();
|
||||
const Containers::Array<ShaderPropertyDesc>& GetProperties() const { return m_properties; }
|
||||
const ShaderPropertyDesc* FindProperty(const Containers::String& propertyName) const;
|
||||
void SetFallback(const Containers::String& fallback);
|
||||
const Containers::String& GetFallback() const { return m_fallback; }
|
||||
|
||||
void AddPass(const ShaderPass& pass);
|
||||
void ClearPasses();
|
||||
@@ -189,6 +194,7 @@ private:
|
||||
Containers::Array<ShaderAttribute> m_attributes;
|
||||
Containers::Array<ShaderPropertyDesc> m_properties;
|
||||
Containers::Array<ShaderPass> m_passes;
|
||||
Containers::String m_fallback;
|
||||
|
||||
class IRHIShader* m_rhiResource = nullptr;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user