【译】CEDEC2015 面向次世代机的实时动画表现表现方法

发表于2016-04-06
评论0 1.9k浏览

 

 


  本演讲的内容,在2015年CEDEC上分享是关于PS4和Xbox One版【火影忍者疾风传 究极风暴4】开发的相关话题,包括了开发的经过,移植过程中所产生的技术问题,以及作为次世代表现而新追加的绘制功能。

 

会议主要内容是次世代的移植和游戏表现的介绍两部分。

导入

 

 

 

 


  首先是游戏的介绍,应该也有人知道,火影忍者系列第一款游戏是2009年在PS3发售的。然后,基本上上1~2年1个续篇,对应平台也从PS3独占变成了也支持Xbox360和PC。最后这次介绍的究极风暴4是对应PS4, Xbox One以及PC来发售的。

 


  本作已经在今年2月发售,是系列第一部对应PS4和Xbox One的作品

 


  而本作的目标就是忠实的再现原作的日系动画表现。所以,本作的渲染模型是基于【Cel Shader】并没有使用现在流行的【基于物理渲染】。

  由于本作一开始是对应PS3,PS4,Xbox360,Xbox One以及PC一共5个平台,而到了14年10月时,变更为只对应次世代机的PS4,Xbox One,PC3个平台。因为平台变更了,不光是前作的资源,当时已经在制作的资源如何使用也成为了问题,其中,有问题的场景有40种,角色100个以上。所以,如何在不修改工作流,只需要适当的工作就可以作出次世代那样丰富表现就成为了目标。

 


 

Shader的移植

  首先是Shader的移植,    和次世代的区别中,图形API的变化是其中最大的一个变更点,也就是从DirectX9到DirectX11的变更。而且PS4是无法直接使用DirectX11的,因为使用的是基于DirectX11等级的API,所以这里以DirectX为标准来进行说明。

 


  移植最大的不同点之一是图形API从Dx9向Dx11的变迁。

 


  上图是DirectX11的主要变更点,固定管线的去除和Device的分离也是变更点,这次演讲主要以Shader Model的变化进行说明。

  每个Directx世代的对应的Shader Model,Directx9对应的是【1.0,2.0,3.0】,Directx10对应【4.0,4.1】,Directx11对应的【5.0】(SM6.0也已经在GDC2016上公布了),对于家用机游戏,从3.0移植到5.0的情况比较多,主要的变更点是寄存器,函数的扩展,大部分Shader不需要修改就可以移植。下面要对必须要对应的变更点做说明。

 

 

  先是constant buffer,它是从Directx10开始追加的设置Shadr参数的缓冲,在以前的Directx9,参数需要分别的进行设定,而Directx11可以把它对象化,而且不光constant buffer,Render State,Sampler同样变成了对象化。如果要向Directx11的Shader传递参数,这里必须进行以下的修改。

 

 

 


  与Directx9时的HLSL相比,首先是变量的定义上,上图代码里使用全局声明也是可以的。

 


  还有就是参数的传递方式,设定每个变量,就像Set「datatype」里的一组变量,是把数据的指针进行传递的。就像代码示例里那样,每个变量都是分别进行设定的。

 


  使用Cbuffer来定义Shader参数,上图右例,是类似C结构体的Cbuffer,可以在括号里设置constant buffer使用的寄存器编号。

  接下来是参数的传递方法,因为这里稍微有些复杂,使用了简化的函数名,程序方面用CreateBuffer函数来生成缓冲,用UpdateSubresource来更新缓冲内容,使用SetConstantBuffers来绑定缓冲寄存器。函数的第一个参数就是要写入Shader的寄存器编号。这里是使用PSSetConstantBuffers函数绑定像素Shader到寄存器的示例,最初的参数0指定的是绑定到0号寄存器上,这个函数一次性更新了五个变量。

 

 

  还有一个需要注意的就是,要尽量减少constant buffer更新的大小和频率,因为基本上constant buffer的一部分内容是不更新的,不需要每次都对constant buffer的整体进行更新,所以需要按照更新频率来进行分割。本作的大部分shader只使用了一个constant buffer,为了防止每帧更新,在CPU这边设置了Cache,实现了全部参数设置后一次性在GPU上更新缓冲的方法。这样实现后在性能上也没有问题了。

  接下来是Texture和Sampler的定义,在Directx9里,是在shader中定义Sampler时决定使用的Texture。

 


  上图的代码里,红色的就是指定Texture的部分。

  而Directx11的情况,是在使用Samping函数时绑定Texture,Directx9使用tex2D函数,而Directx11中变更为使用Sample函数,这样Sample函数的第一个参数变成了sampler,使得Directx11里一个sampler可以被多个Texture对象使用。

 

 

  为了对应不同平台Shader上的差别,这里把constant buffer, texture, sampler等的定义用宏来管理,管理了约220个Shader文件。

 

 

  向下图右侧的Samper的细节编译时并没有问题,但并不能实际的反映,必须要在程序里传递值的设置。在本作里因为没有使用technique和effect,所以没有这些问题。

 

 

