【Unity Shader】半透明特效在RenderTexture上的显示问题

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

  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值