转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=2736

KlayGE从4.0开始引入deferred rendering层(DR),并且这几个版本都在持续地改进,以提高性能和降低使用难度。在即将发布的4.4里,deferred rendering更是往前跨了一大步,实现了一个初步的Tile-based Deferred Rendering(TBDR)。和常见的TBDR不同之处在于,这里的方法只需要SM3。(其实SM2也没问题,只是如果光源较多,会遇到指令长度限制)

Tile-based

在传统的deferred rendering中,每个光源需要和每个像素做一次相交测试,测试通过的才计算光照。这个相交测试一般通过light volume的方式进行优化。但最终仍然需要对每个light画1次。也就是说,每个像素需要对每个光源读取一次G-Buffer,计算一个光照,并做一次blend写入。这个带来的带宽开销远大于forward rendering,使得在低带宽的设备,尤其是手机平板平台上,几乎没有办法使用deferred rendering。

Tile-based的核心思想是,把G-Buffer划分成等大小的tile(一般会用32×32),每个tile会维护一个列表。对于每个tile,从depth buffer可以算出它的bounding box。把光源分成N个一组,每个光源和每个tile的bounding box做一次相交测试,并把光源id放入tile的列表中。在lighting的时候,一个pass只需要读取一次G-Buffer,就能计算列表中所有光源的光照。而输出的时候只做一次blend写入。因为在GPU寄存器上读写的速度远高于读写显存,这么做直接能把带宽减少N倍。用流程图来表示,就是:

从这个流程图可以很明显看出两者的大体框架相同,但Tile-based能把N个pass变成shader里的N次循环,所以就有机会提高效率。

带宽比较

这里来一个带宽的定量比较。假设G-Buffer由2个ABGR8组成,depth buffer的格式是float,光源数量是L、分为N个一组。Lighting buffer的格式是ABGR16F,shading buffer的格式是B10G11R11F。那么可以比较一下平均一个pixel的带宽。

  Deferred Tile-based Deferred
Tiling读取带宽 0 (32*32 + 2*(16*16 + 8*8 + 4*4 + 2*2)) / (32*32) * 4 = 6.66
Tiling写入带宽 0 2*(16*16 + 8*8 + 4*4 + 2*2 + 1*1) / (32*32) * 4 = 2.66
Lighting读取带宽 L * (4 + 4) + L * 8 = L * 16 L/N * (4 + 4) + L/N * 4 = L/N * 12
Lighting写入带宽 L * 8 L/N * 4
Shading读取带宽 8 0
Shading写入带宽 4 0
总和 L*24+12 L/N*16+9.32

DR不需要tiling,所以tiling部分的带宽都是0。TBDR的shading已经合并到lighting pass了,不需要独立的shading pass。同时也是因为已经是shading了,不需要把diffuse和spacular分开,也不需要输出到ABGR16F四个通道(三个diffuse,一个specular的亮度),只要RGB三个通道足矣。

由于tiling和shading的带宽相比之下已经微不足道了,所以这里主要就看lighting部分。如果N比较大,可以很明显看出lighting的带宽占用会明显减少。在KlayGE 4.4的实现里,N=32,已经能把带宽消耗减少到类似forward的水平了。

一些实现细节

TBDR的实现在网上已经有很多文章和代码,这里就只讨论一些细节。

Tiling的方法很简单,类似于mipmap那样,把depth buffer每次减少1/2。但需要保存的是min和max两个depth值,这样才能构成bounding box。这个bounding box实际上是一个斜的视锥。可以用个off center的frustum构造方法求出来。详见Intel的例子

在求交计算的时候,point light可以用球,spot light暂时用的是AABB。(其实spot最好使用cone和frustum求交,但我没找到相关算法)。在shader里把它们和tile的frustum做求交测试,也就是把原先CPU上的view frustum culling搬到shader里,per-tile执行。

重点在于,一般提到TBDR的地方说的都是用compute shader,至少也是具有任意写入能力的pixel shader 5,才能把这个列表保存到类似OIT的per-pixel linked lists里。但这样的话就失去了对老硬件和移动平台的支持(虽然下一代移动GPU就能支持完整的D3D11,但普及尚需时日)。KlayGE 4.4的方法是类似于light indexed rendering的做法,用个常见的ABGR8格式,每个light占用一个独立的bit组成32位的mask来保存这个列表。这么一来,就可以把32个光打包成一组,用这个固定长度的bit“列表”保存哪些光源对这个tile有影响。在不支持位运算的硬件上,可以用除法和求余来模拟出bit and操作,所以也能得到某个bit是否是1。

结果

最终实现的TBDR只需要用到SM3甚至SM2的shader,带宽减少32-64倍,瓶颈移到了计算上。而且,和原先的deferred rendering相比,只改了不到100行C++代码和100多行shader代码。任何一个deferred框架都可以轻松迁移到这个方法上。同时性能提升也是很明显的,目前可以轻松在低端硬件上实时渲染大量光源。

这里测试了720p的分辨率上,sponza场景在高端的GTX680分别使用DR和TBDR,每一帧所花费的毫秒数,横轴表示光源数。

和理论分析一样,随着光源的增多,TBDR花费的时间也逐渐减少,到1024个光的时候已经能少20%了。注意这里的TBDR只是个算法验证,还没到优化的阶段。而DR已经经过多轮优化了。

在低端的NVS4200M上,这个差距就更明显了,差距可以超过50%:

