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

@@ -1,7 +1,20 @@
// XC_BUILTIN_DEPTH_ONLY_OPENGL_PS
#version 430
layout(location = 0) out vec4 fragColor;
layout(binding = 0) uniform sampler2D uBaseColorTexture;
layout(std140, binding = 1) uniform MaterialConstants {
vec4 gBaseColorFactor;
vec4 gAlphaCutoffParams;
};
in vec2 vTexCoord;
void main() {
fragColor = vec4(0.0);
#ifdef XC_ALPHA_TEST
vec4 baseColor = texture(uBaseColorTexture, vTexCoord) * gBaseColorFactor;
if (baseColor.a < gAlphaCutoffParams.x) {
discard;
}
#endif
}

View File

@@ -1,7 +1,21 @@
// XC_BUILTIN_DEPTH_ONLY_VULKAN_PS
#version 450
layout(location = 0) out vec4 fragColor;
layout(set = 2, binding = 0) uniform texture2D uBaseColorTexture;
layout(set = 3, binding = 0) uniform sampler uLinearSampler;
layout(set = 1, binding = 0, std140) uniform MaterialConstants {
vec4 gBaseColorFactor;
vec4 gAlphaCutoffParams;
};
layout(location = 0) in vec2 vTexCoord;
void main() {
fragColor = vec4(0.0);
#ifdef XC_ALPHA_TEST
vec4 baseColor = texture(sampler2D(uBaseColorTexture, uLinearSampler), vTexCoord) * gBaseColorFactor;
if (baseColor.a < gAlphaCutoffParams.x) {
discard;
}
#endif
}

View File

