CryEngine技术讲解

发布时间:2016-12-6 18:12:58 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"CryEngine技术讲解",主要涉及到CryEngine技术讲解方面的内容,对于CryEngine技术讲解感兴趣的同学可以参考一下。

这个帖可能在这儿发比较奇怪,不过我是一个信仰黑客精神的程序员,也非常支持KlayGE的研发,希望发一些我的原创资料,和作者,以及KlayGE的作用者交流,甚至有一些麻烦的问题,也希望作者可以解答,如果KlayGE的研发能够涉及到这些东西,那就最好了。 作为一个刚从业不久的引擎开发人员,为了能快速有效地提高自己引擎的渲染质量,使用了各种办法来解析Cryengine的渲染手法。在此我将以专业的视角来与您分享我的经验和成果。如果您也是专业的图形程序员,希望与您一起讨论,解读这款令人惊叹的引擎,如果您是一个刚刚入门的新人或者爱好者,这将成为您不可多得的原创中文资料。 Cryengine是目前最难窥探的引擎没有之一,比起在中国泛滥的虚幻和GB的源代码,Cryengine也显得神秘得多,很少有人说自己有这款引擎,哪怕只有一个Eval。虽然有教育免费版,但是据我所知,也只有北大才申请到了授权。花了500W左右买了授权的好像也只有畅游和久游。但是越是如此,这款引擎的魅力越让人无法抗拒。当我有PerfHUD,PIX这样的分析工具时,我如何能不想着去拆解这个神秘又神奇的引擎呢。 Crysis所伴随的往往是最高画质的赞美和硬件杀手的批评,但是,我觉得即使这样,Cryengine仍然可以称为当今世界上优化最好,负载最大的引擎。其实引擎的设计追求的主要是负载能力,追求画面的应该是游戏。但是反过来,拥有最大的画面质量,没有引擎的强大负载,肯定是做不到的。任何引擎可以被美术用成硬件杀手,但是能在同样的情况下,跑出Crysis那样的画面的引擎肯定有着强大的负载能力。 Cryengine优化的出彩之处主要有以下几个方面: 1材质排序:从PerfHUD的结果来看,Cryengine对DXAPI的调用是最为简洁的,如此多的材质,却只有如此简洁的状态切换过程,不能不令人赞叹,相比之下,OGRE或者GB之类的三流引擎做得就要差得多。材质排序已经被做到了极至,从这里省下来的时间,成为了Crysis如此复杂的宏大场景的基础。 2技术选择:这是我最佩服Crytek的一点,如此多的次世代渲染技术,竟然每个都如此地和谐,兼顾着性能与效果。我研究了它的好多渲染手法,真是深有感触,为啥能如此恰当地选择技术呢?后来看了它们LPV的一篇Paper中有这样一个预算 ,这从恍然大悟。原来他们竟如此专业,预先做了这样的评估,难怪技术都被优化得如此高效,和谐。 3.瑕疵优化:这个通常被人忽略,或者被人认为是错的。很多人都觉得宁愿速度慢一点,也要求技术没有瑕疵。其实,这是不对的。瑕不掩瑜,在Crysis如此震撼的效果面前,有几个会对它技术的瑕疵非常关注,觉得不能忍受呢?但是在Cryengine中,所有的瑕疵都换来了宝贵的时间,以至它能对一个游戏添加如此多的渲染技术,以达到Crysis的效果。 有了这些与众不同,使Cryengine变得如此另类,以及怪物般的负载能力。当然有人要说,Cryengine不是最快的,因为相同速度的情况下,虚幻的画面可能更好。对,确实,虚幻的Irradiance技术提供了一个廉价的GI效果,但是,这个东西带来的限制却让虚幻完全没有能力大幅度改变场景光照,因为主光源是预先渲染好的。这个东西在Cryengine3中已经被支持了,同时候还有了LPV这个神奇的动态GI。这样说的话,Crysis所追求的全动态场景的理念其实也是逼真临场体验的一部分,当然需要更多的性能开销了。也就是因为Crysis有昼夜变化,才带来了这种前所未有的临场他体验。 接下来,我要对Crysis所使用的渲染技术进行一些细致的剖析。 Crysis是用Cryengine2制作的,Cryengine3无幸窥见,在这里,先说说确切的Cryengine2的渲染过程。 众所周知Cryengine2,没有使用DeferredShading,所以无法支持太多的光源,主要渲染围绕着阳光进行,而且使用了非常复杂的PixelShader来实现漂亮的材质,所以ZPass预渲染就变得很必要,不然会有很多无用象素被复杂的PixelShader渲染,当然这个和DeferredShading一样,无法支持Blend,所以只有两种,普通和AlphaTest。渲染ZPass为了开启PreZ,肯定要进行排序,先渲染普通物体,后渲染带AlphaTest(当然是使用Shader的Texkill来进行,没有状态切换)的物体。其实标准的ZPass应该是不需要ColorWrite的,但是Crysis利用这个机会,输出了深度到一张R32F,因为视距为八公里,乘一个0.000125映射到[0,1],天空为2。有了深度的G-Buffer,其实就已经可以做很多事了,除了光照外很多的后处理都可以用这张深度缓冲来进行。有了深度后,会先进行AO计算,然后阴影,这都是屏幕空间的计算,然后渲染每个物体都会对这两张图进行采样。AO是一张RGBA,R通道用来存SSAO的结果,G通道用来存2.5DTerrainAO的结果。然后进行一次Blur。阴影是有个Mask的,平行光一般是R,剩下三个通道,大概可以存放三个点光源或者SpotLight吧。然后就是对一张R16G16B16A16F进行HR的高范围渲染。这回DepthFunc已经是Equal了,因为深度已经完全填充。当然,为了PreZ,还是先普通后AlphaTest,然后会看到大量的碎片,因为Z检测会挡掉大量像素。所有着色像素加起来也几乎就是屏幕像素了,除非有两个三角形有点是同Depth的Fighting状态,当然可能性很低。完成后会进行Blend渲染,主要是粒子,玻璃之类的东西。结束后,就要进行HDRToneMap和HDRHighLightBloom了。完成后,接下来有一个EdgeAA,当然除此之外应该还有抗齿过程,只是调试时肯定是要关掉的。EdgeAA是个抗齿的后处理,只使用Depth来提取边缘。然后还有个Glow,大概会把火焰之类的Bloom加大吧。在这之后,就是SunShaft,来加上漂亮的Ray和Beam,最后会进行ColorGrading,完成渲染的最后一步,这样,就能看到Crysis的画面了。这样说是不是有些笼统呢?没关系,如果大家喜欢,我还会继续深入剖析Cryengine渲染的一些技术点,来解读震撼画面背后的故事。今天有点晚了先写到这儿了。   睡前再写一些看了KlayGE后的感想,KlayGE是一款我很喜欢的开源引擎。对于开源引擎来说,没有强大的资金支持,很难开发出像商业引擎那样功能强大的实用引擎。KlayGE这样研究一些新鲜的API,支持OGL3或4,DX11,以及一些好玩的技术的实现,却是真正有帮助的。它的字体算法的设计真的是非常的独到,让我非常震撼,我正在想有什么办法能使缩小时更清晰。像Ogre,Irrlicht那种引擎中既见不到强大的实用性,又没有这样的看点,我个人还是比较无爱的。KlayGE最近又出了FFT的水,对于只能看到SigGraph1999的我来说,还是非常有帮助的,记得上回Ogre有个水体插件,也做了FFT的波动,不过实时CPU刷顶点做法还是有点过了,这了新的Demo看,真的挺兴奋的。 有一点想问下作者,你的DeferredShading为啥不支持HW的AA呢,而使用一个后处理来进行?DX10开始,MRT不是已经可以AA了吗?难道还有什么障碍? 最后发张我现在自己渲染的图,虽然比Crysis差不少,但是渲染技术是差不多的。其实如果时间允许,我真是想自己操刀写个引擎,把Ogre改成这样真不是一般的麻烦,Ogre的渲染体系太古典了,不太适应现代的技术,搞得我动不动接管过来调DX,不然要么性能莫名其妙地不见,要么就是干脆无法实现。不过因为DX9,使用了DeferredShading后只能用后处理来抗齿,其实可以用超级采样,但是舍不得那性能啊。Ogre的材质系统不灵活,导致我一怒之下统一使用了线性过滤,材质糊糊的很不爽。下一步,可能就是要尝试下LPV了,毕竟GI还是很令人Happy的 继续更新啦,首先谈谈Cryengine的地形技术。地形技术是Cryengine的一个较为核心的技术,为了实现八公里的超远视距,地形经过了比较细致的优化。Cryengine的地形主要使用的数据结构仍然是高度图,并且在Cryengine2中可以看到,它所支持的尺寸非常有限,好像也不是动态加载技术的无缝大场景。为此为特地下了Crysis的Sandbox一探究竟。Cryengine的地形Lod时并没有Morph的过渡而是直接突变,这让我很惊呀,一般地,地形Lod时的突变会非常刺眼以至于让人难以接受,但是在Crysis中,我却完全无法意识到这一点,反复摆弄它的场景后发现,原来是超高密度的植被覆盖使得地形的跳动完全被植被所遮挡,植被同样也在不体地突变,所以一般只能感觉到植被Lod时的突变,而无法感觉到地形Lod时的突变。因为不需要Morph,Cryengine地形的灵活性就体现出来了,它可以切到最小只有2M*2M一个单元,但是越远,绘制的实际单元还是有所合并,具体LOD的细节仍然没有完全搞清楚,如果哪位大牛知道,希望能够不吝地告诉我,不胜感激啊。但是有一点是很清楚,它的LOD是有根据视觉复杂度和距离两个标准来决定网格精度的,我贴一张Wireframe先: 可以看到,网格精度并不是均匀地由近到远递减的,而是以地块视觉复杂度为权值的递减,期间有相当多的补面,以保证没有T型接缝。不过由于不需要Morph,跨级LOD之间的补面变得相对容易。 除了LOD外,地表材质也是Cryengine的一个比较出众的特性,Crysis的地表材质细节之丰富,绝对是目前绝无仅有的,但是支持它使用如此多材质的地表细节技术,却是Cryengine的一个特殊做法带来的。Cryengine并没有使用什么四层混合,而是按单层来划分的。当一层材质被刷到地形上的时候,Cryengine会生成一个材质的覆盖范围,也就是说每一个材质绘制时都有独立的IB区段,这样最大的好处是每个层都可以使用独立的渲染技术,而不会影响其它层,比如有parallax的地形层只有很少的一两个,但是混在其它层中却让地形细节有了整体的提升。还有就是因为地形距离有八公里,所以不可能都使用Blend的Tiling细节,在细节的几百米范围之外,就切换成只有一张的预生成大纹理,VirtualTexture技术在这里得到了应用。在同时使用了Tiling和VirtualTexture的情况下,Cryengine的地形远近都有很好的细节表现,同时性能上也能够支撑起八公里的视距。 当然Cryengine的地形技术中还有个神奇的Voxel技术。Voxel其实是个很古老的概念,应用到地形中应该是三角洲的时候。不过那时的Voxel技术不是很适应现在的图形管线,Cryengine只是使用了那Voxel作为一部分特殊地形的数据存储,最后用了某种算法,生成了与高度图Terrain无缝连接的Mesh,使得悬崖,山洞可以在引擎中用Terrain实现。通常要做这些往往都使用模型,而不同的系统使用起来很容易产生接缝。这就是Crysis地貌如此丰富的原因。 不过Voxel的生成算法,我还没有想到,或者看到,很想知道有什么好办法来实现这个。不知道龚敏敏大大是否有这方面的办法,或者有见过关于这个的文献。如果KlayGE能整合一个类似的算法,那就最好了。 很希望看到KlayGE的VirtualTexture和GI。目前我也正在整理一些解决方案,有这样的参考真的很不错哈。我可能考虑把LightMass和一种实时GI解决方案整合到无缝场景中。 接下来继续更新 Cryengine的阴影是我最喜欢的一个Cryengine的解决方案,它的科学性,实用性,让我很震撼。在目前的硬件条件下,Cryengine的阴影系统是一个比较完美的实时阴影解决方案。首先要说明的一点是,Cryengine2虽然不是DeferredShading,但是仍然有深度图可用,所以可以在屏幕空间计算阴影,这样能为PCF节省非常多的采样,与VSM相比,采样次数会更少。这样就有了下面的结论:PCF适用于实时性较高的阴影采样,因为一次采样的次数较少,而VSM更适用于低频更新的阴影,因为VSM可以预采样,采样完之后就能很快地生成阴影,这样的话,只要阴影不更新,VSM就不需要再采样。有了以上的思想,就有了Cryengine的阴影解决方案。首先用四张1024大的D24S8作为PSSM的四层,据我目测,PSSM的距离大概在200-300之间,由于远处的物件通常是在较浓的雾里,所以,其实远处阴影对画面的增益会较弱,近的阴影距离让Cryengine的四层1024图都获得了相当高的阴影清晰度。这四层阴影也并非实时更新,Cryengine对这阴影进行了控频,不过游戏中并未感觉到,只是Cryengine3在GDC2009的那段视频中,很明显看到了控频的痕迹。VSM则被用来渲染地形的阴影,众所周知,WOW的地形没有阴影,一开始我还以为这是对的,后来才发现原来WOW的光不会动,所以在阴影不被拉长的情况下,这样的阴影还是可以接受的,但是如果需要阳光动态变化,甚至拉到很长,没有阴影的地形会让物件的阴影腾空,相当难看,所以渲染地形的阴影还是有必要的。但是地形的阴影一般比较模糊,因为距离比较远,所以PCF对于地形来说,阴影边缘太过生硬,所以Cryengine选择了用VSM,在一张1024的R16G16F上渲染地形,然后进行一次Blur,由于地形的阴影渲染范围很大,再加上地形静止不动,和光线变化较慢的特点,地形的阴影更新频率非常低,这样,地形阴影渲染的开销就会比较小。在渲染地形阴影的同时,Cryengine还加上了云阴影,使得阴影非常完整,逼真。VSM使用半精度其实是非常冒险的,VSM不像PCF,利用统计学算法的VSM如果有完美的实数,将会是无比完美的,可惜,浮点的精度有限,想要VSM的阴影有一个模糊的边缘,高精度很必要。通常都使用32位的浮点,半精度会引起近处非常明显的条状失真。不过Cryengine的这个失真仍然存在,只不过并不是很明显,主要原因有以下两点,第一,地形本身是个低频细节的模型,所以阴影距离通常都比较远,第二,Cryengine使用的阴影距离近,所以,本身深度范围都小,所以精度自然就会比较高,浮点数嘛。所以Cryengine很有效地利用PCF和VSM模拟出了非常高效完美的阴影。这个解决方案目前也被我一直在使用。 关于采样,一般,PCF的采样是不如VSM的,原因是PCF是一个比较出来的二值结果,无法利用MipMap,线性采样和AA之类的预采样,这也正是VSM的优势,但是在DX9中,有个HWShadowMap的解决方案,利用透视校正的采样,可以利用线性过滤,一次采样即可得到4次差值的PCF,而在这个基础上进行多次采样,就可以得到非常柔和的效果。一般的,在动画或光发生改变时,阴影很容易发生抖动,这种抖动是非常刺眼的,这是由于被采样的纹理本身的锯齿抖动造成的。想要解决这个问题,一般就两种,VSM可以利用AA来解决,而PCF则利用随机采样。随机采样之所以不容易感觉抖动是因为高频的抖动不容易被人眼察觉的关系。GPU2上就有一篇文章描述一种随机采样方法,不过GPU上的采样方法比较原始,所以实用性并不强,Cryengine使随机采样到了一个新的境界。首先,GPU上说的方法是连续采样一张随机纹理,来得到随机的信息,但是这显然是种浪费,因为一次采样就可以得到随机了。Cryengine所用的方法是预生成一个圆形分布的采样点集,然后采样一次随机纹理,随机纹理上记录的是这个点集的旋转角度,这样的话,一次随机采样,就能使所有点都随之改变。而且也正是这些图形分布的点的旋转,使得阴影边缘更柔和了。GPU上的方法,随机采样的UV是屏幕空间的,这样的随机采样点抖动很快很频繁,而且容易被察觉到屏幕空间相关。Cryengine则是使用了一个光空间透视较正的办法,得到一个只与远近及角度相关的随机纹理UV,这可以把抖动降低。经过了上面的改进,Cryengine的阴影采样效果非常不错,虽然比不上SAVSM,但是比起以往的PCF阴影效果强了太多,把随机采样推到了一个新的高度。 关于ShadowPass,PSSM需要把阴影存在四个SM中,那么采样就会遇到用几个PASS的问题,像WOW,直接采样四张图,肯定会造成无效采样,性能会比较低,而GB则使用一张大图来存,通过变换来定位,再采样,而Cryengine用了另一种方法,使用模板,模板可以分别提取每层需要的像素,然后进行采样,四个Pass得到最终的阴影,理论上来说,全屏的阴影,应该是这个性能最优,因为采样的图更小,又没有重复采样的浪费。 以下是我使用这个解决方案得到的结果,因为引擎和时间的关系,我没有做阴影距离,所以是全距离阴影,我的视距为400米,我用了2048X4的PSSM,和2048G32R32F的地形阴影。因为我这个距离,地形阴影用半精度会出现严重的精度不足的VSM失真,所以没有办法,Cryengine在这个距离上是掐得相当准的,稍有偏差,就会导致无法接受的失真。 Cryengine中的AO是SSAO第一次被应用到游戏中,一才就炒热了实时间接光照。Cryengine的AO技术并不是目前效果最好的,但是它的Blur却是最快的,也就是因为超快的Blur,使得它可以应用FullAO,而不是HalfAO,因为FullAO的使用,叶子或者草之类的高频物体的AO变得比较好,所以总体来说,也算是个不错的AO解决方案。因为Cryengine的渲染体系是没有Normal可用的,所以仅Depth采样所得到的AO或多或少会有一些问题,所以只能说,这个是目前仅深度AO中,较好的效果,因为它的全局性非常强,这得益于算法中会根据距离来缩放射线长度,所以Cryengine的AO非常显眼,不像有些AO的效果离远了就容易被忽略。Cryengine的AO是全精度计算的,这可能会导致比较大的开销,所以Cryengine对采样进行了优化,主采样使用屏幕原大小的图,然后对周围采样时候则用了缩小后的Half图,这节省了一些采样时间,也引起了一个竖条状的失真,这个可以在Crysis中见到,雪天的门口比较明显。随机图方面,Cryengine用了一张4*4的图,一共16种,这使得它的杂点非常难看,但是却给BlurAO带来了便利,因为只需要四次采样,加上线性过滤,就能得到完全平滑的AO效果了,这比起Nvidia的HBAO要快得多。不过这样的AO仍然有比较多的缺点,比如角色的后面容易黑,低多边形镶嵌的痕迹明显,还有就是Blur后会造成象素的偏差,所以Crysis中也容易看到AO中有亮边,但这不影响这个AO全局性好的特点。不过具体如何,还是仁者见仁。我使用这个AO方案是因为草叶之类的高频物件表现相对好的原因。 Cryengine还有个预计算的TerrainAO,我暂时还没有机会去看。 下面发两张我的结果: 我的结论是远处,以及草叶表现较好,不过如果有Normal的话,还是非常大的改进余地。 KlayGE中的AO是不是和DX中的HDAO差不多啊?感觉那个AO可以钩出非常细节的AO线,但是全局表现不如这个,怪不得叫HDAO,如果能配上一些低频的AO的话,应该会更好看一些。Nvidia的HBAO效果也挺好的,就是Blur老是出现点,但是可以比较好的解决低多边形镶嵌的痕迹,所以还是不错的解决方案。将来我会再尝试做个更好一些的AO,目前这个仍然没有十分让人满意的方案。

上一篇:好莱坞名导:魔兽世界教会我们的7个人生哲理
下一篇:Axis接收远程调用c# webservice返回的数组

相关文章

相关评论