延迟着色

今天我们来讨论一下游戏中多光源的应用,为了有更好的光照效果,引擎就必须对多光源进行支持。实现方式大致有以下几种:

1、传统的前身渲染(Forward rendering)。

  这个一般在国内的游戏引擎中比较常见,国外引擎中也有使用,比如最近的使命召唤系统,为了保证帧率就使用了前向渲染来支持有限个数的点光源。这个一般也有两种做法,一种是对场景渲染多遍,每遍计算一个光源信息。另一种方法是只画一遍,在shader里面处理多个光源的情况。但他们对每个物体支持的光源个数均有限。一般最多支持四个光源(不包括主方向光)。它的主要缺点就是光照计算跟场景复杂度和光源个数有很大关系。假设有n个物体,m个光源,且每个每个物体受所有光源的影响,那么复杂度就是O(m*n)。

2、延迟光照 (Deferred lighting)DL

  这个在早期的CryEngine[1]版本中应用比较成熟,第一遍主要是把法线写到一张RT上,然后再进行光照的计算(主要是点光源 聚光灯 环境光),最后再把整个场景画一遍,取上一步计算好的光照,然后再计算主方向光的光照,得到最终计算好的结果。这种方法的优点是光照计算(点光源、聚光灯的计算)跟场景复杂度无关,可以支持任意数量的光源,而且对帧缓冲区带宽的压力也比较小,但一个比较大的缺点是需要对整个场景画两遍,如果场景中物体比较多的话(经过各种剔除和合批之后),这种方式并不是特别合适。

具体流程如下所示:[2]

3、延迟着色 (Deferred shading)DS

  这个技术在很多商业引擎中都有应用,包括UE和一些国外比较出名的自研引擎。它跟延迟光照的最大区别在于场景只需要画一遍,但是在第一遍输出的信息就会多一些,除了法线一般还会输出漫反射颜色、高光强度、光泽度等,根据引擎的不同需要,这个根据项目或者引擎的具体实现不同也会有所不同,接下来就计算光照信息(包括点光源、聚光灯效果等的光照信息),最后一步是进行着色,得到最后的结果,当然刚才前面说到的计算光照和着色也可以放在一起来做。它相对于DL的最大优点是场景只需要画一遍,但是一般需要使用MRT,这样对帧缓冲区带宽的压力就比较大。它也跟场景复杂度没有太大关系,支持任意的点光源。主要缺点就是D3D9下面不支持MSAA,因为开启了MRT。

具体流程图如下所示:

4、延迟光照和延迟着色相结合 (Hybrid Deferred shading)

  由于引擎需要支持各种好的效果,所以在单纯使用DL或者DS都不能很好的满足需要,所以就出了一种两种结合的方式,即同时支持两种着色方式,这个在CE的后期版本中已经应用起来,Crysis3也是这样做的。我们的引擎使用的也是这种方式,这样就兼备了两者的优点吧。当然还是要写多张RT,但是大多数的几何体就只需要画一遍就可以了。

具体流程如图所示:

5、前向渲染++ (Forward plus plus)

  这个没有具体去研究,好像对D3D9支持不友好,在D3D10及以后的版本中比较好,而且也是在实验性阶段,不知道有没有在商业引擎中得到验证。各位看官如果有兴趣可以自行研究。[3]

目前应用最多的应该就是Hybrid Deferred shading这种方式了,加上现在又开发了Tile-based deferred shading技术,这样就可以减少很多带宽消耗,能提高不少效率。但是这种技术在不支持Compute shader的D3D9上实现并不是特别容易,我们引擎参考KlayGE的方式实现了下,但是效果并没有那么理想,可能实现方式有点问题。但是由于我们点光源数量并不会特别多(同屏几百个),所以也就没有再继续深究下去。

  

  下面就简单介绍一下我们引擎使用的方式,出于保密,我们只讨论一个做法,并不会有特别详细的代码。我们也是参考国外的文章来写的,并没有太多创新性的东西,所以我会把我参考的文章一一列出来,这样大家在实现的时候也有一个比较好的参考。如果大家对上面说的这些没有太多的概念,可以看看Shishkovtsov 2005 Policarpo and Fonseca 2005以及Hargreaves and Harris 2004,但文章都比较老,建议实现的时候参考一些比较新的文章。下面开始说我们的实现。

  由于我们的引擎需要对多光源进行很好的支持,以及需要支持比较多的光照模型,加上我们引擎支持超大视距,所以最后决定使用Hybrid deferred shading,这种方式,这样既可以满足多光源的需要,也能保证大部分物体只需要画一遍,只有在一些比较复杂的光照计算时才需要把几何体画两遍,这样可以明显减少DP(DrawPrimitive)的次数。

