透明效果
作者:互联网
透明效果
开启半透明时,每个片元追加一个属性 —— 透明度 (Alpha)
两种方法实现透明效果
-
使用透明度测试(Alpha Test)这种方法无法达到真正的半透明效果
-
透明度混合(Alpha Blending)
名词解释
-
深度缓冲(depth buffer or z-buffer)
在实时渲染中,用于解决可见性的问题。使用深度缓冲,就不用关心不透明物体的渲染顺序
它的基本思想是:当渲染一个片元时,需要把它的深度值和已经存在于深度缓冲中的值进行比较(如果开启了深度测试),如果它的值距离摄像机 更远,那么说明这个片元不应该被渲染到屏幕上(有物体挡住了它);否则,这个片元应该覆盖掉此时颜色缓冲中的像素值,并把它的深度值更新 到深度缓冲中(如果开启了深度写入)。
-
透明度测试(霸道极端)
根据透明度来舍弃片元,只要一个片元的透明度不满足条件(通常是小于某个阈值),该片元被直接舍弃。这样的结果会很极端,要么完全透明, 要么完全不透明。
-
透明度混合(真正的半透明)
使用当前片元的透明度作为混合因子,与已经存储在颜色缓冲的颜色进行混合,得到新颜色。
注意透明度混合要关闭深度写入(z-write),因此要非常小心物体的渲染顺序。但是深度测试还是在的,当使用透明度混合渲染一个片元时,还是 会比较它的深度值与当前深度缓冲中的深度值,如果它的深度值距离摄像机更远,那么就不会再进行混合操作。深度缓冲是只读的
8.1 为什么渲染顺序很重要
为什么我们要关闭z-write?
如果不关闭z-write,深度测试时判断结果半透明的表面以后的面深度都比表面远,结果直接 表面以外的面 都被剔除了,我们无法透过半透明便面看 到后面的东西了。简单来说我们要使半透明的物体不影响其他物体的深度判断。
为什么渲染顺序很重要?
情况一
如果先渲染B,再渲染A,则B先写入颜色和深度缓冲(不透明物体还是有z-write的),接着渲染A,透明物体仍然会进行深度测试,因此我们发现 和B相比A距离摄像机更近,因此,我们会使用A的透明度来和颜色缓冲中的B的颜色进行混合,得到正确的半透明效果。
如果先渲染A,在渲染B,则A先写入颜色缓冲,接着渲染B,B进行深度测试后,认为他就是第一个物体(A没有z-write)且B没有透明度测试,不 会和A混合啥颜色,他就直接覆盖了A的颜色,结果看起来B在A的前面。
情况二
如果先渲染B,再渲染A,B先正常写入颜色缓冲,然后A再和颜色缓冲的B混合得到正确的颜色
如果先渲染A,在渲染B,则A先写入颜色缓冲,结果B与颜色缓冲的A混合的颜色不对,
可以将AB想做PS里的两个半透明图层,上下层的顺序对画面的影响
渲染引擎常见的渲染顺序
- 先渲染所有不透明的物体,并开启它们的深度测试和深度写入。
- 把半透明物体按它们距离摄像机的远近进行排序,然后按照从后往前的顺序渲染这些半透明物体,并开启它们的深度测试,但关闭深度写入。
穿帮情况:
深度缓冲中的值其实是像素级别的,即每个像素有一个深度值,但是现在我们对单个物体级别进行排序,这意味着排序结果是,要么物体A全部在B前面渲染,要么A全部在B后面渲染。但如果存在循环重叠的情况,那么使用这种方法就永远无法得到正确的结果。
这里的问题是:如何排序?对于图8.4中的情况,选择哪个深度值都会得到错误的结果,我们的排序结果总是A在B的前面,但实
际上A有一部分被B遮挡了。这也意味着,一旦选定了一种判断方式后,在某些情况下半透明物体之间一定会出现错误的遮挡问题。这种问题的解决方法通常也是分割网格。
8.2 Unity Shader的渲染顺序
名称 | 队列索引号 | 描述 |
---|---|---|
Background | 1000 | 这个渲染队列会在任何其他队列之前被渲染,我们通常使用该队列来渲染那些需要绘制在背景上的物体 |
Geometry | 2000 | 默认的渲染队列,大多数物体都使用这个队列。不透明物体使用这个队列 |
AlphaTest | 2450 | 需要透明度测试的物体使用这个队列。在Unity 5中它从Geometry队列中被单独分出来,这是因为在所有不透明物体渲染之后再渲染它们会更加高效 |
Transparent | 3000 | 这个队列中的物体会在所有Geometry和AlphaTest物体渲染后,再按从后往前的顺序进行渲染。任何使用了透明度混合(例如关闭了深度写入的Shader)的物体都应该使用该队列 |
Overlay | 4000 | 该队列用于实现一些叠加效果。任何需要在最后渲染的物体都应该使用该队列 |
8.3 透明度测试
- 在片元shader中使用clip函数来进行透明度测试。clip是Cg语言的一个函数,定义如下
- 参数 :裁剪时使用的标量或矢量条件。
- 描述 :如果给定参数的任何一个分量是负数,就会舍弃当前像素的输出颜色。
$$
void~~Clip ~( float~4 x )
$$
8.4 透明度混合
语义 | 描述 |
---|---|
Blend Off | 关闭混合 |
Blend SrcFactor DstFactor | 开启混合并设置混合因子, 源颜色(该片元产生的颜色)会乘以SrcFactor,而目标颜色(已经存在于颜色缓冲的颜色)会乘以DstFactor,然后将两者相加再存入颜色缓冲中 |
BlendOp BlendOperation | 并非是把源颜色和目标颜色简单相加后混合,而是使用BlendOperation对它们进行其他操作 |
-
只有在开启了混合后,设置片元的透明通道才有意义
-
记得在pass中使用Blend命令
设置SrcFactor=SrcAlpha,DstFactor=OnrMinusSrcAlpha时的颜色计算公式如下
$$
Dstcolor_{new}=SrcAlpha\times SrcColor +(1-SrcAlpha) \times DstColor_{old}
$$
8.5 开启深度写入的半透明效果
Z-write的打开与否
半透明的物体设置Z-write off 后算是真正意义上的半透明(我现在是这么想),但是事实上这样的显示效果并不太好,我们会看到物体内部多余的东西
我们可以打开深度写入变成伪半透明,这样的话我们只可以透过它看到不透明物体,半透明物体会被完全剔除确实也是个问题,不过我现在还不会解决(doge)(会了下一集人家就讲了)
8.6 ShaderLab的混合命令
各种混合等式
8.7 双面渲染的透明效果
两个pass,背面的pass要先写(保证渲染的顺序)
标签:透明,颜色,效果,渲染,缓冲,物体,深度,半透明 来源: https://www.cnblogs.com/jiangliblog/p/15853590.html