文章

UnityShade入门精要(4·透明测试与混合)

透明效果

对于不透明物体,有两种方法可以保证正确绘制遮挡关系:

  • 不启用深度测试,确保渲染顺序:从后往前渲染,因为每次渲染都会更新颜色缓冲区
  • 启用深度测试,深度值比深度缓冲更小的会通过测试
透明效果

但是想要实现透明效果,就不那么简单了,在 Unity 中,我们通常使用两种方法来实现透明效果:

透明度测试(AlphaTest):只要一个片元的透明度不满足条件(比如小于某个阈值),那么它对应的片元就会被舍弃,否则,就会按照普通的不透明物体的处理方式来处理它,它产生的效果也很极端,要么完全透明,要么完全不透明,

透明度混合 (AlphaBlending):关闭深度写入,不关闭深度测试,根据alpha与已经存储在颜色缓冲中的颜色值进行混合(透明通道 (Alpha Channel)作为混合因子)

对于透明物体,有两种方法可以保证正确绘制遮挡关系:(要注意渲染顺序)

  • 开启了深度测试和深度写入,先渲染不透明物体,启用透明度测试,来渲染透明物体
  • 开启了深度测试和深度写入,先渲染不透明物体,关闭深度写入,不关闭深度测试(只读模式),启用透明度混合,从后往前的顺序,来渲染透明物体并混合颜色

先渲染不透明物体?保证正确的遮挡关系,否则颜色就会被不透明物体更新掉(透明物体在前方,会导致错误的渲染结果)

关闭深度写入?如果透明物体更近,颜色缓冲的颜色就会被剔除,也就无法透过半透明表面看到后面的物体了(颜色不能正确混合)

启用深度测试?保证对于位于不透明物体后面的透明物体不会执行颜色混合

从后往前渲染透明物体?混合结果会不同,因此半透明物体之间也是要符合一定的渲染顺序的

渲染队列

unity中是通过渲染队列来实现物体与其他物体之间的渲染顺序的

SubShader 的 Queue 标签Tags {} 来决定我们的物体(此shader应用的物体)将归于哪个渲染队列。 Unity 在内部使用一系列整数索引来表示每个渲染队列,且索引号越小表示越早被渲染

1732981311763

ZWrite Off用千关闭深度写入

透明度测试实例

CG函数: void clip(float4 x); void clip(float3 x); void clip(float2 x); void clip(floatl x); void clip(float x);如果给定参数的任何一个分量是负数(减去指定值后),就会舍弃当前片段(不会写入深度和颜色缓冲)

Properties属性_Cutoff用来控制透明度测试的阈值

RenderType 标签通常被用于着色器替换功能。IgnorePrnjeccor标签为true这意味着这个 Shader不会受到投影器 (Projectors) 的影响

透明度混合实例

不要忘了禁用深度写入,并且为了进行混合,我们需要使用 Unity 提供的blend混合命令,是否开启混合,并设置混合状态

混合命令如下:

1732981352923

输出时a分量设置为uniform的源混合因子

开启深度写入

关闭了深度写入,就无法对模型(本身有遮挡关系)进行像素级别的深度排序,即模型本身依旧会颜色混合,不会遮挡剔除

正确的渲染效果应该是,在模型内部之间不会有任何真正的半透明效果,但有模型与它后面的背景混合的效果,实现方式如下:

第一个 Pass (渲染)开启深度写入,但不输出颜色,它的目的仅仅是为了把该模型的深度值写入深度缓冲中;

第二个 Pass 进行正常的透明度混合,由于上一个 Pass已经得到了逐像素的正确的深度信息(后面三角图元不会通过深度测试,不会绘制,前面的片段会保留执行透明混合),该 Pass_就可以按照像素级别的深度排序结果进行透明渲染。

但这种方法的缺点在于,多使用一个 Pass 会对性能造成一定的影响。

shaderlab 的混合命令

实际上,混合还有很多其他用处,不仅仅是用于透明度混合

当进行混合时,我们有时也需要使用两个混合等式: 一个用于混合RGB通道, 一个用于混合 A通道,使用不同的混合因子

混合因子如下:

1732981387629

BlendOp BlendOperation混合操作命令,可以改变如何将src和dst混合最终颜色

通过混合因子和混合操作的组合,可以得到类似Pbotoshop混合模式中的混合效果(例如正片叠底等)

双面渲染的透明效果

在现实生活中, 如果一个物体是透明的, 意味着我们不仅可以透过它看到其他物体的样子,也可以看到它内部的结构。这是因为,默认情况下渲染引擎剔除了物体背面

使用 CulJ指令来控制需要剔除哪个面的渲染图元,如果设翌为 Off, 就会关闭剔除功能

透明度测试只需要加入Cull off就可以

但是透明度混合就要麻烦些,是因为它关闭了深度写入,这时必须从后往前的渲染顺序,才能得到正确的结果,如果仅仅关闭剔除,就无法保证同一个物体的正面和背面图元的渲染顺序,

那么解决方案,就是在第一个pass渲染背面,然后渲染正面,那么们可以保证背面总是在正面被渲染之前渲染, 从而可以保证正确的深度渲染关系。

透明度测试,透明度混合,双面渲染:

1732981411549

本文由作者按照 CC BY 4.0 进行授权
本页总访问量