前向渲染(Forward)延迟渲染(deferred)
假设有1个光源和1000个具有光照反射的三角形在view coordinate沿着z轴正方形延伸摆放,法线与z轴平行,即所有三角形xy全相同,只有z不同,但是这里增加一个条件:摆放顺序是无序的。
从屏幕上其实你只能看到一个带光照的三角形,其他的都被挡住了。
那么前向渲染会这样做:
- 遍历1000个三角形片元
- 进行深度检测,没通过的忽略
- 通过检测的进行光照计算
- 更新帧缓冲区
- 返回1继续直到遍历结束
由于上面的要求是无序摆放,那么如果运气差一点 1000次深度检测全部都能通过,那么光照会计算1000次,可是因为只能看见最上面的,那么999次光照计算都是多余的。如果光源越多第三步的重复次数越多,整体复杂度也会越高。
延迟渲染引入了GBuffer,它会这样做:
- 遍历1000个三角形片元
- 进行深度检测,没通过的忽略
- 通过的将坐标、光照等信息写入GBuffer
- 返回1继续直到遍历结束
- 遍历Gbuffer
- 利用Gbuffer中的数据进行光照计算
- 更新帧缓冲区
- 返回5继续直到遍历结束
可以看出前向渲染和延迟渲染的不同点在于多了一个Gbuffer,且关于Gbuffer的编写也是一个难点。
如果用大O表示法来表示两种光照模型(Light Model):
前向渲染,几何对象数量 * 灯光数量
延迟渲染,屏幕分辨率可视的片元 * 灯光数量
可以将延迟渲染( Deferred Rendering)理解为先将所有物体都先绘制到屏幕空间的缓冲(即G-buffer,Geometric Buffer,几何缓冲区)中,再逐光源对该缓冲进行着色的过程,从而避免了因计算被深度测试丢弃的⽚元的着色而产⽣的不必要的开销。也就是说延迟渲染基本思想是,先执行深度测试,再进行着色计算,将本来在物空 间(三维空间)进行光照计算放到了像空间(二维空间)进行处理。
延迟渲染利:
解决了前向渲染不能使用大量灯光的问题。
延迟渲染弊:
不能使用半透明对象。
需要显卡支持多目标渲染(Multiple Render Targets,多目标渲染在后面进行解释)。
没有抗锯齿。
阴影依赖于光照的数量。
关于多目标渲染Multiple Render Targets,在微软的文档中是这么解释的:
“在只调用一次draw call的情况下渲染多个表面。”
这里用UE4来举个例子(UE4使用的就是延迟渲染技术,所以可以看到他的半透明对象显示方式是有问题的):
这里有一个物件,可以看到左上角那一排当前默认的显示模式是lit,也就是光照模式,这应该是我们看到的一个渲染完成的mesh的最终效果,现在我们切换一下lit,显示如下:
如此一来可以看到如下显示:
看到周围那一圈的小图了吗,每一张图都是一个target,这些target都是不带光照信息的。所以多目标的目标target指的就是这些渲染成单个的图像,如basecolor,roughness,scenedepth等等,多目标渲染就是将当前场景中(当前相机的可视范围内)的objects渲染成一张张不同的图像信息,将每一张的信息写入各自的buffer中(例如basecolor就写在basecolor buffer中)。最后,这些buffers和场景中的每一个灯光进行最终合成,输出的就是最终显示效果的图像了。
参考链接:
http://m.elecfans.com/article/651416.html