1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
| Shader "Custom/URP/SliceEffect" { Properties { _MainTex ("主纹理", 2D) = "white" {} _BaseColor ("基础颜色", Color) = (1, 1, 1, 1)
// 切割平面:xyz = 法线方向,w = 平面偏移 // 平面方程:dot(worldPos, _SlicePlane.xyz) + _SlicePlane.w < 0 的区域被切除 _SlicePlane ("切割平面 (xyz=法线, w=偏移)", Vector) = (0, 1, 0, -1)
// 切面颜色和宽度 _SliceColor ("切面颜色", Color) = (1, 0.3, 0.1, 1) _SliceWidth ("切面宽度", Range(0.001, 0.1)) = 0.02 _SmoothBlend ("平滑过渡宽度", Range(0, 0.1)) = 0.01
// 溶解效果(配合噪波纹理) _NoiseTex ("溶解噪波", 2D) = "white" {} _DissolveAmount ("溶解程度", Range(0, 1)) = 0.0 _DissolveEdgeWidth ("溶解边缘宽度", Range(0, 0.1)) = 0.02 _DissolveEdgeColor ("溶解边缘颜色", Color) = (1, 0.5, 0, 1) }
SubShader { Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
// Pass 1:正面渲染 Pass { Name "ForwardLit" Tags { "LightMode" = "UniversalForward" }
// 只渲染正面(切割后可以看到背面的切面颜色) Cull Back
HLSLPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE #pragma multi_compile _ _SHADOWS_SOFT
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); TEXTURE2D(_NoiseTex); SAMPLER(sampler_NoiseTex);
CBUFFER_START(UnityPerMaterial) float4 _MainTex_ST; float4 _BaseColor; float4 _SlicePlane; float4 _SliceColor; float _SliceWidth; float _SmoothBlend; float4 _NoiseTex_ST; float _DissolveAmount; float _DissolveEdgeWidth; float4 _DissolveEdgeColor; CBUFFER_END
struct Attributes { float4 positionOS : POSITION; float3 normalOS : NORMAL; float2 uv : TEXCOORD0; };
struct Varyings { float4 positionHCS : SV_POSITION; float3 worldPos : TEXCOORD0; float3 worldNormal : TEXCOORD1; float2 uv : TEXCOORD2; float4 shadowCoord : TEXCOORD3; };
Varyings vert(Attributes input) { Varyings output; output.positionHCS = TransformObjectToHClip(input.positionOS.xyz); output.worldPos = TransformObjectToWorld(input.positionOS.xyz); output.worldNormal = TransformObjectToWorldNormal(input.normalOS); output.uv = TRANSFORM_TEX(input.uv, _MainTex);
// 计算阴影坐标(需要 _MAIN_LIGHT_SHADOWS 宏) VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz); output.shadowCoord = GetShadowCoord(vertexInput); return output; }
half4 frag(Varyings input) : SV_Target { float3 worldPos = input.worldPos;
// ---- 1. 切割平面剔除 ---- // 计算当前点到切割平面的有符号距离 float sliceDist = dot(worldPos, _SlicePlane.xyz) + _SlicePlane.w;
// 超出切割范围(平面正侧):直接剔除片段 if (sliceDist > _SliceWidth) discard;
// ---- 2. 溶解效果 ---- float2 noiseUV = TRANSFORM_TEX(input.uv, _NoiseTex); float noiseVal = SAMPLE_TEXTURE2D(_NoiseTex, sampler_NoiseTex, noiseUV).r;
// 噪波值 < 溶解程度时剔除 if (noiseVal < _DissolveAmount) discard;
// ---- 3. 切面颜色区域(靠近切割平面的区域显示切面颜色)---- bool isSliceFace = (sliceDist > -_SliceWidth && sliceDist <= _SliceWidth);
// 溶解边缘发光 bool isDissolveEdge = (noiseVal < _DissolveAmount + _DissolveEdgeWidth);
// ---- 4. 标准 URP 漫反射光照 ---- Light mainLight = GetMainLight(input.shadowCoord); float3 normal = normalize(input.worldNormal); float NdotL = saturate(dot(normal, mainLight.direction)); float3 diffuse = mainLight.color * NdotL * mainLight.shadowAttenuation;
// 基础颜色 float3 albedo = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv).rgb; albedo *= _BaseColor.rgb;
// 切面区域覆盖颜色 if (isSliceFace) { // 切面内部亮色显示(使用切面颜色) float faceFactor = smoothstep(_SliceWidth, 0.0, abs(sliceDist)); albedo = lerp(albedo, _SliceColor.rgb, faceFactor); }
// 溶解边缘发光叠加 if (isDissolveEdge) { float edgeFactor = 1.0 - (noiseVal - _DissolveAmount) / _DissolveEdgeWidth; albedo = lerp(albedo, _DissolveEdgeColor.rgb * 3.0, edgeFactor); }
float3 ambient = SampleSH(normal) * 0.5; float3 finalColor = albedo * (ambient + diffuse);
return half4(finalColor, 1.0); } ENDHLSL }
// Pass 2:背面(切面)渲染 Pass { Name "SliceFaceBack" Tags { "LightMode" = "UniversalForwardOnly" }
Cull Front // 只渲染背面,用于显示切面内部
HLSLPROGRAM #pragma vertex vert #pragma fragment fragBack #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
CBUFFER_START(UnityPerMaterial) float4 _SlicePlane; float _SliceWidth; float4 _SliceColor; float _DissolveAmount; CBUFFER_END
struct Attributes { float4 positionOS : POSITION; float2 uv : TEXCOORD0; }; struct Varyings { float4 positionHCS : SV_POSITION; float3 worldPos : TEXCOORD0; };
TEXTURE2D(_NoiseTex); SAMPLER(sampler_NoiseTex); float4 _NoiseTex_ST;
Varyings vert(Attributes input) { Varyings output; output.positionHCS = TransformObjectToHClip(input.positionOS.xyz); output.worldPos = TransformObjectToWorld(input.positionOS.xyz); return output; }
half4 fragBack(Varyings input) : SV_Target { // 背面也需要切割和溶解剔除(保持一致) float sliceDist = dot(input.worldPos, _SlicePlane.xyz) + _SlicePlane.w; if (sliceDist > 0.0) discard;
// 切面颜色(带轻微漫射感) return _SliceColor; } ENDHLSL }
// Shadow Caster Pass(支持投射阴影) Pass { Name "ShadowCaster" Tags { "LightMode" = "ShadowCaster" } ColorMask 0 Cull Back
HLSLPROGRAM #pragma vertex shadowVert #pragma fragment shadowFrag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
CBUFFER_START(UnityPerMaterial) float4 _SlicePlane; float _SliceWidth; float _DissolveAmount; CBUFFER_END
struct Attributes { float4 positionOS : POSITION; float3 normalOS : NORMAL; }; struct Varyings { float4 positionHCS : SV_POSITION; float3 worldPos : TEXCOORD0; };
TEXTURE2D(_NoiseTex); SAMPLER(sampler_NoiseTex); float4 _NoiseTex_ST;
Varyings shadowVert(Attributes input) { Varyings output; output.worldPos = TransformObjectToWorld(input.positionOS.xyz); // 使用 URP 的阴影偏移(防止 shadow acne) float3 lightDir = _MainLightPosition.xyz; output.positionHCS = TransformWorldToHClip( ApplyShadowBias(output.worldPos, TransformObjectToWorldNormal(input.normalOS), lightDir) ); return output; }
half4 shadowFrag(Varyings input) : SV_Target { float sliceDist = dot(input.worldPos, _SlicePlane.xyz) + _SlicePlane.w; if (sliceDist > _SliceWidth) discard; return 0; } ENDHLSL } } }
|