Grand Theft Auto V (侠盗列车手5)图形研究 (二)

发表于2015-11-23
评论0 3.9k浏览

原文链接 http://www.adriancourreges.com/blog/2015/11/02/gta-v-graphics-study-part-2/

 

Level of Detail

如果说Rockstar(GTA的开发商)在一个领域优于竞争对手的,那就是接下来要介绍的LOD。洛杉矶的游戏世界随着多边形和细节的多少,有许多不同的版本,即便是在线直播游戏时也不会被加载画面阻塞,使得整个游戏体验更加的身临其境。

 

Lights 光源

你看到的远处所有的小的光源都是真实的,你可以朝着他们的方向开车,并找到投射光源的灯泡。

Aaron Garbut

 

上面这段话是 Rockstar North的创始人和艺术总监Aaron Garbut,在PS3版发布不久前宣布的。

他的描述是否准确?让我们思考下面这个夜景:

 

 

简直像真的一样:你看到的每个小的光斑都是用一个使用32x32 texture的正方形渲染出来的。    

尽管用 instanced geometry(实例化几何体) 进行了大量的batch,但仍有数万多边形推送到了GPU

                          

 

 

而且这些并不只是静态几何体:车辆的前灯也在街道上移动,实时更新。当然,这个距离并不需要渲染所有的车辆模型,只要两个前灯就足以创作视觉。但如果你要接近一些远处的光源,LOD会增加,并最终绘制汽车的整体模型。

Low-Poly Meshes 低多边形网格

我们回到前面讨论的那一帧上,游戏世界里一些相当广阔的部分在一帧中被渲染。例如我们下面讨论的山的渲染:

 

    

 

那么遥远的小山究竟是什么样呢?

 

 

原来这个山一点也不小,实际上Vinewood Hill(现实中的好莱坞山)是一个跨越了几平方公里的区域,以及许多的房屋和建筑。

还有伽利略天文台坐落在山顶上,以及 Sisyphus Theater(希腊剧场), Lake Vinewood(好莱坞水库),可以在所有的这些区域里探索或驾车,并由数千的draw-calls 和大量的多边形来绘制。

 

但在当前这个场景里,这个区域很远,所以用低多边形的版本来渲染:只有1个draw-call和2500多边形。

 

所有的渲染是用一个读取了多张Diffuse texture的Mesh做到的。即便有一些工具可以把Mesh转化为低多边形的版本,但这个转化并不能完全的自动化处理,即便是Rockstar的3D美术师花费几天时间来手动的微调Mesh,也不会感到惊讶的。

 

另外一个例子,是城市中“小首尔”区的几条街,也是由一个draw-call来绘制的。

 

游戏世界的低多边形版,在高效的渲染reflection  cubemap这类不需要非常高细节和很高分辨率时非常的有用。游戏里如果只有一个LOD等级的话,实时的渲染环境cubemap因为包含了大量的几何体,会非常昂贵或无法实现。

 

Asset Streaming 资源流加载

像在GTA中给不同的LOD创建多个版本的游戏世界,是非常庞大和耗时的任务,是一个相当挑战。但是,即便你完成了这些,也仅仅做到了一半:你可以在硬盘上放几个G的model和texture,但如果不能找到方法来高效的加载到内存或GPU显存上就没有任何意义。

 

GTA V是实时的流加载资源,当你进入地图的另一个区域时,加载/卸载model和texture。真正使人印象深刻的是它实时的实现了并在几个小时内保持稳定。

 

技术上最大的成就,就是把这一些都压缩到了家用机的内存,并让游戏得以流畅的运行。我们流加载和压缩到内存的越多,就意味着可以比GTA4有更高数量级的细节。

Aaron Garbut

 

当然,这种流加载系统也有其局限性:例如当你切换角色时,相机要从地图的一个区域跳到另外一个区域,这种情况下,流加载系统会突然的过载,也是完全可以理解的,它需要5秒来整理和赶上进度。但GTA5通过缩小/转化/放大的动画很好的处理了这个过渡,并不会觉得完全像是加载画面。

 

当你正常驾车时,移动速度足够慢,流加载系统就有足够的带宽来保持更新。开飞机的情况就不一样了:它们对流加载系统来说太快了,这也就是为什么驾驶飞机的速度与现实相比大大的减慢了。飞行时,mesh会以和驾车相比更低等级的LOD来渲染以缓解流加载的压力,但有时仍然会有资源的"突然出现"。

 