我们使用了3张RT,均为4字节具体格式如下所示。


Diffuse R


Diffuse G


Diffuse B


Specular Level


Normal.x


Normal.y


Gloss * sign(Normal.z)


Material ID


R16(Depth)


G16(Reflection  Level等)

3张RT的格式分别为A8R8G8B8 A8R8G8B8 R16G16,Material id根据id的不同会采用不同的光照模型。法线采用压缩的方式,和Gloss一起压缩到RGB三个通道中,具体方法如下图所示:[4]

深度Dpeth存储的是一个线性值,这样可以直接在vs里面计算好到ps里面进行插值最后写到第三张RT上。第三张RT上的G16R的值会根据Material ID来进行不同的解释。在MRT里面的数据准备好以后,我们接下来就需要进行点光源和环境光的计算,这时为了简单会采用统一的光照模型来做。如果只是只画一遍的几何体,那么接下来就可以做一个全屏的后期处理来得到最后的结果,如果着色模型比较复杂,需要画两遍,那么我们就在第二遍的时候计算主方向的信息并得到最后结果。

  这里有几个细节的地方需要说下,一个是通过世界深度信息来反算世界位置。这个我们利用了相似三角形来做的,需要在VS里面把世界空间中远裁剪面上四个点减去摄像机的位置传入,这样在ps中就可以直接利用相似三角形得到世界位置。

另外一个点光源照明范围的正确处理,我们是用了模板来标记它的处理范围的,这样做起来比较简单,效率也可以。当然也有其它的优化方法。

总结:

  总起来说,其实这个东西还是比较简单的,当然要实现比较高的效率还是需要花费不少心思的,魔鬼都在细节中,要实现跟其它流程和效果的完美结合也需要花一些功夫,况且我们还要前向渲染也要很好的支持,主要是考虑在低端的笔记本上也能有比较流畅的帧率,我们引擎支持前向和延迟渲染的实时切换。而且还有透明物体的处理,这个也比较麻烦,我们就直接在前向里面来做的,当然延迟里面也是有方法可以做的[5][6]。除了上面提到的处理多光源的方法外,许多国外的牛人也对其进行了改造,比如Light Indexed Deferred Lighting[7]。

  总之可能在未来的几年之内,Hybrid deferred shading可能会变得越来越流行,很值得大家去研究下。上面都是我个人参考资料并理解消化的,可能难免有错误之处,如果有还请指正,也欢迎大家讨论。

参考文献:

[1] A bit more deferred -CryEngine3

[2] Hybrid Deferred Rendering  Marries van de Hoef

[3] Tiled Rendering Show down Forward Plus Plus Vs Deferred Rendering

[4] The Art and Technology behind Crysis 3

[5] http://www.john-chapman.net/content.php?id=13

[6] Transparency with Deferred Shading

[7] Light Indexed Deferred Lighting Damian Trebilco

时间: 2024-12-19 18:38:11

延迟着色的相关文章

OpenGL核心技术之延迟着色法

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解>电子工业出版社等. CSDN视频网址:http://edu.csdn.net/lecturer/144 如果读者使用过Unity3D引擎,在相机的组件中有关于延迟着色的控制开关,读者自己可以尝试体验一下效果.我们现在一直使用的光照方式叫做正向渲染(Forward Rendering)或

Deferred Shading,延迟渲染(提高渲染效率,减少多余光照计算)【转】

