转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=1603

上文讲到了如何把信息挤入有限的G-Buffer,另一个在实际中面临的问题是如何渲染透明物体。

透明物体

游戏中透明物体是不可缺少的,对于Deferred Rendering来说,透明物体一直是痛苦的。常见的做法是在deferred rendering的场景之上用forward shading来单独渲染透明物体,但那样就意味着必须单独实现一整套forward shading的流水线。这对于维护和扩展都是很不利的,对性能也很有影响。

在KlayGE 4.0里,我用的方法被称为Deep G-Buffer。其基本过程是,把第一篇所描述的Deferred Rendering流水线复制三份,不透明的物体、透明物体的背面、透明物体的正面分别有自己独立的G-Buffer、lighting pass、shading pass和special shading pass。最后会生成三张shading的结果,再把它们按照alpha混合起来就可以了。

首先建立的是不透明物体的G-Buffer,跟原先一样:
Opaque objects's G-Buffer
细致的朋友可以发现,由于用了best fit for normals,G-Buffer里的normal看上去很有趣。

然后用把cull设置为front,只画透明物体的背面,存在第二个G-Buffer中。这里还需要用类似depth peeling的方法clip掉比不透明物体更远的pixel。因为不透明物体挡住了绝大部分pixel,透明物体的背面只剩下很少一部分:
Transparent object back face's G-Buffer

同样,我们可以在第三个G-Buffer存透明物体的正面:
Transparent object front face's G-Buffer

经过lighting pass、shading pass和special shading pass,就得到了不透明物体的shading:

透明物体背面的shading,几乎没有被照亮的:
Transparent object back face's shading

以及透明物体正面的shading:
Transparent object front face's shading

注意透明物体都会在special shading pass给出像素alpha值。接下来只要把它们混合起来,就可以得到我们想要的结果:
After blending

再来一张侧面图,可以看到由于光照方式一样,透明物体和不透明物体的光照能连续平滑地过渡。

Side view

本篇抛砖引玉地提出了在Deferred框架下渲染透明物体的一个方法,它能简单有效地解决问题。缺点是三倍的内存和带宽消耗。如果depth peeling的层数增加,内存和带宽的消耗还会增加。这里其实也可以借鉴其他order independent transparency的方法,来取代depth peeling分离G-Buffer。下篇文章将会分析KlayGE中的实时GI