0x00现象
下图可见,模型的翅膀部分有黑色的矩形。
游戏项目中,需要模型显示在UI上,这里采用了RenderTexture的方案,可以参考使用RenderTexture实现3D模型与UI的组合显示。
RenderCamera Background(0,0,0,0)
0x01寻找原因
首先查看RenderTexture的绘制是否正常
由于粒子特效常常会对alpha进行处理,加之模型不透明部分显示没有问题,于是查看alpha通道,有惊喜:
可以看到,翅膀的外围还有一大一小两个矩形,从alpha通道的情况来看,应该是介于[0, 1]之间。
最终与UI混合的图片
我们期望的效果是翅膀的外围(特效部分)并不需要显示矩形。翻译一下, 我们只想要特效alpha通道为1的部分,并不想要特效alpha通道介于[0, 1]之间的部分。
Unity对半透明物体的渲染,依赖于Alpha Blend。
为什么一个物体会看起来是“半透明”的。在OpenGL中,这是通过Blending技术实现的。我们都知道一个叫“Color Buffer”的东西,这个可以理解成我们会在屏幕上看到的各种颜色。
对于不透明物体来说,经过Fragment Shader处理后的fragment会和当前在Color Buffer中的fragment进行深度比较,结果要么覆盖它要么就被舍弃。
但对于半透明物体,由于它关闭了深度缓存,因此不会进行深度比较,而是通过混合系数和当前Color Buffer中的颜色进行混合,使物体看起来好像透过它看到了其他物体。
参见:【Unity Shaders】Alpha Test和Alpha Blending
问题出现在显示的部分,显示的问题无非就是颜色的问题,即RGBA。那么来分析一下,从渲染特效,渲染模型,渲染到RenderTexture,其中有两次Alpha Blend:
第一次Alpha Blend
Particle & Background ==> RenderTexture
Cull Off
Lighting Off
ZWrite Off
Blend SrcAlpha One // Blend 1
ColorMask RGBA
第二次Alpha Blend
RenderTexture & UI ==> FinalColor
Cull Off
Lighting Off
ZWrite Off
Blend One OneMinusSrcAlpha //Blend 2
ColorMask RGBA
0x02 解决方案
如果想去除翅膀周围的黑色方块,可以在第一次Alpha Blend的时候ColorMask不输出Alpha通道的方式。
将
ColorMask RGBA
修改为
ColorMask RGB
ColorMask是什么?
ColorMask
ColorMask RGB | A | 0 | any combination of R, G, B, A
Set color channel writing mask. Writing ColorMask 0 turns off rendering to all color channels. Default mode is writing to all channels (RGBA), but for some special effects you might want to leave certain channels unmodified, or disable color writes completely.
When using multiple render target (MRT) rendering, it is possible to set up different color masks for each render target, by adding index (0–7) at the end. For example,
ColorMask RGB 3
would make render target #3 write only to RGB channels.
参见:ShaderLab: Pass
为什么这样修改可以?
由于Blend One OneMinusSrcAlpha的计算方式,当输出的alpha = 1时(ColorMask RGBA),DstColor就消失了。而当输出的alpha = 0时(ColorMask RGB),没有写入alpha通道,所以alpha从camera background处获得,取得0,会保留DstColor。
为什么ColorMask不会影响Blend?
可以看到ColorMask(Writing Masking)是在Blend之后,而写入Framebuffer之前执行
https://www.khronos.org/opengl/wiki/Write_Mask
还有一种方案:
在特效后面增加一层背景,宣雨松有一篇文章介绍这种方案UGUI研究院之在UI上使用RenderTexture显示模型+AlphaBlend特效(二十五)
0x03 最终效果
如图,可见特效显示正常,后面的背景也显示正常。
参考资料
https://www.cnblogs.com/jietian331/p/10675265.html
https://blog.uwa4d.com/archives/Severe_MOBA.html