ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

透明效果

2022-01-28 19:34:58  阅读:222  来源: 互联网

标签:透明 颜色 效果 渲染 缓冲 物体 深度 半透明


透明效果

开启半透明时,每个片元追加一个属性 —— 透明度 (Alpha)

两种方法实现透明效果

  • 使用透明度测试(Alpha Test)这种方法无法达到真正的半透明效果

  • 透明度混合(Alpha Blending)

名词解释

  • 深度缓冲(depth buffer or z-buffer)

​ 在实时渲染中,用于解决可见性的问题。使用深度缓冲,就不用关心不透明物体的渲染顺序

​ 它的基本思想是:当渲染一个片元时,需要把它的深度值和已经存在于深度缓冲中的值进行比较(如果开启了深度测试),如果它的值距离摄像机 更远,那么说明这个片元不应该被渲染到屏幕上(有物体挡住了它);否则,这个片元应该覆盖掉此时颜色缓冲中的像素值,并把它的深度值更新 到深度缓冲中(如果开启了深度写入)。

  • 透明度测试(霸道极端)

​ 根据透明度来舍弃片元,只要一个片元的透明度不满足条件(通常是小于某个阈值),该片元被直接舍弃。这样的结果会很极端,要么完全透明, 要么完全不透明。

  • 透明度混合(真正的半透明)

​ 使用当前片元的透明度作为混合因子,与已经存储在颜色缓冲的颜色进行混合,得到新颜色。

​ 注意透明度混合要关闭深度写入(z-write),因此要非常小心物体的渲染顺序。但是深度测试还是在的,当使用透明度混合渲染一个片元时,还是 会比较它的深度值与当前深度缓冲中的深度值,如果它的深度值距离摄像机更远,那么就不会再进行混合操作。深度缓冲是只读的

8.1 为什么渲染顺序很重要

为什么我们要关闭z-write?

​ 如果不关闭z-write,深度测试时判断结果半透明的表面以后的面深度都比表面远,结果直接 表面以外的面 都被剔除了,我们无法透过半透明便面看 到后面的东西了。简单来说我们要使半透明的物体不影响其他物体的深度判断。

为什么渲染顺序很重要?

情况一

image-20220122223317831

​ 如果先渲染B,再渲染A,则B先写入颜色和深度缓冲(不透明物体还是有z-write的),接着渲染A,透明物体仍然会进行深度测试,因此我们发现 和B相比A距离摄像机更近,因此,我们会使用A的透明度来和颜色缓冲中的B的颜色进行混合,得到正确的半透明效果。

​ 如果先渲染A,在渲染B,则A先写入颜色缓冲,接着渲染B,B进行深度测试后,认为他就是第一个物体(A没有z-write)且B没有透明度测试,不 会和A混合啥颜色,他就直接覆盖了A的颜色,结果看起来B在A的前面。

情况二

image-20220122231906623

​ 如果先渲染B,再渲染A,B先正常写入颜色缓冲,然后A再和颜色缓冲的B混合得到正确的颜色

​ 如果先渲染A,在渲染B,则A先写入颜色缓冲,结果B与颜色缓冲的A混合的颜色不对,

可以将AB想做PS里的两个半透明图层,上下层的顺序对画面的影响

image-20220122233936938

image-20220122234004563

渲染引擎常见的渲染顺序

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

穿帮情况:

image-20220123001408619

深度缓冲中的值其实是像素级别的,即每个像素有一个深度值,但是现在我们对单个物体级别进行排序,这意味着排序结果是,要么物体A全部在B前面渲染,要么A全部在B后面渲染。但如果存在循环重叠的情况,那么使用这种方法就永远无法得到正确的结果。

image-20220123002153193

这里的问题是:如何排序?对于图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 后算是真正意义上的半透明(我现在是这么想),但是事实上这样的显示效果并不太好,我们会看到物体内部多余的东西

image-20220123215553716

我们可以打开深度写入变成伪半透明,这样的话我们只可以透过它看到不透明物体,半透明物体会被完全剔除确实也是个问题,不过我现在还不会解决(doge)(会了下一集人家就讲了)

image-20220123220827897

8.6 ShaderLab的混合命令

各种混合等式

8.7 双面渲染的透明效果

两个pass,背面的pass要先写(保证渲染的顺序)

标签:透明,颜色,效果,渲染,缓冲,物体,深度,半透明
来源: https://www.cnblogs.com/jiangliblog/p/15853590.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有