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

上一篇讲到了把GI系统从Deferred Rendering框架中分离出来,以降低耦合度。本篇会涉及到一个共享shadow map、提高性能的改进。

多视口的改进

多视口的特性是KlayGE 4.2引入的。Deferred rendering layer支持通过多个视口生成多个渲染结果,可以用于分屏、反射、缩略图等情景。原先每个视口都是完全独立渲染的,互相不共享任何东西。实际上spot light和point light的shadow map是view independent的,不会因为视点不同而改变,就应该在视口间共享。

于是开发团队成员李渊完成了这个任务,把shadow map的生成提前到所有视口的G-Buffer之前。也就是说,原先的流水线是:

for each view port:
   generate g-buffer.

   for each shadowed light:
      generate shadow map or reflective shadow map.

      shadowing from shadow map.
      lighting.

   shading.

经过修改的流水线是:

for each shadowed light:
   generate shadow map or reflective shadow map.

for each view port:
   generate g-buffer.

   for each shadowed light:
      shadowing from shadow map.
      lighting.

   shading.

这么一来,通过在视口间共享shadow map,减少了重复生成shadow map的开销。需要注意的是,cascaded shadow map是view dependent的,需要在G-Buffer之后生成。

重构Update

在完成了上述修改后,多名团队成员以及论坛上的lcbiotech都提到了DeferredRenderingLayer::Update函数过长的问题,已经影响到了理解和维护,重构迫在眉睫。经过一番重构,那个函数被分解成了几十个小函数,每个负责做一件事情。Update函数本身则只是定义了流水线,实际执行都是通过调用那些小函数完成的。在对外的接口完全不变的情况下,流程变清晰很多。

在重构Update的过程中,我对现在的渲染流程产生了新的想法。于是进一步发展出了下一篇会讲的,在不增加存储开销的情况下支持透明物体。