前向渲染(Forward Rendering)和延迟渲染(Deferred Rendering)

前向渲染(Forward Rendering)

它的实现最贴合我们的思维逻辑,当我们渲染模型时,只需要关心画模型然后直接处理光照,让它自己去做深度测试,最后深度测试过的都显示在屏幕上。

1、对要渲染的物体进行遍历渲染出shadowmap

2、再遍历一遍上面要渲染的物体,根据shadowmap对每一个物体的像素进行光照计算

优点

很明显,就是简单,并且可以针对每个物体指定它的材质,因为每个物体都是独立渲染的。

缺点

1、由于依赖深度测试,如果物体是乱序的,可能会出现大量的像素光照计算都是浪费的。

2、不能支持光源数量较多的情况。所以我们一般有两种做法来处理多光源的情况,一种是一遍渲染多个光源,所有光照运算都在一个着色器中进行,因为一个着色器有指令数量的限制。另一种是多遍渲染多个光源,意思就是每多一盏灯,就多渲染一次模型,所以性能消耗也比较大。

延迟渲染(Deferred Rendering)

它的做法是在第一遍渲染模型的时候,不进行光照计算,直接将位置、法线深度、颜色等存到G-Buffer。很多人第一次接触G-Buffer这个名词都是一头雾水,其实就是创建多张和屏幕一样大的纹理,然后每张纹理的像素值分别用来存上面提到的这些数据。也就是说一次渲染,需要输出多张纹理,这跟前向渲染是不同的, 前向渲染只渲染到一张纹理上,这张纹理最终会渲染在屏幕上。而延迟渲染这多张纹理都不是最终结果,可以理解为只是用几张贴图存储一堆中间数据。

第二遍再根据G-Buffer的数据,进行光照计算,写入帧缓冲区

优点

处理完G-Buffer之后,其实每盏灯光就可以通过一个Drawcall的消耗去执行光照计算。第一遍处理完的G-Buffer是深度测试过的,不像前向渲染一样,有那么多光照计算的浪费。

缺点

1、最终的光照计算方式只能是一种,也就是其他文章提到的只允许一个材质,因为最终计算的时候只剩下一堆数据,不知道它们分别是谁的,所以只能无差别对待。而前向渲染可以每个模型一种计算方式。

2、不允许使用透明物件,因为最终G-Buffer只剩一个像素了,无法进行混合。不过可以在第二遍渲染完之后,用前向渲染的方式渲染透明物体。

3、不支持抗锯齿,意味着不能用MSAA,不过可以用FXAA进行后期处理

4、有些硬件不支持MRT(Multiple Render Targets 多重纹理目标),也就是输出到多张纹理上实现G-Buffer的功能

5、G-Buffer需要比较大的带宽,有些硬件没不具备这个能力

6、由于光照计算本身性能消耗也不低,延迟渲染的光照计算其实等同于在做一次全屏的后处理,后处理其实对手机来说过于昂贵。而如果只有一盏灯的话,其实前向渲染省了这次额外的渲染。所以移动设备上延迟渲染的性能会比前向渲染的性能要差一些

Forward+ Shading

最近刷知乎的时候看到一篇文章结合了前向渲染和延迟渲染的优势,为前向渲染无法同时使用多灯光的问题提供了解决的方案。https://zhuanlan.zhihu.com/p/85615283

 

题外话

其实一开始接触光照模型、渲染路径、PBR啥的总被一些名词折腾得很懵逼,这里简单提一下,标准光照模型和PBR都属于光照模型,在前向渲染中主要负责像素着色器里的光照计算,而延迟渲染则负责第二遍对整个G-Buffer进行光照计算。渲染路径指的是整个渲染流程,先后干什么事,例如前向渲染和延迟渲染可以是渲染路径里的一个环节,还可以有其他的,例如渲染UI或者清屏之类的

你可能感兴趣的:(图形)