Files
gold_dolphin/unity/Assets/Light/shaders/SpriteWithGroundClip.shader
2026-06-28 21:44:33 +08:00

239 lines
7.7 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Shader "Custom/SpriteWithGroundClip"
{
// 带地面裁剪和阴影的Sprite Shader
// 当Sprite的世界Y坐标低于地面高度时会被裁剪掉
// 支持投射阴影(可选)
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_GroundHeight ("地面高度 (Y坐标)", Float) = 0.0
[MaterialToggle] _EnableClip ("启用裁剪", Float) = 1.0
_ClipSoftness ("裁剪边缘柔和度", Range(0, 0.5)) = 0.05
// 阴影设置
[MaterialToggle] _CastShadow ("投射阴影", Float) = 1.0
_ShadowOpacity ("阴影透明度", Range(0, 1)) = 0.5
_ShadowOffset ("阴影偏移 (Y方向)", Float) = -0.1
_ShadowColor ("阴影颜色", Color) = (0, 0, 0, 0.5)
// 颜色
_Color ("颜色", Color) = (1, 1, 1, 1)
}
SubShader
{
Tags
{
"RenderPipeline" = "UniversalPipeline"
"Queue" = "Transparent"
"RenderType" = "Transparent"
}
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
Cull Off
Pass
{
Name "SpriteWithGroundClip"
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_instancing
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
struct Attributes
{
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
float4 color : COLOR;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
float4 color : COLOR;
float3 worldPos : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
CBUFFER_START(UnityPerMaterial)
float4 _MainTex_ST;
float4 _Color;
float _GroundHeight;
float _EnableClip;
float _ClipSoftness;
CBUFFER_END
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
Varyings vert(Attributes input)
{
Varyings output;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_TRANSFER_INSTANCE_ID(input, output);
output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
output.uv = TRANSFORM_TEX(input.uv, _MainTex);
output.color = input.color;
output.worldPos = TransformObjectToWorld(input.positionOS.xyz);
return output;
}
half4 frag(Varyings input) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(input);
// 采样纹理
half4 texColor = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv);
half4 color = texColor * input.color * _Color;
// 地面裁剪逻辑
if (_EnableClip > 0.5)
{
float worldY = input.worldPos.y;
float distanceToGround = worldY - _GroundHeight;
// 如果在地面以下,裁剪掉
if (distanceToGround < 0)
{
// 使用柔和边缘
float alpha = smoothstep(0, _ClipSoftness, distanceToGround);
color.a *= alpha;
// 如果Alpha太小直接丢弃
if (color.a < 0.01)
{
discard;
}
}
}
return color;
}
ENDHLSL
}
// 阴影Pass
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
ZWrite On
ZTest LEqual
Cull Off
HLSLPROGRAM
#pragma vertex ShadowPassVertex
#pragma fragment ShadowPassFragment
#pragma multi_compile_instancing
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
float2 uv : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
float3 worldPos : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
CBUFFER_START(UnityPerMaterial)
float4 _MainTex_ST;
float4 _Color;
float _GroundHeight;
float _EnableClip;
float _ClipSoftness;
float _CastShadow;
float _ShadowOpacity;
float _ShadowOffset;
float4 _ShadowColor;
CBUFFER_END
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
Varyings ShadowPassVertex(Attributes input)
{
Varyings output;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_TRANSFER_INSTANCE_ID(input, output);
// URP阴影Pass需要使用特殊的矩阵变换
float3 positionWS = TransformObjectToWorld(input.positionOS.xyz);
float4 positionCS = TransformWorldToHClip(positionWS);
// 应用阴影偏移(向光源方向偏移)
#if UNITY_REVERSED_Z
positionCS.z -= unity_LightData.z;
#else
positionCS.z += unity_LightData.z;
#endif
output.positionCS = positionCS;
output.uv = TRANSFORM_TEX(input.uv, _MainTex);
output.worldPos = positionWS;
return output;
}
half4 ShadowPassFragment(Varyings input) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(input);
// 如果不投射阴影,直接丢弃
if (_CastShadow < 0.5)
{
discard;
}
// 采样纹理获取Alpha
half4 texColor = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv);
half alpha = texColor.a * _Color.a;
// 地面裁剪逻辑与主Pass相同
if (_EnableClip > 0.5)
{
float worldY = input.worldPos.y;
float distanceToGround = worldY - _GroundHeight;
if (distanceToGround < 0)
{
float clipAlpha = smoothstep(0, _ClipSoftness, distanceToGround);
alpha *= clipAlpha;
if (alpha < 0.01)
{
discard;
}
}
}
// 如果Alpha太低不投射阴影
if (alpha < 0.1)
{
discard;
}
// 输出阴影URP阴影格式
return half4(0, 0, 0, alpha * _ShadowOpacity);
}
ENDHLSL
}
}
FallBack "Sprites/Default"
}