在KlayGE 4.4发布前,我会进一步优化TBDR,希望能有更好的表现。KlayGE 4.5中打算实现个compute shader的版本,把1024个light分成一组,基本上可以在一个pass算完所有的光照和着色。以后也会考虑更新的clusted deferred。

本篇讲了一个只需要SM3的TBDR,下一篇会将一些Deferred框架的其他改进。

KlayGE 4.4中渲染的改进(一):只需要SM3的TBDR的更多相关文章

  1. KlayGE 4.4中渲染的改进(三):高质量无限地形

    转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=2761   本系列的上一篇讲了DR中的一些改进.本篇开始将描述这个版本加入的新功能,高质量地形 ...

  2. KlayGE 4.4中渲染的改进(五):OpenGL 4.4和OpenGLES 3

    转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=2796 上一篇我们提到了SSSSS,作为本系列的最后一篇,本文将介绍KlayGE 4.4的Op ...

  3. KlayGE 4.4中渲染的改进(四):SSSSS

    转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=2774 本系列的上一篇提到了KlayGE 4.4将会出现的高质量地形渲染.本篇仍讲一个新功能, ...

  4. KlayGE 4.4中渲染的改进(二):DR的其他改进

    转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=2749   上一篇讲了TBDR的实现,本篇继续讲解deferred rendering层的一些 ...

  5. 怎么在ZBrush中渲染漫画风格的插画

    创建“漫画插画”的外观和感觉想必一定很有趣吧,但是,获得想要的精确外观有时也会令人相当沮丧,因此了解一些基本原则,创建类似于ZBrush漫画MatCaps的作品很有必要. 若有疑问亦或者想查看具体的视 ...

  6. UEditor js动态创建和textarea中渲染【原】

    UEditor动态创建和textarea中渲染 http://ueditor.baidu.com/website/examples/textareaDemo.html <!DOCTYPE> ...

  7. flask 在模板中渲染错误消息

    在模板中渲染错误消息 如果form.valicate_on_submit()返回False,说明验证没有通过,对于没有验证通过的字段,WTForms会把错误信息添加到表单类的errors属性中,这是一 ...

  8. flask 在模板中渲染表单

    在模板中渲染表单 为了能够在模板中渲染表单,我们需要把表单类实例传入模板.首先在视图函数里实例化表单类LoginForm,然后再render_template()函数中使用关键脑子参数form将表单实 ...

  9. ASP.NET Core 中的SEO优化(2):中间件中渲染Razor视图

    前言 上一篇文章<ASP.NET Core 中的SEO优化(1):中间件实现服务端静态化缓存>中介绍了中间件的使用方法.以及使用中间件实现服务端静态化缓存的功能.本系列文章的这些技巧都是我 ...

随机推荐

  1. 转载扩展Windows Mobile模拟器存储空间的方法

    扩展Windows Mobile模拟器存储空间的方法 在Windows Mobile应用程序开发的初期,可以使用SDK自带的模拟器来进行调试,这给我们开发人员提供了一种方便的途径.一般的应用程序,占用 ...

  2. poj 1737 Connected Graph

    // poj 1737 Connected Graph // // 题目大意: // // 带标号的连通分量计数 // // 解题思路: // // 设f(n)为连通图的数量,g(n)为非连通图的数量 ...

  3. 8.4.3 Glide

    1). 导入库 dependencies { compile 'com.github.bumptech.glide:glide:3.5.2' compile 'com.android.support: ...

  4. vb- ----之常用函数

    [VB]常用函数 2007-10-25 10:52 3375人阅读 评论(1) 收藏 举报 vbstringdateintegervbscriptwindows (一)类型转换类函数1. CType( ...

  5. RHEL6.5中完成播放音乐的“大业”

    参考文章:http://ylw6006.blog.51cto.com/470441/589964 感谢:ylw6006@51CTO 首先,费了不少劲去找到三个文件(还要对应版本el6.i686或el6 ...

  6. TFT-LCD的相关概念

    显示尺寸(display size) 是指实际可视区域的对角线长度,单位是英寸,简称寸(1英寸=2.54厘米). 长宽比(aspect ratio) 是指TFT-LCD可视区域的长度和宽度之比,也叫做 ...

  7. Swift编程语言(中文版)官方手册翻译(进度8.8%)

    翻译着玩,进度会比较慢. 等不及的可以看CocoaChina翻译小组,他们正在组织翻译,而且人手众多,相信会提前很多完成翻译. 原文可以在iTunes免费下载 目前进度 7 JUN 2014: 8.8 ...

  8. Visual Studio 2013 错误提示“未找到与约束匹配”的修正

    昨天由于项目需要,在开发电脑上安装了Microsoft Office Project 2007来做时间计划,但是安装之后第二天重新打开VS之后,就无法打开项目或者原有程序文件无法打开.错图提示界面如下 ...

  9. Building Apps for Windows Phone 8.1教程下载地址整理

    官方教程地址http://channel9.msdn.com/Series/Building-Apps-for-Windows-Phone-8-1http://media.ch9.ms/ch9/8db ...

  10. C#使用Timer.Interval指定时间间隔与指定时间执行事件

    C#中,Timer是一个定时器,它可以按照指定的时间间隔或者指定的时间执行一个事件. 指定时间间隔是指按特定的时间间隔,如每1分钟.每10分钟.每1个小时等执行指定事件: 指定时间是指每小时的第30分 ...