Soft Particles核心原理是通过比较粒子深度与场景深度差值动态调节透明度:差值越小,粒子越贴近遮挡物,alpha越低;需启用_SoftParticlesEnabled宏、开启Depth Texture,并用SampleSceneDepth等正确对齐深度值。

Soft Particles 的核心原理是什么
软粒子不是靠贴图 alpha 渐变实现的,而是让粒子在靠近不透明物体表面时自动淡出。关键依据是:粒子片段的 depth 与当前帧深度缓冲中对应位置的 depth 差值。差值越小,说明粒子越贴近遮挡物,透明度就越高。
URP 中 ParticlesUnlit 的软粒子开关在哪
URP 粒子着色器默认不启用软粒子,必须手动开启。它依赖两个条件同时满足:
-
_SoftParticlesEnabled宏需在 ShaderLab 的Keywords或材质 Inspector 中启用(URP 14+ 后该 keyword 默认未定义) - 场景必须启用了
Depth Texture(URP Asset → Rendering → “Depth Texture” 打钩) - 着色器中需调用
SoftParticleFactor函数,传入世界空间顶点位置和摄像机参数 ——ParticlesUnlit的 HLSL 片元函数里已有该逻辑,但只在宏启用时编译进 shader
漏掉任一条件,alpha 都不会根据深度衰减,只会按贴图原始 alpha 显示硬边。
自定义软粒子时 depth 值怎么对齐
最容易出错的是世界空间深度与深度缓冲采样坐标的 mismatch。常见问题包括:
- 用
ComputeScreenPos得到的screenPos是齐次裁剪空间坐标,直接用tex2D(_CameraDepthTexture, screenPos.xy)会采样错误 —— 必须先做screenPos.xy /= screenPos.w归一化 - 深度纹理存储的是非线性 Z(Z-buffer),而你计算的粒子世界深度是线性值,必须用
LinearEyeDepth对采样结果解码,再与Linear01Depth转换后的粒子深度比较 - URP 下推荐统一用
SampleSceneDepth(封装了正确采样 + 解码),而非手写tex2D+LinearEyeDepth
示例关键片段(HLSL):
float4 screenPos = ComputeScreenPos(v.vertex); float sceneDepth = SampleSceneDepth(screenPos.xy); float particleDepth = Linear01Depth(mul(unity_MatrixVP, v.vertex).z, _ZBufferParams); float softFactor = saturate((sceneDepth - particleDepth) * _SoftParticleScale); o.alpha *= softFactor;
为什么软粒子在正交相机下失效
因为 SampleSceneDepth 在正交投影下返回的深度值范围与透视投影不同,_ZBufferParams 的缩放系数不匹配。URP 默认只对透视相机启用深度纹理的软粒子适配逻辑。
若必须在正交模式下使用软粒子,需手动绕过 SampleSceneDepth,改用 GetOrthographicViewDepth + 自定义深度比较,或在 URP Asset 中勾选 “Support Orthographic Camera Depth Texture”(部分 URP 版本需手动 patch)。
这个细节常被忽略,直到粒子在 UI 或 2D 场景中突然变硬才意识到。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