Reflections 反射

因为前面分析的帧没有那么多的水,让我们通过下面场景更接近的看看游泳池和海洋是如何渲染的:

 

 

就像之前所见的,这个场景被正常的渲染:生成一张环境Cubemap(下图),主要用来渲染物体对周围的反射效果。

例如,游泳池的梯子的反射就归功于这张cubemap。

 

 

注意角色和一些像梯子这样的小的物体对象并没有在这张cubemap里。

 

在渲染水之前场景看起来像这样:

 

 

渲染水面和这个完全不同,它并不包括上面这张cubemap。

 

Reflection Map 反射贴图

首先,是生成"planar reflection map",这张图分辨率很低,是240x120,处理类似cubemap的生成,但只生成一张buffer并且有梯子和角色出现。

 

场景被颠倒的渲染,随后做对称采样就可以获得正确的反射了。

 

 

Refraction Map 折射贴图

图像的一部分被提取出来:这是水面所在的部分用来创建折射贴图,用来模拟后面的折射效果:光从水面下的射出。

这时加入一些“不透明水”的蓝色(水越深颜色越强),以及caustics(焦散)效果。最终的贴图为原始buffer的一半大小。

 

Combination 组合

要组合不同的buffer,再绘制一个矩形多边形来表现游泳池的水面。依靠bump texture,逐pixel的扰动多边形的法线作出一些水运动的错觉。

海面的情况不只是扰动法线,绘制一个每帧更新顶点的整体的Mesh来模拟波浪的运动以替换之前的四边形。

 

根据每个pixel的法线, pixel shader在不同的点获取reflection和refraction map信息,通过菲涅尔方程计算出坐标。

 

                                                               

 

最后的结果非常不错,加入真实扰动的水面效果非常有说服力。

 

Mirrors 镜面

镜面的渲染和水面是完全一样的技术,由于镜子只反射光,甚至比水面更简单,不用考虑来自镜面后的折射效果。

 

 

不像水面,镜面是完全平坦的,很难隐藏用较低分辨率时问题,texel相当的明显。通过设置给予较高的分辨率可以增加反射的质量。

 

生成 reflection map需要额外的pass渲染场景而且相当的沉重。当镜面在视口外或者玩家距离很远时(这时看起来像一个黑色的四边形),引擎可以避免执行这个额外的pass。

 

Spotlights 聚光灯

记得在每帧开始前生成的环境贴图并不包含任何角色和车辆,只有主要的建筑和风景吧?

这种情况下,下图中车的前灯是如何反射在潮湿的路面上的呢?

 

 

在帧分析的部分这个效果并不明显,因为那是一个白天的场景,但毕竟所有的G-Buffers 都被合并了,灯光也被顺序的绘制。每个灯泡,光投射到的其他mesh被计算了,也包括像潮湿马路的高光泽度表面上很强的反射高光的效果。

 

 

每个光源都要绘制一个mesh,这个mesh类似一个细分的八面体,只是通过修改vertex shader,使它与光晕的形状相匹配。

 

这个mesh没有texture,目的是为了让光晕内所有接触的Pixel可以调用一个Pixel Shader。Shader会根据Pixel深度,与光源的距离,法线以及specular/glossiness属性,来动态的计算光照。

 

 

上面的线框视图就是用来计算路灯光源的影像的Mesh。

 

这里你可以看到延迟管线(Deferred)和前渲染管线(Forward)相比的一大优势:延迟管线可以在场景中渲染大量的光源,而pixel shaders调用尽可能的少,只涉及了被光源影响到的pixel。而前渲染管线中,你必须要计算所有受光源影响的fragment,即使这个fragment实际并不任何光的影响,或者随后被其他的fragment遮挡。

 

好吧,既然看了那么多了,最后一部分的后处理特效吧

 

前篇回顾,欢迎点击:

http://gad.qq.com/article/detail/7082722

Grand Theft Auto V (侠盗列车手5)图形研究 ()

http://gad.qq.com/article/detail/7082727

Grand Theft Auto V (侠盗列车手5)图形研究 ()

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引