粒子的性能问题

  本作的游戏概念是以开发超级破坏为目标。和前作相比,这次的粒子相当的多,需要对绘制系统的允许范围进行确定。

 


  本作的boss战,木人柱间和斑的九尾须佐能乎之间的战斗,可以看到有非常多的粒子。

 


  开发中的调试画面,左上的1080就是粒子的数量

  通常的boss战的粒子数是500左右,数量多的时候会达到约2000~3000的绘制。下图是粒子的性能测量,首先是CPU方面进行粒子的控制和绘制命令的构筑,GPU上进行粒子的绘制。CPU上的负荷是200%~300%,GPU上在100%以内。这里CPU上Overhead的主要原因是绘制命令的生成。

 


  生成绘制命令是主要原因。

 


  PS3和PS4的对比,PS3是3.2GHz的主频,6个SPU,PS4是1.6GHz的主频的8个核心,PS4的核心变多,但时钟频率降低,单线程的时候,直接移植到PS4会比PS3更慢。

  最初进行的是使用GPGPU的研究,因为把旧世代的在CPU里计算的Skinning和Morphing放到了GPU里计算,成功的降低了负荷,所以也希望粒子也可以用GPGPU来加速,但研究的结果证明这样做是很勉强的,所以改用多线程来实现。

 


  在GPGPU化失败后,采用多线程来加速

  在多线程的实现中,也遇到了一些问题,首先是对象之间的依赖关系,渲染指令是根据游戏中的物体对象更新来的生成,在渲染指令生成过程中也会有物体进行更新的情况,这样,就有可能受到影像,所以改成物体对象全更新完后再生成渲染指令。还有就是全局变量和单例(Singleton )的成员变量在读取时没有问题,但在设置值的时候会出问题。这里使用TLS(thread local storage),保持固有的全局变量和单例对象的修改。在每个线程Request前,把主线程的变量拷贝到各线程TLS中来实现。

  然后就是递归函数,当使用Lock, Unlock的互斥处理时,在递归Unlock前再次Lock的话,就会2次调用Lock陷入死锁,所以需要修改成没有递归的设计,实在不行的话,就使用一些土方法,通过设置flag让Lock不会连续两次调用。对单线程的专用代码,把负荷高的函数分散在几个线程里执行。

  还有就是每个线程都通过affinity来指定线程在指定核心上运行来提升效率,上下文切换会有消耗,所以用affinity来指定会快很多,还有互斥处理时Lock的耗时长可能会导致多线程没有效果,可以研究下Lock free的算法。

 

 

  多线程化的结果,CPU方面的负荷大幅减少,回顾多线程化,可以说设计是最重要的,设计的问题点就如前文所说,减少物体之间的依赖,减少全局变量,单例的共用资源,并尽可能的以多线程的形式来实现。可以的话,还是应该利用GPU,争取做到GPGPU化。

 


  多线程化的回顾。

  前半部分的技术话题就到这里,接下来是绘制表现的介绍。

 

 

 


  游戏使用的表现,主要分为4大部分,背景,角色,后处理和粒子,这里依次进行说明

 

