UnityShader入门精要_要点整理_透明效果

这一章要点内容比较多。

透明度测试与透明度混合

透明度测试

它采用一种“霸道极端”的机制,只要一个片元的透明度不满足条件(通常是小于某个阈值),那么它对应的片元就会被舍弃,不做任何处理。否则就会按照普通不透明的物体的处理方式来处理它。它产生的效果是极端的,某个片元要么完全透明(看不见),要么完全不透明。

透明度混合

这种方法可以得到真正的半透明效果。他会使用当前片元的透明度作为混合因子,与已经存储在颜色缓冲中的颜色进行混合,得到新的颜色。但是,透明度混合需要关闭深度写入,这使得我们要非常小心物体的渲染顺序。需要注意的是,透明度混合只关闭了深度写入,但是没有关闭深度测试。这意味着,当透明度混合渲染一个片元时,还是会比较它的深度值与当前深度缓冲中的深度值,如果它的深度值距离摄像机更远,那么就不会再进行混合操作。这一点决定了,当一个不透明物体出现在一个透明物体的前面,而我们先渲染了不透明物体,他仍然可以正常的遮挡住透明物体。也就是说,对于透明度混合来说,深度缓冲是只读的。


透明度混合与深度写入和渲染顺序的关系


使用透明度混合完成的半透明效果,要特别注意渲染顺序和深度写入带来的影响。如果不关闭深度写入,可能会导致半透明物体被不透明物体错误的遮挡(覆盖)。而如果两个透明物体之间的渲染顺序错误,则会造成反向混合(与配置的混合因子公式有关)得到错误的颜色。

所以一般情况下书上推荐的渲染顺序是

  1. 先渲染所有不透明物体,并开启它们的深度测试和深度写入。
  2. 把半透明物体按它们距离摄像机的远近进行排序,然后按照从后往前的顺序渲染这些半透明物体,并开启它们的深度测试,但关闭深度写入。

然而,当物体循环重叠或者物体深度有交叉时,我们无法进行合适的排序。

循环重叠的半透明物体总是无法得到正确的半透明效果 render_order_3.png-15.3kB

深度有交叉,无法使用哪个深度对物体进行排序。红色点分别标明了网格上距离摄像机最近的点、最远的点以及网格中点 render_order_2.png-30.4kB

这时我们需要

  • 拆分网格成多个不重叠的子物体
  • 或者尽量建模时就不要让物体有深度交叉(如尽量不要有凹面)。
  • 或者让透明通道更柔和,让异常穿插看起来不那么明显。
  • 也可以使用开启深度写入的半透明效果,来近似模拟物体的半透明。

 

下面更详细的解释一些细节。

透明度混合为什么要关闭深度写入?

对 于 透 明 度 混 合 技 术 , 需 要 关 闭 深 度 写 入 , 此 时 我 们 就 需 要 小 心 处 理 透 明 物 体 的渲 染 顺 序 。 那 么 , 我 们 为 什 么 要 关 闭 深 度 写 入 呢 ? 如 果 不 关 闭 深 度 写 入 , 一 个 半 透 明 表 面 背 后 的表 面 本 来 是 可 以 透 过 它 被 我 们 看 到 的 , 但 由 于 深 度 测 试 时 判 断 结 果 是 该 半 透 明 表 面 距 离 摄 像 机 更近 , 导 致 后 面 的 表 面 将 会 被 剔 除 , 我 们 也 就 无 法 透 过 半 透 明 表 面 看 到 后 面 的 物 体 了 。 但 是 , 我 们由 此 就 破 坏 了 深 度 缓 冲 的 工 作 机 制 , 而 这 是 一 个 非 常 非 常 非 常 ( 重 要 的 事 情 要 讲 3 遍 ) 糟 糕 的 事情 , 尽 管 我 们 不 得 不 这 样 做 。 关 闭 深 度 写 入 导 致 渲 染 顺 序 将 变 得 非 常 重 要 。

这里书上有个图解过程写的比较详细,贴上来看看。

一个半透明一个不透明物体的渲染顺序与深度写入带来的影响

图8.1 场景中有两个物体,其中A(黄色)是半透明物体,B(紫色)是不透明物体

render_order_0.png-10.7kB

透明度混合时渲染顺序带来的影响

这里书上有个图解过程写的比较详细,贴上来看看

两个半透明物体的渲染顺序之间的影响 。

图8.2 场景中有两个物体,其中A和B都是半透明物体 

render_order_1.png-10.5kB

不开启深度写入的半透明混合效果

transparent_order_wrong.png-94.7kB

代码中比较关键的主要就是一些,tag设置,常见的透明度因子看,TODO!!表格那一篇链接。AlphaBlend_BothSide.shader

