Deferred Rendering(一)原理概述

假如有n盏灯,m个几何体
  • 传统的前向渲染:

    for each dynamic light
         for each mesh light intersects
             render mesh with lighting
    

    光照计算是O(n * m)复杂度的操作。假如几何体m1是被几何体m2挡住的(不考虑半透明的情况),那么在Z-Test阶段,m1对应的像素是被剔除掉的,因此m1对应的光照计算完全浪费掉

  • 延迟渲染:

    for each mesh 
        render mesh
    for each light
        render light 
    

    把几何体进行光照计算的信息渲染到RenderTarget上(经过m次渲染,最终保留下的必定是通过Z-Test的像素对应的信息); 接下来用一个pass,通过对RenderTarget采样提取光照信息,进行屏幕空间的光照计算(其复杂度为O(m + n)).

由上面可以看出,对于层次感强、复杂度高的场景,延迟渲染相比前向渲染能够极大提升效率。

回顾下典型光照计算:
  • surfaceColor = emissive + ambient + diffuse + specular
  • emissive = Ke
  • Ambient=Ka * globalAmbient
  • diffuse=Kd * lightcolor * max( N · L,0)
  • specular = Ks * lightColor * facing * (max(N · H, 0)) shininess

对比上面提炼一下,前面所说的光照信息大概包括:

  • Position(depth)
  • Normal
  • emissive
  • diffuse albedo
  • specular albedo

这些信息通过RenderTarget存储,被统一称为G-Buffer。

当然根据不同的渲染方案和引擎的具体材质组成等G-Buffer有细微区别。

一个RenderTarget显然是不够的,所以在MRT技术出现之前,Deferred Shading的应用并不多(因为此时要得到G-Buffer需要经过多个pass渲染,相对前向渲染没多少提升)。

【备注:现在硬件最多支持4个MRT,并且驱动要求4个MRT必须有相同的bit宽度;DX10及以上支持8个MRT】

延时光照的缺点
  • 对带宽要求苛刻:计算一下吧,如果采用RGBA32格式,当前分辨率为1920*1080,那么一张RT需要:(1920 * 1080 * 16)/(1024 * 1024)约31.6M,4张大概要127M,低端显卡直接歇菜了。。

  • 锯齿问题:DX9的MRT不支持硬件反锯齿(Dx10支持)。

  • 半透明几何体的渲染:RenderTarget上存储的是距离相机最近的像素点的光照信息,这就导致无法计算出半透明几何体之后的几何体的光照信息。换句话说渲染半透明物体时,无法得到正确的混合结果。

如上,原理说来很简单,但魔鬼往往在细节,后续文章会探讨下针对这三个缺点的解决方案并给出由RenderMonkey搭建的一个demo!

未完待续。。

你可能感兴趣的:(3D编程)