背景

  首先是Decal功能,在本次的战斗和Boss战中,都使用了Decal,使用方法上,由程序来指定投影位置和范围,美术准备要贴上的Texture。实现方法上,最初也是UE4实现的那种屏幕空间Decal,后来变更为对应究极风暴的Forward渲染使用的,把延迟渲染的功能做了限制后实现了。

 


  上图就是把左侧的Texture贴到右边场景中的示例。

 

 

 


  先是角色和背景的绘制,上层左图是深度缓冲,右图是颜色缓冲,利用深度缓冲在屏幕空间上进行Decal的绘制,再把Decal合成到场景里上,然后是不受Decal影像的特效等物体的绘制。

  进行Cel表现的绘制,不需要复杂凹凸的光照,所以不需要实现利用法线信息的复杂绘制功能,也就是粘贴Texture,Alpha Blend的程度,尽可能多的显示。考虑到处理负荷,设置为通常最多20个Decal,Boss战为40个Decal。Decal的表现只需要美术准备一张Texture,花费少量工时就可以实现了。

  然后是阴影的表现,因为一部分模式要削减内存使用,所以阴影不能使用lightmap,而是要自动的生成阴影。具体算法方面,一大变更就是前作是硬件PCF,而本作采用了VSM(variance shadow maps),Cascade的分割数量也从2个增加到4个,阴影Texture的数量在2张1024x1024的基础上,又增加了2张2048x2048,另外,前作使用的Mapping算法LiSPSM在本作中继续是使用。

 

 

  下图是比较的画像,左图是前作的实现方法绘制的阴影,右图是本作的方法。因为前作并用ShadowMap来自动生成背景的阴影,可以看到左边画像里有很强烈的锯齿感。


 

角色

  然后是角色,这次的角色实现了新的受伤表现。这样就必须要为100个多角色制作受伤表现的新模型。

 


  左图是没受伤的状态,右图是受伤状态

 


  佐助的受伤表现,左边是受伤前的模型,右边是受伤模型的前面和背面。

 


  天天的受伤前后的模型对比。衣服下摆破损的表现,在原始模型上也浮现出污泥和伤口表现。

 


  还有就是已有的模型,这里使用背景中使用的Decal来做受伤表现。左边画像是调试显示的Decal的绘制空间,中图和右侧放大图则是实际绘制的受伤表现。

 


  同样,左图是调试显示的Decal绘制区域,右图是游戏中的效果,分别对应角色的骨骼来关联Decal,骨骼动画时Decal也会运动。

 


  全身像,左图是受伤前,右图是受伤后的正面和背面。战斗中最多显示6个角色,每个角色最多设置14个Decal。

 


  和背景Decal不同,受伤的Decal必须要由美术师来设定位置,制作了专门的设置工具,在画像的对话框里调整参数,设置Decal和骨骼的关联以及显示的位置,还有帖付的Texture和大小等。

  这种使用Decal制作的受伤表现,制作一个角色节省8个小时,也就是一个员工一天的工时。但是这样也有问题,因为Decal的特性,它无法设置在关节上,以及披风等飘动的物体上。还有因为设置场所的限制,美术也有感觉很麻烦的意见。

 

 

  然后就是轮廓线的表现,这次扩展了3个功能,分别是附加了Glare的信息,轮廓线颜色的分别改变,以及线的粗细幅度的调整。

 


  左图是前作的轮廓线显示,右侧是本作的轮廓线,轮廓线颜色变成了蓝白色。

  然后就是线的粗细,挤出的幅度的调整功能,以前的究极风暴系列,使用的是后处理绘制和把角色的多边形复制,反转来挤出轮廓线的方式来绘制轮廓线。这次实现的是,通过顶点颜色来控制轮廓线挤出幅度的功能。但是这样,无法对后处理绘制的线进行调整。不过也就是主要角色的头发部分使用了后处理来绘制轮廓线。

 


  左上画像是顶点颜色的可视化,接近红色的地方线粗,接近蓝色的地方细。右边画像是实际绘制的结果,左下画面轮廓线颜色变成青色,根据场景不同,粗细也可以变化。

  这种挤压幅度的调整,因为工时的限制,只在一部分角色上使用了。

  接下里是模糊的表现,对前作的动态模糊做了改良,实现了新的动画模糊效果,

 


  鸣人的忍术移动动作的场景。

 


  进行忍术移动的鸣人扩大图,角色的左侧变的软绵绵的,这次实现的是沿着行进方向的动画风格的模糊表现

  实现方法上,先是在角色前面配置覆盖角色的板型多边形,在多边形上贴付法线贴图,沿着法线对绘制角色的场景进行扭曲。在进行扭曲时,可以利用速度Map对扭曲的强度和法线Texture的调整速度进行设定。这个速度Map是在前作中的运动模糊里使用的,保存的是前一帧的模型的位置矩阵坐标与当前帧的模型矩阵坐标相比较的移动量。

 

 

