欢迎光临散文网 会员登陆 & 注册

【入门精要】008-透明效果

2023-03-31 15:26 作者:柴郡笔记  | 我要投稿

透明度有两种实现方法:一种是透明度测试(AlphaTest),一种是透明度混合(AlphaBlending)。

透明度测试:如果片元不满足条件,则该片元就会被舍弃。被舍弃的片元不会对颜色缓冲有任何影响。如果满足条件,则会按照普通的不透明物体来进行渲染。透明度测试不需要关闭深度写入。其结果要么完全透明,要么完全不透明。

透明度混合:实现半透明效果,需关闭深度写入。他会将当前的半透明片元与颜色缓冲中的颜色值做混合,得到新颜色。由于关闭了深度写入,需格外注意渲染顺序。虽然关闭了深度写入,但这不代表我们关闭了深度测试。当深度测试检测不透明物体在半透明物体之前,则会掩盖半透明物体。


为什么渲染顺序很重要?

因为如果我们的半透明物体被提前渲染,则会导致深度测试时,半透明物体后的不透明物体因深度测试通过而覆盖渲染结果,造成渲染的排序错误。

半透明物体,要从后往前渲染,先渲染远的,再渲染近的。



渲染顺序:

unity为了解决相关问题提供了渲染队列(Render Queue),我们可以在Tag中添加Queue标签决定物体的渲染队列。

Background(1000):在其他物体之前渲染,多用于背景。

Geometry(2000):默认渲染队列,不透明物体渲染队列。

AlphaTest(2450):需要进行透明度测试的物体的队列。

Transparent(3000):在小于3000的队列渲染完成后,从后往前渲染,用于半透明物体。

Overlay(4000):用于实现一些叠加效果,需要在最后渲染的物体的队列。


因此,如果我们想实现半透明效果,应该为shader添加如下条件:

Tags{ "Queue" = "AlphaTest" } 或 Tags{ "Queue" = "Transparent" }

ZWrite Off(关闭深度写入):关闭深度写入,用于半透明物体,常写于Pass通道内。



透明度测试:

透明度测试是CG语言中的一个函数(Clip),如果传入Clip的值中(如:float4)任何一个值小于0,则舍弃该片元,用于片元着色器中。

首先声明标签:

Tags {

            "Queue" = "AlphaTest"               //设置渲染队列

            "RenderType"="TransparentCutout"    //对应改为Cutout

            "ForceNoShaderCasting"="True"       //关闭阴影投射

            "IgnoreProjector"="True"            //不响应投射器

}

然后在Pass通道内声明标签

Tags { "LightMode"="ForwardBase" }

最后在片元着色器中添加方法:

clip(“传入的值”);

设置好合适的Fallback,即可。



透明度混合:

透明度混合和透明度测试不一样,两者可共存。

透明度混合可以实现真正的透明度效果。他会使用当前片元的透明度作混合因子,与颜色缓冲中的颜色值做混合,得到结果。但由于我们关闭了深度写入,这使得我们要格外注意排序。


为了实现效果,unity为我们提供了一个混合命令:Blend。

Blend的工作就是把当前自身的颜色与颜色缓冲中的颜色作混合,混合的方法由相应指令决定。

举例:

BlendOp Add                                        //混合方法为Add

Blend SrcAlpha OneMinusSrcAlpha    //(当前源的透明度乘以当前源颜色) 与 (一减当前源的透明度的值乘以颜色缓冲后的值) 相加


实现方法:

添加Tag:

Tags {

            "Queue" = "Transparent"             //修改渲染顺序

            "RenderType"="Transparent"          //对应改为Transparent

            "ForceNoShaderCasting"="True"       //关闭阴影投射

            "IgnoreProjector"="True"            //不响应投射器

}

关闭深度写入:

ZWrite Off

Pass通道内添加混合模式:

BlendOp [“计算方法”]

Blend [“当前源颜色”] [“深度缓冲颜色”]

设置好合适的Fallback,即可。



开启深度写入的半透明效果:

由于关闭了深度写入,造成了模型渲染排序的错误。如何解决这个问题呢?

我们可以用两个Pass通道来解决。

第一个Pass通道不渲染,开启深度写入,只输出深度值。

第二个Pass通道关闭深度写入,正常渲染。

实现方法:

Pass{

    ZWrite On                    //开启深度写入

    ColorMask 0                //当ColorMask为0时,不输出任何颜色

}

Pass{

    同透明度混合;

}

设置好合适的Fallback,完成。



ShaderLab混合命令:

之前提到了Blend,现在我们来详细了解一下。

混合是如何实现的:当片元着色器产生一个颜色时,可以选择与颜色缓存中的颜色进行混合,得到混合后的结果。

Blend [源颜色x混合因子] [颜色缓存x混合因子]

命令:

Blend SrcFactor DstFactor:开启混合,源颜色乘以SrcFactor,颜色缓存乘以DstFactor,两者默认相加。

Blend SrcFactor DstFactor,SrcFactorA DstFactorA开启混合,源颜色(rgb)乘以SrcFactor,颜色缓存(rgb)乘以DstFactor,两者默认相加。源颜色透明度(a)乘以SrcFactorA,颜色缓存透明度(a)乘以DstFactorA,两者默认相加。两者区别只是将颜色通道和透明度分开计算。


混合参数(Blend):

One:因子为1

Zero:因子为0

SrcColor:因子为源颜色值,RGB通道与A通道分开混合。

SrcAlpha:因子为源颜色的A通道。

DstColor:因子为目标颜色值,RGB通道与A通道分开混合。

DstAlpha:因子为目标颜色的A通道。

OneMinusSrcColor:因子为(1-源颜色值),RGB通道与A通道分开混合。

OneMinusSrcAlpha:因子为1-源颜色的A通道

OneMinusDstColor:因子为(1-目标颜色值),RGB通道与A通道分开混合。

OneMinusDstAlpha:因子为(1-目标颜色的A通道)。


混合操作(BlendOp):

Add:将混合后的源颜色和目标颜色相加

Sub:将混合后的源颜色减去目标颜色

RevSub:将混合后的目标颜色减去源颜色

Min:取二者最小(逐分量比较取值)

Max:取二者最大(逐分量比较取值)


常见混合类型:

Blend SrcAlpha OneMinusSrcAlpha:正常的透明度混合

Blend OneMinusDstColor One:柔和相加

Blend DstColor Zero:正片叠底

Blend DstColor SrcColor:两倍相乘

Blend One One(BlendOp Min):变暗

Blend One One(BlendOp Max):变亮

Blend OneMinusDstColor One:滤色

Blend One OneMinusSrcColor:滤色

Blend One One:线性减淡



双面渲染:

大多渲染情况下,我们只渲染了物体正面。而想要渲染反面,或者两面都渲染,则需要使用Cull指令来完成。

Cull有三种指令:Front(剔除正面)、Back(剔除反面)、Off(不剔除)

使用方法同Blend,如

Cull Off

即可。




【入门精要】008-透明效果的评论 (共 条)

分享到微博请遵守国家法律