Unity URP Shader 修改深度让人物不再被地面遮挡
- 前言
- 项目
- 场景布置
- 代码编写
前言
遇到一个小问题,人物总是被XY
平面的地面遮挡,于是在Shader
中改一下深度输出,这样地面再也不会挡住人物了。
项目
场景布置
将人物放到XY
平面的后面
配置Shader
参数
代码编写
Shader "Unlit/DepTest"
{
Properties
{
[MainColor] _BaseColor("Base Color", Color) = (1, 1, 1, 1)
[MainTexture] _MainTex("Main Texture", 2D) = "white" {}
_DepthBias("Depth Bias", Float) = 0.01 // 深度偏移,确保在XY平面之前渲染
}
SubShader
{
Tags { "RenderType" = "Transparent" "RenderQueue"="Transparent" "RenderPipeline" = "UniversalPipeline" }
Pass
{
Name "UnlitPass"
Tags { "LightMode" = "UniversalForward" }
Cull Off // 双面渲染
Blend SrcAlpha OneMinusSrcAlpha // 混合模式,支持透明度
ZTest LEqual // 深度测试,确保当前像素深度小于等于之前的像素才渲染
// ZTest Always // 深度测试设置为Always,确保总是渲染
ZWrite Off // 关闭深度写入,防止影响其他物体的深度排序
// ZWrite On
ColorMask RGBA // 允许写入颜色缓冲区的所有通道 (红、绿、蓝、透明)
HLSLPROGRAM
#pragma vertex vert // 定义顶点着色器方法名称
#pragma fragment frag // 定义片元着色器方法名称
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
struct Attributes
{
float4 positionOS : POSITION; // 顶点位置,模型空间坐标
float2 uv : TEXCOORD0; // 顶点纹理坐标
};
struct Varyings
{
float4 positionHCS : SV_POSITION; // 输出到片元着色器的顶点位置,裁剪空间坐标
float2 uv : TEXCOORD0; // 传递给片元着色器的纹理坐标
float depth : TEXCOORD1; // 存储深度值,供片元着色器使用
};
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
CBUFFER_START(UnityPerMaterial)
half4 _BaseColor;
float4 _MainTex_ST;
float _DepthBias; // 深度偏移量
CBUFFER_END
Varyings vert(Attributes IN)
{
Varyings OUT;
// 获取对象在世界空间中的位置
float4 worldPosition = mul(GetObjectToWorldMatrix(), IN.positionOS);
// 将世界空间坐标转换为裁剪空间坐标
OUT.positionHCS = TransformWorldToHClip(worldPosition);
// 传递纹理坐标
OUT.uv = TRANSFORM_TEX(IN.uv, _MainTex);
// 计算并存储深度值
OUT.depth = OUT.positionHCS.z / OUT.positionHCS.w;
return OUT;
}
struct FragmentOutput
{
half4 color : SV_Target; // 最终颜色输出
float depth : SV_Depth; // 深度输出
};
FragmentOutput frag(Varyings IN)
{
FragmentOutput OUT;
OUT.color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, IN.uv) * _BaseColor;
OUT.depth = IN.depth - _DepthBias; // 深度偏移
return OUT;
}
ENDHLSL
}
}
FallBack "Unlit/Texture"
}