@@ -1,8 +1,20 @@
// XC_BUILTIN_DEPTH_ONLY_D3D12_PS
struct PSInput {
float4 position : SV_POSITION;
Texture2D gBaseColorTexture : register(t0);
SamplerState gLinearSampler : register(s0);
cbuffer MaterialConstants : register(b1) {
float4 gBaseColorFactor;
float4 gAlphaCutoffParams;
};
float4 MainPS(PSInput input) : SV_TARGET {
return float4(0.0, 0.0, 0.0, 0.0);
struct PSInput {
float4 position : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
void MainPS(PSInput input) {
#ifdef XC_ALPHA_TEST
float4 baseColor = gBaseColorTexture.Sample(gLinearSampler, input.texcoord) * gBaseColorFactor;
clip(baseColor.a - gAlphaCutoffParams.x);
#endif
}

View File

@@ -1,5 +1,11 @@
Shader "Builtin Depth Only"
{
Properties
{
_BaseColor ("Base Color", Color) = (1,1,1,1) [Semantic(BaseColor)]
_Cutoff ("Alpha Cutoff", Range) = 0.5 [Semantic(AlphaCutoff)]
_MainTex ("Base Map", 2D) = "white" [Semantic(BaseColorTexture)]
}
SubShader
{
Pass
@@ -9,10 +15,14 @@ Shader "Builtin Depth Only"
Resources
{
PerObjectConstants (ConstantBuffer, 0, 0) [Semantic(PerObject)]
MaterialConstants (ConstantBuffer, 1, 0) [Semantic(Material)]
BaseColorTexture (Texture2D, 2, 0) [Semantic(BaseColorTexture)]
LinearClampSampler (Sampler, 3, 0) [Semantic(LinearClampSampler)]
}
HLSLPROGRAM
#pragma vertex MainVS
#pragma fragment MainPS
#pragma shader_feature_local _ XC_ALPHA_TEST
#pragma backend D3D12 HLSL "depth-only.vs.hlsl" "depth-only.ps.hlsl" vs_5_0 ps_5_0
#pragma backend OpenGL GLSL "depth-only.vert.glsl" "depth-only.frag.glsl"
#pragma backend Vulkan GLSL "depth-only.vert.vk.glsl" "depth-only.frag.vk.glsl"

View File

@@ -1,6 +1,7 @@
// XC_BUILTIN_DEPTH_ONLY_OPENGL_VS
#version 430
layout(location = 0) in vec3 aPosition;
layout(location = 2) in vec2 aTexCoord;
layout(std140, binding = 0) uniform PerObjectConstants {
mat4 gProjectionMatrix;
@@ -8,8 +9,11 @@ layout(std140, binding = 0) uniform PerObjectConstants {
mat4 gModelMatrix;
};
out vec2 vTexCoord;
void main() {
vec4 positionWS = gModelMatrix * vec4(aPosition, 1.0);
vec4 positionVS = gViewMatrix * positionWS;
gl_Position = gProjectionMatrix * positionVS;
vTexCoord = aTexCoord;
}

View File

@@ -1,6 +1,7 @@
// XC_BUILTIN_DEPTH_ONLY_VULKAN_VS
#version 450
layout(location = 0) in vec3 aPosition;
layout(location = 2) in vec2 aTexCoord;
layout(set = 0, binding = 0, std140) uniform PerObjectConstants {
mat4 gProjectionMatrix;
@@ -8,8 +9,11 @@ layout(set = 0, binding = 0, std140) uniform PerObjectConstants {
mat4 gModelMatrix;
};
layout(location = 0) out vec2 vTexCoord;
void main() {
vec4 positionWS = gModelMatrix * vec4(aPosition, 1.0);
vec4 positionVS = gViewMatrix * positionWS;
gl_Position = gProjectionMatrix * positionVS;
vTexCoord = aTexCoord;
}

View File

@@ -7,10 +7,12 @@ cbuffer PerObjectConstants : register(b0) {
struct VSInput {
float3 position : POSITION;
float2 texcoord : TEXCOORD0;
};
struct PSInput {
float4 position : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
PSInput MainVS(VSInput input) {
@@ -18,5 +20,6 @@ PSInput MainVS(VSInput input) {
float4 positionWS = mul(gModelMatrix, float4(input.position, 1.0));
float4 positionVS = mul(gViewMatrix, positionWS);
output.position = mul(gProjectionMatrix, positionVS);
output.texcoord = input.texcoord;
return output;
}

View File

@@ -28,6 +28,7 @@ layout(std140, binding = 1) uniform LightingConstants {
layout(std140, binding = 2) uniform MaterialConstants {
vec4 gBaseColorFactor;
vec4 gAlphaCutoffParams;
};
layout(std140, binding = 3) uniform ShadowReceiverConstants {
@@ -137,6 +138,11 @@ vec3 EvaluateAdditionalLight(AdditionalLightData light, vec3 normalWS, vec3 posi
void main() {
vec4 baseColor = texture(uBaseColorTexture, vTexCoord) * gBaseColorFactor;
#ifdef XC_ALPHA_TEST
if (baseColor.a < gAlphaCutoffParams.x) {
discard;
}
#endif
int additionalLightCount = min(int(gLightingParams.x + 0.5), XC_MAX_ADDITIONAL_LIGHTS);
if (gMainLightColorAndFlags.w < 0.5 && additionalLightCount == 0) {
fragColor = baseColor;

View File

@@ -30,6 +30,7 @@ layout(set = 1, binding = 0, std140) uniform LightingConstants {
layout(set = 2, binding = 0, std140) uniform MaterialConstants {
vec4 gBaseColorFactor;
vec4 gAlphaCutoffParams;
};
layout(set = 3, binding = 0, std140) uniform ShadowReceiverConstants {
@@ -139,6 +140,11 @@ vec3 EvaluateAdditionalLight(AdditionalLightData light, vec3 normalWS, vec3 posi
void main() {
vec4 baseColor = texture(sampler2D(uBaseColorTexture, uLinearSampler), vTexCoord) * gBaseColorFactor;
#ifdef XC_ALPHA_TEST
if (baseColor.a < gAlphaCutoffParams.x) {
discard;
}
#endif
int additionalLightCount = min(int(gLightingParams.x + 0.5), XC_MAX_ADDITIONAL_LIGHTS);
if (gMainLightColorAndFlags.w < 0.5 && additionalLightCount == 0) {
fragColor = baseColor;

View File

@@ -29,6 +29,7 @@ cbuffer LightingConstants : register(b1) {
cbuffer MaterialConstants : register(b2) {
float4 gBaseColorFactor;
float4 gAlphaCutoffParams;
};
cbuffer ShadowReceiverConstants : register(b3) {
@@ -139,6 +140,9 @@ float3 EvaluateAdditionalLight(AdditionalLightData light, float3 normalWS, float
float4 MainPS(PSInput input) : SV_TARGET {
float4 baseColor = gBaseColorTexture.Sample(gLinearSampler, input.texcoord) * gBaseColorFactor;
#ifdef XC_ALPHA_TEST
clip(baseColor.a - gAlphaCutoffParams.x);
#endif
const int additionalLightCount = min((int)gLightingParams.x, XC_MAX_ADDITIONAL_LIGHTS);
if (gMainLightColorAndFlags.a < 0.5f && additionalLightCount == 0) {
return baseColor;

View File

@@ -3,6 +3,7 @@ Shader "Builtin Forward Lit"
Properties
{
_BaseColor ("Base Color", Color) = (1,1,1,1) [Semantic(BaseColor)]
_Cutoff ("Alpha Cutoff", Range) = 0.5 [Semantic(AlphaCutoff)]
_MainTex ("Base Map", 2D) = "white" [Semantic(BaseColorTexture)]
}
SubShader
@@ -26,6 +27,7 @@ Shader "Builtin Forward Lit"
#pragma vertex MainVS
#pragma fragment MainPS
#pragma multi_compile _ XC_MAIN_LIGHT_SHADOWS
#pragma shader_feature_local _ XC_ALPHA_TEST
#pragma backend D3D12 HLSL "forward-lit.vs.hlsl" "forward-lit.ps.hlsl" vs_5_0 ps_5_0
#pragma backend OpenGL GLSL "forward-lit.vert.glsl" "forward-lit.frag.glsl"
#pragma backend Vulkan GLSL "forward-lit.vert.vk.glsl" "forward-lit.frag.vk.glsl"

View File

@@ -1,7 +1,21 @@
// XC_BUILTIN_SHADOW_CASTER_OPENGL_PS
#version 430
layout(location = 0) out vec4 fragColor;
layout(binding = 0) uniform sampler2D uBaseColorTexture;
layout(std140, binding = 1) uniform MaterialConstants {
vec4 gBaseColorFactor;
vec4 gAlphaCutoffParams;
};
in vec2 vTexCoord;
void main() {
fragColor = vec4(0.0);
#ifdef XC_ALPHA_TEST
vec4 baseColor = texture(uBaseColorTexture, vTexCoord) * gBaseColorFactor;
if (baseColor.a < gAlphaCutoffParams.x) {
discard;
}
#endif
gl_FragDepth = gl_FragCoord.z;
}

View File

@@ -1,7 +1,22 @@
// XC_BUILTIN_SHADOW_CASTER_VULKAN_PS
#version 450
layout(location = 0) out vec4 fragColor;
layout(set = 2, binding = 0) uniform texture2D uBaseColorTexture;
layout(set = 3, binding = 0) uniform sampler uLinearSampler;
layout(set = 1, binding = 0, std140) uniform MaterialConstants {
vec4 gBaseColorFactor;
vec4 gAlphaCutoffParams;
};
layout(location = 0) in vec2 vTexCoord;
void main() {
fragColor = vec4(0.0);
#ifdef XC_ALPHA_TEST
vec4 baseColor = texture(sampler2D(uBaseColorTexture, uLinearSampler), vTexCoord) * gBaseColorFactor;
if (baseColor.a < gAlphaCutoffParams.x) {
discard;
}
#endif
gl_FragDepth = gl_FragCoord.z;
}

View File

@@ -1,8 +1,21 @@
// XC_BUILTIN_SHADOW_CASTER_D3D12_PS
struct PSInput {
float4 position : SV_POSITION;
Texture2D gBaseColorTexture : register(t0);
SamplerState gLinearSampler : register(s0);
cbuffer MaterialConstants : register(b1) {
float4 gBaseColorFactor;
float4 gAlphaCutoffParams;
};
float4 MainPS(PSInput input) : SV_TARGET {
return float4(0.0, 0.0, 0.0, 0.0);
struct PSInput {
float4 position : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
float MainPS(PSInput input) : SV_Depth {
#ifdef XC_ALPHA_TEST
float4 baseColor = gBaseColorTexture.Sample(gLinearSampler, input.texcoord) * gBaseColorFactor;
clip(baseColor.a - gAlphaCutoffParams.x);
#endif
return input.position.z;
}

View File

@@ -1,5 +1,11 @@
Shader "Builtin Shadow Caster"
{
Properties
{
_BaseColor ("Base Color", Color) = (1,1,1,1) [Semantic(BaseColor)]
_Cutoff ("Alpha Cutoff", Range) = 0.5 [Semantic(AlphaCutoff)]
_MainTex ("Base Map", 2D) = "white" [Semantic(BaseColorTexture)]
}
SubShader
{
Pass
@@ -9,10 +15,14 @@ Shader "Builtin Shadow Caster"
Resources
{
PerObjectConstants (ConstantBuffer, 0, 0) [Semantic(PerObject)]
MaterialConstants (ConstantBuffer, 1, 0) [Semantic(Material)]
BaseColorTexture (Texture2D, 2, 0) [Semantic(BaseColorTexture)]
LinearClampSampler (Sampler, 3, 0) [Semantic(LinearClampSampler)]
}
HLSLPROGRAM
#pragma vertex MainVS
#pragma fragment MainPS
#pragma shader_feature_local _ XC_ALPHA_TEST
#pragma backend D3D12 HLSL "shadow-caster.vs.hlsl" "shadow-caster.ps.hlsl" vs_5_0 ps_5_0
#pragma backend OpenGL GLSL "shadow-caster.vert.glsl" "shadow-caster.frag.glsl"
#pragma backend Vulkan GLSL "shadow-caster.vert.vk.glsl" "shadow-caster.frag.vk.glsl"

View File

@@ -1,6 +1,7 @@
// XC_BUILTIN_SHADOW_CASTER_OPENGL_VS
#version 430
layout(location = 0) in vec3 aPosition;
layout(location = 2) in vec2 aTexCoord;
layout(std140, binding = 0) uniform PerObjectConstants {
mat4 gProjectionMatrix;
@@ -8,8 +9,11 @@ layout(std140, binding = 0) uniform PerObjectConstants {
mat4 gModelMatrix;
};
out vec2 vTexCoord;
void main() {
vec4 positionWS = gModelMatrix * vec4(aPosition, 1.0);
vec4 positionVS = gViewMatrix * positionWS;
gl_Position = gProjectionMatrix * positionVS;
vTexCoord = aTexCoord;
}

View File

@@ -1,6 +1,7 @@
// XC_BUILTIN_SHADOW_CASTER_VULKAN_VS
#version 450
layout(location = 0) in vec3 aPosition;
layout(location = 2) in vec2 aTexCoord;
layout(set = 0, binding = 0, std140) uniform PerObjectConstants {
mat4 gProjectionMatrix;
@@ -8,8 +9,11 @@ layout(set = 0, binding = 0, std140) uniform PerObjectConstants {
mat4 gModelMatrix;
};
layout(location = 0) out vec2 vTexCoord;
void main() {
vec4 positionWS = gModelMatrix * vec4(aPosition, 1.0);
vec4 positionVS = gViewMatrix * positionWS;
gl_Position = gProjectionMatrix * positionVS;
vTexCoord = aTexCoord;
}

View File

@@ -7,16 +7,19 @@ cbuffer PerObjectConstants : register(b0) {
struct VSInput {
float3 position : POSITION;
float2 texcoord : TEXCOORD0;
};
struct PSInput {
float4 position : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
PSInput MainVS(VSInput input) {
PSInput output;
float4 positionWS = mul(gModelMatrix, float4(input.position, 1.0));
float4 positionWS = mul(gModelMatrix, float4(input.position, 1.0f));
float4 positionVS = mul(gViewMatrix, positionWS);
output.position = mul(gProjectionMatrix, positionVS);
output.texcoord = input.texcoord;
return output;
}