Unity Shader 增加透明支持
文章目录
介绍
项目中使用的一部分 Shader 是 Cutout 类型的,功能是透明度在一定阈值以下会隐藏,否则显示,处于显示隐藏的二值状态。
但是有需求是物体在遮挡视线时变为半透明。
最初的方案是动态切换材质,然后设置透明度,但是进行性能分析的时候发现创建新材质极其耗费性能。因此尝试为原来的 Shader 增加透明度功能。
方案
尝试一
使用纹理自带的 alpha 值作为裁剪的依据,然后使用材质指定 _Color 属性的 alpha 值作为透明值。
需要修改混合模式以使用 alpha 值显示
Blend SrcAlpha OneMinusSrcAlpha
Shader 需要修改为以下属性以保证与其他半透明 Shader 正确排序
Tags{ "RenderType" = "TransparentCutout" "Queue" = "Transparent"
需要使用编辑器脚本查找 wall 层级使用的所有 Shader 名字,也需要修改所有材质的 RenderQueue 为 Shader 默认值,因为上面修改了 Shader 的默认 RenderQueue 值。
RenderType 在相机使用 public void RenderWithShader(Shader shader, string replacementTag); 时才启用,用于按照规则替换不同 Shader 显示。
尝试二
在实际测试时发现这样修改的 Shader 会遮挡特效的显示,而原来的换材质的方案并不会这样。检查原来默认的 Transparent/Diffuse Shader
是一个 Surface Shader,需要点击 Compile and show code 按钮查看编译后的代码:
|
|
可以看到其中与现有 Shader 最重要的区别就是 ZWrite Off
,并未写入深度值。经过测试,在 Cutout Shader 中增加 ZWrite Off
后,与场景内的各种半透明物体(特效、人物头顶高亮指引等等)都显示正确了。
但是如果 RenderQueue 重置为默认的 AlphaTest 2450 了。那么显示又不正确了。
所以正确做法与换材质 Shader 相同,将需要修改的属性作为动态属性在脚本中设置,因此只有在变透明的时候才需要关闭 ZWrite Off
,同时设置 RenderQueue = Transparent
3000 以便与特效混合正确显示。
Shader 默认关闭了混合 Blend Off Blend Off: Turn off blending (this is the default) 如果在运行时动态修改,需要动态使用 BlendMode 替代 Blend Off
|
|
Unity - Manual: ShaderLab: Blending
总结
最终需要修改的属性
- Alpha 混合模式
- ZWrite 深度缓存开关
- RenderQueue 渲染顺序
这些属性的默认值都要保持原样不变,只在遮挡相机时使用脚本进行动态修改。
缺陷
由于在运行时修改了 ZWrite,在开启 ZWrite 的瞬间会出现画面的跳变,这是无法修改的问题,原理上的限制决定了渲染结果会出现不同。
文章作者 狂飙
初次发布 2019-09-01 23:13:10 +0800
永久链接 https://networm.me/2019/09/01/unity-shader-transparent-support/