后处理

  接下来,就是为匹配各个场景的场面而实现的颜色修正的后处理表现,这次为了更好的场景印象,全部场景都进行了新的色调调整。其中包括variation功能和Tone Curve功能。首先,是variation功能,下图是使用前后的对比。


    
 

 

使用了第1个样式的变化,整体变青色

 

样式2,和前一个相比整体变亮。

 

样式3,整体变红。

 

  以前开发游戏,是在真机中测试好参数,再把实时的设定输出到文件里保存,这样如果项目扩大,管理成本的消费也会变得很高,但实时的反映来确认效果,确实有很大的魅力不能放弃,所以在本作中使用Photoshop进行大量场景的调整。具体上,使用了PS上的标准variation功能,并把设定后的参数保存为可以真机读取的.AVA格式。

 

 


  右图是使用PS variation功能的调整画面,美术师把保存的背景截图在这个画面里进行编辑,而左图是以前的设定参数画面,可以看到比以前方便了不少。

  然后是Tone Curve,下面是使用前后的对比,以前也是通过专用工具来设定,在本作中variation一样,通过PS来制作。
 

  

  使用前后的对比

  具体的实现方法,先制作256x4的Gradation Texture,然后把通过截图调整的ToneCurve的效果设定到Gradation Texture上,在真机上使用这个Texture,就可以在游戏里显示Tone Curve的效果。

 


 

  其他使用的后处理,还有Fringe效果和鱼眼效果



 

  Fringe的功能,画面边缘的方向色相差变大

 


  鱼眼功能,地面变成曲面,在奥义表现的故事模式里使用。

粒子

  最后,是游戏里的粒子处理负荷优化的相关话题,本游戏的粒子表现,主要包括通常角色使用的技能特效,Boss战的表现,以及一部分的破坏表现。为了对应大量各种粒子的使用用途,像角色使用的复杂处理的Shader一样,粒子也分配了相对复杂的粒子。而通常的粒子,一般是使用Billboard来绘制,也可以用大量多边形构成的模型。


 


 

  左边是关闭粒子绘制的表现,右边是绘制粒子的表现,通过增加场景中的信息量,制作出了非常有迫力的表现。

 

 


  前面龙卷风场景的放大图,红圈部分是Billboard的粒子,蓝圈部分是大量多边形构成的粒子,使用大量多边形构成的粒子在可以获得不错外观的同时,实际绘制的粒子数也更少一些。

  表现的介绍就到此为止,本作是把旧世代的资源在新机种上使用的,所以硬件机能并没有完全利用到,所以在性能的改善和新效果上还是有提升的余地,因为游戏角色数量超过了100个,要对应每个角色都实现新的技术也是很难的,特别是提升一个角色的品质的工时消耗上,要有准确的把握。尽管本作没有在渲染引擎上做根本的变革,但还是制作出了次世代的绘制表现。

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