//
//省略代码........ 完整代码请看https://download.csdn.net/download/lanazyit/13586309
//
    //TODO 书中的解释没有完全看懂,只记得透明度混合一般要设置这三个Tag,以后再详细查解
        Tags{
            "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"
        }
        pass{
            Tags {"LightMode" = "ForwardBase"}
            //要注意透明度混合主要生效的是在这里
            ZWrite Off//注意 要关闭深度的写入
            //这里的意思片元产生的颜色*片元自己的透明度 + 颜色缓冲中的颜色 * (1 - 当前片元的透明度)
            Blend SrcAlpha OneMinusSrcAlpha //OneMinusSrcAlpha 意思是 1-SrcAlpha
//
//省略代码........ 完整代码请看https://download.csdn.net/download/lanazyit/13586309
//

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

与不开启深度写入的操作区别是,这里使用两个Pass来渲染模型:第一个Pass开启深度写入,但不输出颜色,它的目的仅仅是为了把该模型的深度值写入深度缓冲中;第二个Pass进行正常的透明度混合,由于上一个Pass已经得到了逐像素的正确的深度信息,该Pass 就可以按照像素级别的深度排序结果进行透明渲染。但这种方法的缺点在于,多使用一个Pass 会对性能造成一定的影响。

开启深度写入,与未开启深度写入透明效果的对比。

未开启的无法处理重叠的问题。transparent_order_wrong.png-94.7kB开启的可以处理重叠问题,但是重叠的部分变成不透明的了。alpha_blend_zwrite.png-87.9kB

 

代码,注意使用了两个pass,但是一个pass比较简单,只输出深度值,颜色值被ColorMask过滤。AlphaBlendZWrite.shader


//省略代码........ 完整代码请看https://download.csdn.net/download/lanazyit/13586309
//TODO 书中的解释没有完全看懂,只记得透明度混合一般要设置这三个Tag,以后再详细查解
        Tags{
            "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"
        }
        //在前面加一个Pass,开启深度缓存,只写入深度缓存,不输出任何颜色
        pass{
            //TODO 这里需要再复习一下深度写入,深度缓存,颜色合并的概念与区别
            //后续解释 这些概念主要在2.3.8节,可以复习查阅
            //深度测试是用来判断片元跟相机距离远近的,一把情况下较远的片元会被舍弃
            //深度写入是指当一个新的开启了深度测试的片元距离相机更近时,是否使用它的深度值覆盖掉原有的深度缓存。
            //颜色合并是指当深度测试等一系列测试都通过时,是否与原有的颜色缓存中的颜色混合,若不混合则直接覆盖,一般也是透明效果才用得到混合。
            //TODO 最后,需要解释一下为什么写入深度值后,颜色合并就正确了呢?
            //后续解释 前面之所以出现颜色反复重叠的情况,是因为深度缓存中无任何透明片元的深度值,所以每当有颜色过来都会直接混合
            //,当这里写入了片元的深度值和颜色缓存后,如果其他片元想要在这里写入颜色缓存
            //,就必须先要与之前的片元进行深度比较,不会再出现直接混合的问题。
            ZWrite On
            //注释,ColorMask是用于设置颜色通道的掩码,可以为R、B、G、A的任何组合,当为0时,意味着不会输出任何颜色
            ColorMask 0
        }
        pass{
            Tags {"LightMode" = "ForwardBase"}
            //要注意透明度混合主要生效的是在这里
            ZWrite Off//注意 要关闭深度的写入
            //这里的意思片元产生的颜色*片元自己的透明度 + 颜色缓冲中的颜色 * (1 - 当前片元的透明度)
            Blend SrcAlpha OneMinusSrcAlpha //OneMinusSrcAlpha 意思是 1-SrcAlpha
//省略代码........ 完整代码请看https://download.csdn.net/download/lanazyit/13586309

双面渲染半透明混合效果

使用两个通道,一个渲染背面一个渲染正面,要注意,先渲染背面,再渲染正面才能得到合适的效果。对比一下两种情况下的效果。

alpha_blend.png-55.1kBalpha_blend_both_sided.png-66.2kB

代码,注意Cull设置。AlphaBlend_BothSide.shader

//省略代码........ 完整代码请看https://download.csdn.net/download/lanazyit/13586309
  //要注意,UnityShader的pass渲染是顺序执行的
        pass{
            Tags {"LightMode" = "ForwardBase"}
            //要注意,这里是裁剪掉Front所以是只渲染后面的
            Cull Front
            //要注意透明度混合主要生效的是在这里
            ZWrite Off//注意 要关闭深度的写入
            //这里的意思片元产生的颜色*片元自己的透明度 + 颜色缓冲中的颜色 * (1 - 当前片元的透明度)
            Blend SrcAlpha OneMinusSrcAlpha //OneMinusSrcAlpha 意思是 1-SrcAlpha

//省略代码........ 完整代码请看https://download.csdn.net/download/lanazyit/13586309
        pass{
            Tags {"LightMode" = "ForwardBase"}
            Cull Back
            //要注意透明度混合主要生效的是在这里
            ZWrite Off//注意 要关闭深度的写入
            //这里的意思片元产生的颜色*片元自己的透明度 + 颜色缓冲中的颜色 * (1 - 当前片元的透明度)
            Blend SrcAlpha OneMinusSrcAlpha //OneMinusSrcAlpha 意思是 1-SrcAlpha
//省略代码........ 完整代码请看https://download.csdn.net/download/lanazyit/13586309

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值