[UnityShader学习笔记] UnityShader中透明效果及相关原理(深度缓存、深度测试、深度写入和面片剔除等)

前言

  • 此文章为笔者学习《UnityShader入门精要》书籍的学习笔记,因此大部分内容均出自此书;
  • 笔者尽量进行总结,并会补充相关的知识例如片元、深度缓存、帧缓存的概念;
  • 在一些地方如光照模型的计算不会过多涉及,因此需要有一定的光照和图形学基础;
  • 此文章目前没有提供源码。如果你需要源码,请在评论区或者私信我,我会准备源码后放在github上!

渲染顺序

  • 注意:
  • 这部分内容属于理论部分,如果你只想知道如何在UnityShader中实现透明效果,此部分可以省略;
  • 但是为了更好的理解透明效果的原理,笔者认为这部分理论知识是需要掌握的;

如果你曾经使用过绘图软件进行绘画,同一个图层下,如果使用不透明的画笔进行绘画,那么下一笔绘制的肯定会覆盖掉前一笔绘制过的东西。由此可见,绘制顺序在绘制中起到的作用。

图形学中,也需要考虑这个绘制顺序,不然即使A物体在B物体的后面,如果按照先绘制B后绘制A的话,仍然会出现A遮挡住B的情况出现。如下图所示,AB两个物体,会有两种渲染顺序,且它们的渲染结果是截然不同的:
渲染AB两个物体,有两种渲染顺序
然而在渲染管线中,一般是不需要刻意注意绘制顺序的,这是因为GPU中有一个称为深度缓存(z-buffer) 的东西。

深度缓存、深度测试和深度写入

o 深度缓存

所谓深度缓存,和帧缓存(frame-buffer) 一样,是一个二维纹素矩阵,只是上面存储的不是RGBA颜色值,而只存储了一个深度值(z)。

这个深度缓存是为了深度测试(depth-test)服务的,深度测试是片元测试中的其中一部分,发生在渲染管线中片元着色器后面(感兴趣可以了解渲染管线,了解顶点渲染到输出的过程会对图形学的学习有很大帮助)。

o 深度测试

所谓深度测试,简单来说就是将当前需要绘制的内容,和已经绘制的内容的深度进行比较——如果需要绘制的离得更远,就丢弃,否则不丢弃。
假设z越小表示离得越近,将当前要渲染的片元的深度值 Zsrc,与深度缓存中相同位置的深度值 Zdst进行比较,如果:

  • Zsrc > Zdst,说明当前片元更远,被遮挡,即片元被丢弃
  • Zsrc <= Zdst,说明当前偏远更近,可以被渲染

(至于什么是片元,会在后面进行补充)

o 深度写入

最后就是深度写入,顾名思义,就是将一个片元的深度值写入深度缓存当中。
至于写入的时机,一般就是这个片元通过深度测试的时候,也就是说当此片元离得更近时,会将此片元的深度值更新到深度缓存当中。

片元(补充部分)

渲染管线中,当顶点经过图元装配、光栅化以后,得到的内容称为片元(fragment)。片元最后会成为像素,但不是全部的片元都会成为像素,换一句话说,片元有可能会被丢弃。
至于为什么会被丢弃,前面已经说过其中一个原因了,那就是没有通过深度测试。当然深度测试只是片元测试中的一个部分,其他的还有透明度测试等。如下图所示:
片元测试示意图

透明物体对渲染顺序的影响

虽然前面说过,因为有神奇的深度缓存,因此一般来说不用考虑渲染顺序的问题,因为片元会根据自己的深度和已有的深度进行比较后自动丢弃,但这是针对不透明物体而言的。一旦场景中有不透明物体,那么深度缓存、深度测试就“不灵”了。

为什么这么说呢?我们可以进行场景假设,模拟一下实际的渲染。

不透明物体+半透明物体

假设场景中,有物体A和B,且假定A在B的前面,其中A是半透明物体B是不透明物体,如下图所示(其中灰色条纹是背景图,方便效果显式):

在这里插入图片描述


  • 如果我们先渲染B,后渲染A,那么流程是这样的(假定深度缓存为空):
  1. 渲染不透明物体B,进行深度测试;
  2. 由于此时深度缓存为空,所有的片元都通过了深度测试,可以进行渲染、同时将B的深度写入深度缓存中;
  3. 渲染半透明物体A,进行深度测试,从深度缓存中没有发现比自己更靠近的物体,因此A可以进行渲染;

那么渲染结果如下图所示,这样绘制的结果(先绘制不透明物体,后绘制透明物体)是正确的:
在这里插入图片描述


  • 如果我们先渲染A,后渲染B,那么流程是这样的(假定深度缓存为空):
  1. 渲染半透明物体A,进行深度测试;
  2. 由于此使深度缓存为空,所有的片元都通过了深度测试,可以进行渲染,同时将A的深度写入深度缓存中;
  3. 渲染不透明物体B,进行深度测试,从深度缓存中发现已经有比自己更近的物体(即A),因此丢弃物体B;

(*注: 这里的“物体B”丢弃并不完全准确,准确来说是丢弃被A遮挡的B的部分)

那么渲染结果如下图所示。渲染结果是错误的,因为被A遮挡的B的部分完全消失了:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值