Transparency Rendering 半透明物体Blending

Transparency Rendering 半透明物体Blending

顺序有关Blending

现存的应用较为广泛的半透明绘制方法是这样的: 首先将所有的不透明物体(Opaque objects)绘制到屏幕上(或者延迟渲染体系中绘制到GBuffer里),然后将剩余的所有半透明物体排个序,然后GPU按照排好的顺序渲染并混合(Blend)。注:通常绘制Opaque objects的时候会将Blending关闭以避免不正确的渲染结果,但是如果将置\(a_{s} = 1\),下述的Over也可渲染不透明物体,但是这么做会带来而外的性能消耗。

目前针对于半透明的主要的Blend方法有两种: overunder.

Over顺序Blending

Over渲染的方法是:下一个半透明物体绘制到当前现有场景的上面.这种渲染方法所代表的渲染顺序是从远到近绘制(Back to Front), 这种顺序对应的Blend公式是:

\[c_{out} = a_{s}c_{s} + (1 - a_{s})c_{d} \]

其中:

\(c_{s}\)是当前正在绘制的半透明物体的Color(称为Source)

\(a_{s}\)是半透明的物体的Alpha值

\(c_d\)是在混合(Blending)之前的Color(称为Destination)

\(c_{out}\)是因为将半透明物体放置于现有场景之上导致的混合后的最终像素颜色.

现实世界中被遮蔽的物体亮度通常较暗(如,蓝色物体在红色半透明下面通常呈现出较深的颜色),上述的渲染方法恰好能渲染出这种效果。

Additive Blending

这种方法不会使被半透明物体遮蔽的物体亮度变暗,常用于像闪电等的特效渲染。其Blend公式为:

\[c_{out} = a_{s}c_{s} + c_{d} \]

Under顺序Blending

将Over顺序Blend公式的source和destination对调即可得到新的公式:

\[c_{out} = a_{d}c_{d} + (1 - a_{d})a_{s}c_{s} \]

与Over渲染方法相反,这种半透明渲染方法是将下一个半透明物体绘制到现有场景的下面,这也就导致了从近到远的渲染顺序。注意到在调换完渲染顺序后,因为其Destination并非不透明物体而需要一个Alpha值,因此在这种情况下需要手动维护Destination的Alpha值(即\(a_d\))。

Z-Buffer

一般在半透明渲染的时候要将Z-Depth Replacement关掉。这样的话,绘制半透明物体的时候依旧会进行z-buffer test, 但不会将生成的z value写回z-buffer。

如果保持Z-buffer replacement开启的话,就会导致被遮挡的半透明物体被剔除掉而完全不会绘制,也就不会有后面的混合输出了。

顺序无关Blending

顺序有关的半透明渲染方法有以下两个主要问题:

  1. 我们需要在提交Draw Call前对需要绘制的半透明物体排序,常按照它们重心距镜头的距离排序。这种如果有两个半透明物体有交叉部分,那么渲染出的结果就不对。
  2. 在实际渲染前排序通常会带来额外的性能消耗。

OIT, Order Indepentent Transparency, 翻译成中文叫顺序无关渲染(半透明物体)。

OIT中一个很著名的算法叫做Deep Peeling算法,中文叫深度剥离算法。这个算法主要是用来解决顺序有关绘制中的物体交叉问题,通过按照z轴从近到远“层层剥离”式绘制半透明物体来正确渲染有重叠(相交)部分的两个或多个半透明物体。

这个算法的实现需要两个独立的Z-Buffer和多遍Pass绘制。每一遍Pass会比较这次绘制的结果和上一次绘制的结果的Z-Value,如果深度值相同,说明这次绘制的像素在上一次渲染已经存在,或者说,在Z轴上是属于“同一层”的像素。在这种情况下,通过丢弃此次渲染结果能够达到“剥离上一层”的效果,最后将各层渲染结果混合起来得到最终图像。

A Buffer

Refer to this: A-Buffer

posted @ 2023-02-20 14:49  鸟临窗语报天晴  阅读(144)  评论(0编辑  收藏  举报