Forward Rendering VS Deferred Rendering
现代渲染管线:
现代渲染管线允许我们发送代码到显卡,去改变像素点的信息,像是使它们变得凹凸不平(使用法线贴图)或增加反射等等。
该代码采用几何形状,顶点着色器(Vertex Shader)和片段着色器(Fragment Shader)的形式,它们实质上改变了显卡渲染对象的方式。
前向渲染:
正向渲染是大多数引擎使用的标准,即用型的渲染技术。 我们为图形卡提供几何图形,将其投影并将其分解为顶点,然后将其转换并拆分为片段或像素,这些片段或像素将在传递到屏幕之前得到最终的渲染处理。
它是相当线性的,并且每次将每个几何图形通过管道一次以生成最终图像。
延时渲染:
顾名思义,在延迟渲染中,渲染将延迟一点,直到所有几何图形都通过管道为止。 然后通过在底端应用着色器来生成最终图像。延迟光照是对延迟渲染的一种修改,它通过在场景中使用更多的pass来减小G缓冲区的大小。
光照计算:
在标准的前向渲染管线中,必须对可见场景中的每个顶点和可见场景中的每个片段执行光照计算。假如一个场景中有100个几何体,每个几何体有1000个顶点,那么我们大概会有100000个多边形。显卡可以很好的处理这些多边形。但如果这些多边形被发送到Fragment Shader时,就会存在昂贵的光照计算。
开发者必须为屏幕上每个多边形的每个可见片段执行昂贵的照明计算,无论它是否重叠或被另一个多边形的片段隐藏。假如屏幕分辨率为1024768,那么将有近800000像素要被绘制(O(几何体数量光的数量)),我们很轻松得便会获得过百万的片段操作每一帧。同时,很多片段甚至不会被画进屏幕(因为被深度测试移除了),那么它们的光照计算便被浪费了。
延迟渲染是一种非常神奇的方法,它减少了对象的数量,特别是减少了总片段数,并在屏幕上的像素上执行了照明计算,从而使用了分辨率大小而不是总片段数。(O(屏幕分辨率 * 光照数量)),这样无论场景中有多少几何体都不会影响时间复杂度了
为什么延时渲染可以做到呢?因为它使用多个渲染目标将每个几何图形(但不带阴影)渲染到多个屏幕空间缓冲区。 特别是深度,法线和颜色都写入了单独的缓冲区。 然后将这些缓冲区组合起来,为每个光提供足够的信息以照亮像素。通过知道像素有多远及其法线向量,我们可以将像素的颜色与光线结合起来以生成最终的渲染。
如何抉择:
简而言之,如果使用许多动态光源,则应该使用延时渲染。
但是,延时渲染也有弊端:
• 需要高宽带,因为要发送大量缓冲区
• 不能使用透明对象
• 没有抗锯齿
• 阴影仍然被光的数量决定,延时渲染同样也没有解决阴影的复杂度问题