随着GPU的飞速发展,近年来一种新的渲染方式正悄然走红,这就是“延迟渲染”(Deferred Rendering)技术。目前已经有不少游戏采用这种着色技术,像是UBI的《幽灵行动尖峰战士》系列、跳票王STALKER以及目前最流行的UE3引擎都已经采用了这种新生的着色技术。跟传统的“顺序渲染”不同的是,在Deferred Rendering模式下,我们可以把光照计算需要的depth、normal、diffuse、specular等参数先渲染到若干render target(保存在G-Buffer中),然后可以在最后再根据G-Buffer的内容进行打光着色。
那么这样做有哪些好处呢?我们举个例子:假设在一个场景中GPU需要渲染一堵多个光源影响下的复杂砖墙,可是这堵砖墙在最终场景里被另一个物体挡住大半,玩家只能看到砖墙的一小部分,这时如果采用“顺序渲染”的话就必须从头到尾一步步完成所有的shader计算,即一开始对砖墙进行的大部分运算都是在做无用功;相反如果采用Deferred Rendering的话就可以将砖墙被遮挡部分的无效渲染省略掉,大大提高了运算资源的利用率!不过Deferred Rendering也有自己的缺点,首先是G-Buffer需要消耗掉部分显存;其次还会消耗掉部分显存带宽。所以只有当场景中光源数量众多的情况下才有必要使用Deferred Rendering,否则在shading不够复杂的情况下Deferred Rendering带来的显存、带宽开销就显得有些入不敷出了。最后延迟渲染还有另一个更加严重的弊端——不支持透明或半透明物体,为了解决这一问题,开发小组特别采取了一些措施,具体我们留在后文再详细来看这个问题。
暴雪的引擎开发小组通过研究对比发现,在星际2光源数目众多、shading复杂的游戏环境中采用Deferred Rendering可以大大节省运算资源开销。他们发现在这种渲染模式下为画面添加多重特效所带来的性能损失要比forward rendering线性许多,始终处于可以接受范围内,而且不会受到场景中战斗单元数量的影响,这一点对于一款RTS游戏来说尤其重要!此外,程序员还可以提前进行Z轴缓冲测试跟stencil测试来减少无效渲染,其做到大幅提升效率的目的。
尽可能减少draw call是另一个保证RTS游戏流畅运行的关键,所以引擎开发小组决定放弃拆分多个pass渲染到单个render target的做法,取而代之改用单个pass渲染到multiple render targets(多重渲染目标,下文简称MRTs),这样一次draw call就能画到最多四个面上,有效减少了draw call的数量。为什么说最多四个是因为DX9限制最多一次只能绑定四个render target,所以主流显卡也只能做到四个RT,而且长宽还必须一致。虽然DX10已经允许最多8个RT但很遗憾《星际2》的引擎就目前的资料来看并没有提供对DX10的支持,希望日后暴雪能够考虑添加支持DX10。
这样一来在星际争霸2中对所有不透明物体的渲染就必须将下列参数写到对应的若干MRT中:
不受本地光源影响的颜色值,比如环境贴图和顺序渲染下的光照颜色值
• 深度值
• 逐象素光照法线值
• 环境光遮蔽值(开启静态环境光遮蔽的情况下);如果开启屏空间环境光遮蔽的话则忽略预计算环境光遮蔽贴图
• 无光照漫反射颜色值
• 无光照镜面高光颜色值
前面我们谈到在《魔兽争霸3》中,由于当时的技术所限,对于地形的渲染只能尽量简化效果。而如今在星际2的引擎中,制作小组只需一个pass就能够将用于地形渲染的多层效果写到MRT中,大大提高了效率。保存在MRT里的各种渲染参数为开发人员提供了绘制各种绚丽特效的条件,经常需要写到MRT里的常用数据包括:
用于各种光照跟特效的深度值(这一步跟CryEngine 2所采用的“逐象素场景深度计算”技术类似,由于《星际争霸2》中出现大量需要深度值参与运算的特效,比如容积雾、动态环境光遮蔽、景深、边缘检测等等~~提前计算出深度值然后供后面的渲染步骤反复使用能够有效减少shader运算的浪费,大大提高了效率。)
• 用于环境光遮蔽运算的法线值
• 用于光照的漫反射与高光值
延迟光照
在《星际争霸2》中,只有本地点光源与聚光灯光源采用延迟光照模式,因为这两种光源均被限制了光照区域,所以能从deferred rendering 中获益。而照射全景的方向光源则仍然沿用forward rendering,因为其光照区域为整个场景,所以不存在光照效果被遮挡的情况,如果采用deferred rendering的话效率反而更低。总而言之,不管是“延后”还是“顺序”,两种算法最终得出的画面效果都是一致的,区别只在于不同场景下的效率高低而已,而星际2引擎也同时支持这两种渲染模式,以供程序员在不同场景中灵活选用以保证最高的硬件利用率!
延迟渲染模式大幅减少了draw call的需求,让需要大量动态光源烘托气氛的《星际争霸2》剧情模式成为了现实。上图场景中包含了将近15个动态光源,其中小到圣诞节装饰用的彩灯,大到电视荧幕上的亮光,都能够产生真实的光影效果,为营造真实的光照环境创造了条件。