deferringRender

1)延迟渲染

延迟渲染是相对于正向渲染而提出的。

正向渲染是指我们按照标准的pipeline流程,逐顶点的依次着色渲染。在场景中我们根据所有光源照亮一个物体,之后再渲染下一个物体。

而延迟渲染则是我们首先生成图像的位置,法线,颜色等信息,然后在后处理阶段在执行光照的方式。所谓的延迟就是我们先生成图像,再执行光照。而正向渲染则是通过对每个物体进行光照计算,然后再生成图像。

2)为何要进行延迟渲染

这是因为在早期的GPU设备上。当我们的场景中存在大量的物体,这些物体在位置上可能存在重叠,也就是说一些物体最终无法显示在图像上(或者部分区域无法显示在图像上)。而我们在fragment shader中执行光照的计算是针对物体的,这就会导致大量不显示的图元依旧被计算了,消耗了GPU的性能与功耗。其实这也不算啥,但是当我们的场景中的光源有很多时,这个浪费就很恐怖了,因此才提出了延迟渲染,我们先生成图像中的像素,然后再对像素进行光照,这样就不浪费算力了。

可是有人会说,我们不是有depth-test么?在光照之前执行以下depth-test不就行了。这是因为标准的GPU渲染流程中,depth-test在fragment shader的后面执行,所以很遗憾。

3)GPU架构的改进

其实延迟渲染并不好,它需要更多的buffer来储存信息。当前的GPU,一般都是将depth-test提前,或者有个叫early-z的技术。也就是说把depth-test提前到fragment shader前面执行,这样就解决了上面的问题,因此延迟渲染的重要性就大大降低了,但是这个思想还是很重要的。

4)延迟渲染的做法

用一张图就可以表示:
deferringRender1
图中的内容如下所示:
deferringRender2

也就是说我们要在vertexBuffer中生成position,normal,albedo,sepcular等图像,然后将其输出到g-buffer中。在fragment shader中读取gbuffer中的信息,然后执行光照计算,得到最终的输出结果。

5)延迟渲染的未来

上面说到我们引入了early-z等技术,那么是不是延迟渲染就没啥用了呢?原则上是的,但是随着移动端的兴起,延迟渲染又迎来了春天。因为当前的移动端的GPU大多数采用的是TDBR的架构,这个架构天然的要求延迟渲染。世道真的是无可奈何啊。