rendering: add builtin alpha-test pass support

This commit is contained in:
2026-04-06 21:05:50 +08:00
parent eea38d57d1
commit 9568cf0a16
26 changed files with 856 additions and 104 deletions

View File

@@ -574,10 +574,13 @@ TEST(RenderMaterialUtility_Test, ShadersWithoutBuiltinMetadataKeepImplicitForwar
TEST(RenderMaterialUtility_Test, ResolvesBuiltinForwardMaterialContractFromCanonicalNamesAndAliases) {
Material canonicalMaterial;
canonicalMaterial.SetFloat4("baseColor", Vector4(0.2f, 0.4f, 0.6f, 0.8f));
canonicalMaterial.SetFloat("_Cutoff", 0.3f);
EXPECT_EQ(ResolveBuiltinBaseColorFactor(&canonicalMaterial), Vector4(0.2f, 0.4f, 0.6f, 0.8f));
EXPECT_FLOAT_EQ(ResolveBuiltinAlphaCutoff(&canonicalMaterial), 0.3f);
Material aliasMaterial;
aliasMaterial.SetFloat4("_BaseColor", Vector4(0.7f, 0.6f, 0.5f, 0.4f));
aliasMaterial.SetFloat("_Cutoff", 0.42f);
Texture* baseColorTexture = new Texture();
IResource::ConstructParams textureParams = {};
textureParams.name = "AliasBaseColor";
@@ -588,6 +591,7 @@ TEST(RenderMaterialUtility_Test, ResolvesBuiltinForwardMaterialContractFromCanon
const BuiltinForwardMaterialData materialData = BuildBuiltinForwardMaterialData(&aliasMaterial);
EXPECT_EQ(materialData.baseColorFactor, Vector4(0.7f, 0.6f, 0.5f, 0.4f));
EXPECT_FLOAT_EQ(materialData.alphaCutoff, 0.42f);
EXPECT_EQ(ResolveBuiltinBaseColorTexture(&aliasMaterial), baseColorTexture);
}
@@ -608,9 +612,18 @@ TEST(RenderMaterialUtility_Test, ResolvesBuiltinForwardMaterialContractFromShade
textureProperty.semantic = "BaseColorTexture";
shader->AddProperty(textureProperty);
ShaderPropertyDesc cutoffProperty = {};
cutoffProperty.name = "AlphaClipThreshold";
cutoffProperty.displayName = "Alpha Clip";
cutoffProperty.type = ShaderPropertyType::Range;
cutoffProperty.defaultValue = "0.5";
cutoffProperty.semantic = "AlphaCutoff";
shader->AddProperty(cutoffProperty);
Material material;
material.SetShader(ResourceHandle<Shader>(shader));
material.SetFloat4("TintColor", Vector4(0.3f, 0.5f, 0.7f, 0.9f));
material.SetFloat("AlphaClipThreshold", 0.61f);
Texture* texture = new Texture();
IResource::ConstructParams textureParams = {};
@@ -622,6 +635,7 @@ TEST(RenderMaterialUtility_Test, ResolvesBuiltinForwardMaterialContractFromShade
EXPECT_EQ(ResolveBuiltinBaseColorFactor(&material), Vector4(0.3f, 0.5f, 0.7f, 0.9f));
EXPECT_EQ(ResolveBuiltinBaseColorTexture(&material), texture);
EXPECT_FLOAT_EQ(ResolveBuiltinAlphaCutoff(&material), 0.61f);
}
TEST(RenderMaterialUtility_Test, ResolvesBuiltinForwardMaterialContractFromShaderSemanticDefaults) {
@@ -635,10 +649,18 @@ TEST(RenderMaterialUtility_Test, ResolvesBuiltinForwardMaterialContractFromShade
colorProperty.semantic = "BaseColor";
shader->AddProperty(colorProperty);
ShaderPropertyDesc cutoffProperty = {};
cutoffProperty.name = "_Cutoff";
cutoffProperty.type = ShaderPropertyType::Range;
cutoffProperty.defaultValue = "0.37";
cutoffProperty.semantic = "AlphaCutoff";
shader->AddProperty(cutoffProperty);
Material material;
material.SetShader(ResourceHandle<Shader>(shader));
EXPECT_EQ(ResolveBuiltinBaseColorFactor(&material), Vector4(0.11f, 0.22f, 0.33f, 0.44f));
EXPECT_FLOAT_EQ(ResolveBuiltinAlphaCutoff(&material), 0.37f);
EXPECT_EQ(ResolveBuiltinBaseColorTexture(&material), nullptr);
}
@@ -652,25 +674,38 @@ TEST(RenderMaterialUtility_Test, ExposesSchemaDrivenMaterialConstantPayload) {
colorProperty.semantic = "BaseColor";
shader->AddProperty(colorProperty);
ShaderPropertyDesc cutoffProperty = {};
cutoffProperty.name = "_Cutoff";
cutoffProperty.type = ShaderPropertyType::Range;
cutoffProperty.defaultValue = "0.6";
cutoffProperty.semantic = "AlphaCutoff";
shader->AddProperty(cutoffProperty);
Material material;
material.SetShader(ResourceHandle<Shader>(shader));
const MaterialConstantPayloadView payload = ResolveSchemaMaterialConstantPayload(&material);
ASSERT_TRUE(payload.IsValid());
ASSERT_EQ(payload.size, 16u);
ASSERT_EQ(payload.size, 32u);
ASSERT_TRUE(payload.layout.IsValid());
ASSERT_EQ(payload.layout.count, 1u);
EXPECT_EQ(payload.layout.size, 16u);
ASSERT_EQ(payload.layout.count, 2u);
EXPECT_EQ(payload.layout.size, 32u);
EXPECT_EQ(payload.layout.fields[0].name, "_BaseColor");
EXPECT_EQ(payload.layout.fields[0].offset, 0u);
EXPECT_EQ(payload.layout.fields[0].size, 16u);
EXPECT_EQ(payload.layout.fields[0].alignedSize, 16u);
EXPECT_EQ(payload.layout.fields[1].name, "_Cutoff");
EXPECT_EQ(payload.layout.fields[1].offset, 16u);
EXPECT_EQ(payload.layout.fields[1].size, 4u);
EXPECT_EQ(payload.layout.fields[1].alignedSize, 16u);
const float* values = static_cast<const float*>(payload.data);
EXPECT_FLOAT_EQ(values[0], 0.25f);
EXPECT_FLOAT_EQ(values[1], 0.5f);
EXPECT_FLOAT_EQ(values[2], 0.75f);
EXPECT_FLOAT_EQ(values[3], 1.0f);
const float* cutoffValues = static_cast<const float*>(payload.data) + 4;
EXPECT_FLOAT_EQ(cutoffValues[0], 0.6f);
}
TEST(RenderMaterialUtility_Test, UsesOpacityOnlyWhenBaseColorFactorIsMissing) {