Deferred Shading,看过<Gems2> 的应该都了解了.最近很火的星际2就是使用了Deferred Shading. 原帖位置:   http://blog.csdn.net/noslopforever/archive/2009/03/03/3951273.aspx 这篇文章是对GEMS2里<Deferred Shading in S.T.A.L.K.E.R.>(中文译名<S.T.A.L.K.E.R.中的延期着色>,原作者Oles Shishkovtsov

Android 7.0 Nougat(牛轧糖)---对开发者来说

android 7.0出来了.让你的app准备迎接最新的android版本吧,支持节省电量和内存,这样新的系统行为.使用多窗口UI.直接恢复通知以及其他操作来扩展你的app. android 7.0介绍了各种各样的新功能给用户和开发者, 本文重点介绍面向开发者的一些新功能. 确保检查android 7.0的行为变化,了解有关平台的变化可能会影响你的app. 如果要了解更多的关于用户的新功能,请查看www.android.com. 1.支持多窗口 在android 7.0中,我们介绍了在支持多窗口

Android N特性解析

作者:Redyan, 腾讯移动客户端开发工程师 商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处. 原文链接:http://wetest.qq.com/lab/view/288.html 导语 8月22日,谷歌正式推送Android 7.0 Nougat(牛轧糖)正式版,首发推送了多款Nexus设备.除了修复常规BUG,Android 7.0还新增了分屏.新的Notification.VR支持等新特性. 8月22日,谷歌正式推送Android 7.0 Nougat(牛轧糖)正式版,他

一步步学OpenGL(20) -《点光源》

教程 20 点光源 原文: http://ogldev.atspace.co.uk/www/tutorial20/tutorial20.html CSDN完整版专栏: http://blog.csdn.net/column/details/13062.html 背景 之前已经学习了三个基本的光照模型(环境光,漫射光和镜面反射光),这三种模型都是基于平行光的.平行光只是通过一个向量来表示,没有光源起点,因此它不会随着距离的增大而衰减(实际上没有起点根本无法定义光源和某个物体的距离).现在我们再来看

Android7.0新特性,及Android N适配

新特性部分 Android 7.0 Nougat 提供新功能以提升性能.生产效率和安全性,主要新增了以下的新特性和优化: 一.新的Notification Android N 增加了许多新的notifications API,进行了重新的设计,引入了新的风格. 模板更新: 开发者将能够充分利用新模板,只需进行少量的代码调整. 消息样式自定义: 新增自定义样式.消息回复.消息分组等更加灵活. 捆绑通知: 系统可以将消息组合在一起(例如,按消息主题)并显示组.用户可以适当地进行 Dismiss 或

关于Depth Bounds Test (DBT)和在CE3的运用

Depth Bounds Test (DBT) Depth Bounds Test(深度范围检测),是Nvdia GeForce 6系列以后显卡的特性(GPU Programming Guide GeForce 8 and 9 Series),并不是DirectX的特性.所以在例如Nsight和Pix的图形分析工具里,是看不到它的设置的. Depth Bounds Test的功能是允许程序员在blend render target前进行额外的像素Discard.这个扩展增加了一个新的逐个frag

【译】Android 7.0 for Developers

译者注: 译者:aroundme 原文地址:https://developer.android.com/about/versions/nougat/android-7.0.html 主要是介绍Android 7.0提供新特性. 翻译的动机主要是为了适配Android 7.0,提前踩点.防止大坑. 就翻译来看,除去一些可有可无的更新之外,关注点主要是集中在四点: * 通知栏一系列更新 * 对于应用后台优化(或者说限制) * WebView持续性更新(混合开发需要注意) * 对于GPU的优化,优化3

《游戏引擎全局光照技术》到底是一本什么样的书?

你可能觉得<游戏引擎全局光照技术>是另一本图形学理论知识科普读物,对不起,你错了!本文以问题的方式介绍该书的特点,更多信息的试读内容下载欢迎访问:http://www.thegibook.com 1. 这本书面向的读者群体是谁?本书面向所有需要了解计算机图形学中渲染相关原理的职位,包括游戏,影视动画,以及其它需要使用Unreal Engine等游戏引擎来处理工作的行业: 2. 这本书定位什么级别?中高级,这本书最核心的目的是帮助具备一定基础的读者系统地梳理各个庞杂的计算机图形学知识体系,如果您