第二十一期 超稼动

 
发布日期:2018年7月5日




大家好,这里是深夜挖矿节目肥猫池塘第二十一期
我是精锐战猫

在19期里面我们讲到了dnf里面作为动作游戏的一些核心设定
而这一期我们会谈一下一个游戏同样举足轻重的一个地方:图像
dnf里面的画面到底是怎么形成的,里面的动画到底是怎么动起来的
dnf是否真的吃显卡?帧数高有用吗?
这些一切尽在今晚的肥猫池塘21期中





Sprite

相信做过补丁的朋友都会了解到dnf的imagepack2文件夹是dnf这个游戏最主要的图像文件存放地
而里面的文件名都是清一色的这个前缀:


sprite到底是什么东西?
百度的话,会找到这个解释

当然意思绝对不会是雪碧
顾名思义,sprite就是所谓的“精灵”的意思
sprite在游戏里是指一个图形控件,指的是把一张或者一堆图像进行封装,命名为一个sprite对象,而这个sprite可以接受放大、缩小、动画播放、混合模式等一系列的属性调控,作为一个独立的渲染对象而存在的图像封装就是sprite


这是一个gif,为dnf的npk文件里面的img文件导出之后的动态图片
导出后为这样的png

可以看出游戏里面的动画就是一张张透明底的png以一定的顺序播放之后获得的连续图像

dnf这个游戏实际上就是一大堆png通过程序的安排在不同的地点组合播放形成画面
这是大部分2d游戏的成像机制,有很多人根据这样的原理,吐槽dnf就是一个“贴图游戏”
实际上这个说法是错误的,包括3d在内的所有游戏都是所谓的贴图(texture)游戏





Draw Call

Draw Call,简称DC,顾名思义,就是“描绘请求”的意思
DC是游戏利用cpu去调用gpu的渲染指令的一个过程,非常直观,cpu处理游戏的描绘的时候,意识到这里需要显卡去进行描绘,就会命令显卡去描绘这个地方,这样的一次请求发送就是称之为一次DC

DC以帧为单位,在一帧内cpu根据游戏的情况发送的描绘请求的总量,称之为DC数
DC数是一个游戏是否流畅的一个因素之一,如果DC数过多的话,CPU发送的指令过多GPU反应不过来,就会造成卡帧
常见的3d游戏DC数能维持在200左右的话就是相当标准的高优化游戏,dc数的质量是不对等的,例如命令显卡去渲染一个png序列形成的ui和一棵单一贴图的树,后者更加考验显卡的多边形计算能力,但3d游戏并不是本文要说的东西,总的来说dc数是能够保证画质不被阉割的前提下越少越好


dnf作为一个2d游戏,DC数在战斗时可以接近过千,是一个名副其实的高端游戏(实际上这个数量比大部分主机游戏还要凶残很多)
如果抱着2d游戏=落后的思想去看待游戏的话,这个思想本身就是落后的,其实可以把2d游戏的每一个贴图都看成一个3d多边形面,这样可以理解成dnf压根不吃显卡的多边形性能,也就是显卡的“质”,而是吃它的"量",显存+显卡的运算速度
很多人认为dnf吃显卡就是来自于这个理解,至于是不是真的吃,那就见仁见智
这也是用垃圾板载显卡都能玩这游戏的原因

dnf因为其可怕的dc数实际上在运行时已经不输给主流主机游戏了
不过很大的原因在于韩方制作组对这游戏的优化不足的原因
这游戏是03年时候一个不过十人的小组研发的,理所当然地,当年技术力不足的原因,这个游戏的整体架构实际上非常落后,甚至在十几年之后的今天也是使用这个架构的基础上继续添砖加瓦,自然是一场恐怖的灾难





Sprite Sheet

按照dnf原理来说,一次dc的过程是这样的
情形:地图上有两个哥布林和一个鬼剑士,一个拥有血槽和mp槽的界面
在一帧里进行了这样的渲染请求
哥布林_1帧→哥布林1.png
drawcall
哥布林_4帧→哥布林4.png
drawcall
鬼剑士_134帧→鬼剑士134.png
drawcall
hud→hud.png
drawcall
hp_bar→hp_bar.png
drawcall
mp_bar→mp_bar.png
drawcall

可以看到整整使用了6次的drawcall,当然这只是很简单的一个例子,实际情况没有如此简单

假如地图上有10只哥布林,鬼剑士夹在这堆哥布林之中,这时候的dc提交是这样的
哥布林
哥布林
哥布林

鬼剑士
哥布林
哥布林
哥布林

可以看出其实有很多请求是看上去是重复的,那么有没有办法将这些重复的东西整合在一起呢?
答案是可以的,但dnf里面并没有做这个机制(至少目前还没有完全普及)

这里面就要提到一个叫Sprite Sheet的机制了
所谓的Sprite Sheet(图表集)实际上就是把一大堆的散件png,整合为一整张的Tex图,如下图



在进行加载的时候,系统会把这一整张的tex图全部加载到内存中,再使用定义法定义每一帧的起始xy点和结束xy点,这样实际上就是把一个动画封装到了一张图里面
这样做有什么好处呢?

这里要提到dc的一个机制了,实际上dc不会认精灵,他们认的是精灵里面每一个独立的图像文件
在渲染的时候实际上是把里面的独立帧单独抽出来渲染,例如地图上有十只哥布林,他们的动作是不可能协调一致的,即使有两只哥布林恰好处于相同帧数,实际上这堆哥布林在一帧里面也要提交至少9次的dc
更不用说两个下面提到过的更加可怕的东西

而Sprite Sheet就是解决这样的情况的一个手段了,把几十帧“封装”为1张图片,dc认这一张图片,对这个图片进行整体的渲染
而这十个哥布林用的实际上是同一个纹理(Texture)文件,地图上存在重复的哥布林的时候,只要他们是使用图表集分割的动画,就是共用连续的纹理,不需要分开十次dc,而是整合为1次

dc提交这时候会变成这样
哥布林
鬼剑士
哥布林


原先的11次的dc变成了3次,上面提到了“连续”一词,那是因为鬼剑士夹在这堆哥布林中间,遮住鬼剑士的哥布林和被鬼剑士遮住的哥布林绘图顺序是有先后的,纹理在描绘鬼剑士的时候停止了连续,所以要先描绘了鬼剑士然后再描绘剩下的哥布林,造成了3次dc的情况

当然上面提到的ui也可以用图表集封装为一张tex,让原先需要消耗3次dc的ui变成一次
在压榨显卡性能的3d游戏里面,为了流畅自然需要进行各种的优化,这个方法其实就是3d游戏见得最多的一个优化方法
例如一个角色的模型分成了头发、头、身体、手、脚五个部位,如果用传统的贴图法弄,渲染这个角色要用到5次dc,相当浪费系统性能
用这个图表集办法把五个部位的贴图整合为一个贴图,这样就只需要dc一次,大幅度减少系统的消耗

dnf的开发者笔记也提到过他们陆续努力实装这个方法对游戏进行优化了


通过整合ui去大幅度节省dc数,毕竟这一个ui就要花了过百次dc……

当然这个办法不是万能的,整合图片意味着要消耗额外的内存去存放这一个实际上非常大的大图
在某些情况下甚至比散图还要消耗性能
但是这个方法依旧是游戏制作的一个主流,也是最基本的一个要求
dnf到了现在才去实现的原因纯粹就是当初技术力过于落后…………现在在还债





Avatar和色表

Avatar来自于印度语,意思是化身
来到游戏里面,是指“纸娃娃系统”
所谓的纸娃娃其实就是时装系统,大部分网游为了骗钱,都是把角色设定为可以自由换装改变外形的
纸娃娃系统就是为了实现这个换装系统的重要措施

假设有一个角色,他可以拿着两种不同的武器进行战斗,这时候角色的素材会如何安排
是画两套动态图,一个是拿着武器A的角色,一个是拿着武器B的角色吗?
不对的,而是画三套动态图:空手的角色,武器A,武器B





通过一一对应坐标系,把武器A的帧数对应空手角色的帧数一一拼合,就可以生成角色拿着武器A的图像了



这就是纸娃娃的原理

同理,dnf里面的角色就是分成了10个部位的纸娃娃拼合在一起的角色,以角色的裸体为底盘,在上面一层层叠加衣服等独立的部位
这个的确是一个划时代的发明,但是用到dnf里面就是灾难
按照dnf的系统,这十个图层其实统统都是独立的,去月光酒馆看看就知道,可以透过半透明看到角色的裸体


独立就意味着每一个部位都要独立进行dc,换句话说单就一个apc角色而言,需要dc十几次
走在赫顿马尔广场上面,可以感觉到一股卡顿感扑面而来……满大街都是角色,描绘都要描绘半天
所幸的是dnf做了白影系统,可以将不需要描绘的角色白影处理,这也是一个优化的方法

上面提到过3d游戏实际上可以通过整合tex来减少dc数,所以实际上3d游戏的纸娃娃比2d的要好做很多,这也是dnf先天的一个劣势吧
更可怕的一点就是dnf不止玩家有纸娃娃……


而色表,玩过mugen的人估计都很熟悉了



实际上在古早的街机游戏里面,就为了节省容量,而广泛使用色表技术来存放角色的素材
在古老的街机游戏里面我们可以看到很多相同造型但颜色不同的敌人
实际上这个就是色表技术的一个运用,这些敌人的模型实际上是同一个,只是我们把模型的颜色信息独立保存了
在实际游戏的时候,通过系统染色,生成不同颜色的敌人



色表模型实际上是记录了颜色着色区的一个基板文件,颜色版就是记录着色区对应哪个颜色的一个文件
假如一个传统的着色模型他的大小是16
那么有三个不同颜色的敌人,存放这些模型的容量就需要3倍的大小,也就是48
如果使用着色器办法存放的话,基板文件的大小将会是12,颜色表的大小会抽离出来为4
但是这个基板文件是可以通过颜色表着色变成正常的模型的,也就是说一个基板可以使用不止一个的颜色表
存放三个不同颜色的敌人所使用的容量实际上是12+4+4+4=24,比上面的少了一倍




颜色表可以让游戏的容量大幅度降低,而且从dc数上实际和普通做法是没有区别的
这个本来是一个2d像素游戏必须要有的功能,在dnf里面至少是2016年才开始使用
是的,在2016年之前他们一直都在使用最笨重的方法去保存贴图……






混合模式和辉光

混合模式是一个图像术语,指的是把一个图片作为底图,在上面铺上一个作为混合层的图片进行混合,两个图片的rgb指根据图像混合的公式进行计算,得到最终的效果
最常见的混合模式就是加法,也就是我们所说的“发光图层”
加法的原理相当简单,就是把两个图的rgb的数值混合起来,得到最终rgb值

例子:鱿鱼站在草地上,作为一个底图


这时候我们要把力法二觉的转职特效拼合上去


力法二觉的转职特效是有黑底的,直接放上去,就是这样的效果


这时候就需要用到混合模式来进行混合了
把表层的rgb一一对应底层的rgb进行加法计算,得到最后的效果:


黑色的地方哪里去了呢?因为黑色的rgb其实是(0,0,0)
所以黑色和任何图层进行加法计算,最后都只会得到底色

这个是最基本的混合模式,也是dnf里面唯一有的混合模式(……)

而辉光(Glow)则是一个非常常见的图像特效
效果就是让物体渲染发出一层光芒,营造材质感



辉光是如此常见,甚至随便一个游戏引擎里面都可以一抓一大堆
而dnf里面使用得最多的特效也是辉光
但是在dnf里面辉光不是由系统进行渲染生成的

dnf的图像引擎基本上就是20年前的游戏的水平
所以辉光这种需要用到渲染的东西压根在引擎里弄不出来
他们实现辉光的办法是在制作时候把辉光弄成图层………………



然后使用加法混合上去
这是一种相当原始的办法,让人不禁同情dnf的特效组是多么的蛋疼
同时这种方法也增加了大量的磁盘容量消耗,确实是一种没办法的中的办法






粒子效果

dnf里面也有粒子效果(Particle Effect)
不要看到粒子效果就觉得都是圆形的粒子,实际上粒子(Particle)的原意是“小碎块”
粒子效果是一个脚本文件,他定义了一个发射器,发射器是使用何种的方向和力度去发射粒子,发射器发射粒子的数量有多少,粒子的外形,还有粒子是否受重力影响等等


最常见的粒子效果就是喷火了,粒子效果特别擅长去弄这种不规则地喷出的特效,dnf里面也很常见这种很难用手绘来制作的效果

值得一提的是机械的引爆也是粒子效果






红眼觉醒时候吸收的血气也是粒子效果,而且是比较高端的程序实现的粒子效果

粒子效果的优点就是系统生成,每次发射的动画都是不同的,充满了随机性,很多游戏里面都大量运用了粒子效果去制作特效,但是dnf里面给人的感觉有点脑抽,因为有些可以粒子效果的地方他们是做成了png序列素材的,不过也不难理解,粒子效果没有我们想象中的那么好调教






卷轴

游戏实际上是使用摄像机去进行追踪视觉的
在dnf里面是以角色为中心进行追踪
而为了表达地图的空间感,我们会把地图做得比摄像机的视觉还要大,我们在地图上往前移动摄像机进行追踪时地图会被往后拉走,这个就是游戏的卷轴系统
卷轴系统让地图变得有空间感变得可能,很多古老的游戏由于机能限制是没有卷轴功能的

聪明的游戏开发者为了让自己的游戏变得更有立体感
他们会对地图进行分层
然后每个层的卷轴速度都不一样

以dnf为例,一个地图分成4个图层:Far、Middle、Main、Near
main图层就是我们角色活动的图层,给他一个基准值:100
而其他三个图层的卷轴速度分别为这样


这样我们在行走的时候,我们所在的地方会以正常的速度进行卷轴
而远景的卷轴速度只有主图层的一半
这样就可以营造一种迫真的空间感了,很多2d游戏都是用这个办法去表现纵深的



我印象中很深刻的就是恶魔城血族里面第三关的boss战,背景的卷轴速度是地面层的几倍
这样反而营造出一种boss在背景飞来飞去绕着塔顶打你的感觉
如何表现取决于制作者本身的意愿啊






帧数

帧数(Frame Per Second,FPS)是指游戏在一秒内成像的图片的数量
FPS60就是意味着游戏在一秒内,生成了60张图片

对于帧数的误解,常见于动画里面一秒24帧和游戏帧数的理解问题
还有我们人眼只能识别60帧,再多帧数就无法继续识别的误解

人眼最多识别60帧的说法是错误的,事实上根据不同人的眼睛的差别,能识别的帧数上限也是各不相同
120fps和60fps的确有完全不同的感受,这是很多人都能感受出来的

那么为什么动画片24帧就让我们感觉到足够流畅呢,而游戏连60帧都不够
这里就要谈到“动态模糊”这个概念了

动画本质上是快速的画面替换让人类的眼睛受到欺骗
但是实际上人类的眼睛能识别的帧数是很高的,24帧一秒的fps对于人眼来说可以说肉眼都可以看到卡顿
动画之所以流畅的原因是因为动画并不是按照帧去存放视频的,而是以“时间段”的格式去存放视频
举个例子,第一帧的时候世清在这里,第二帧的时候世清来到了这里


两帧之间实际上是进行了一个瞬间位移,我们眼睛只要足够锐利,就能看出其中的卡顿感
游戏也是相同的原因,渲染出来的图像是一帧帧连续的瞬间位移图像,只是利用了视觉停留原理欺骗我们他们在连续地"动"
每一帧之间实际上是没有途中位移的过程的

而动画就是忠实地记录了两帧之间的补充
和游戏里面只能生成瞬间的两帧不同,动画保存的是一整段时间,也就是说单位位移时候的全部过程是以一个变形的图像的形式保存的
我们看动画实际上是看一帧帧连续的时间段的播放,所以比起游戏更不容易看出卡顿感
我们看一些主播的视频比起实际游戏更加流畅的原因也在这里,视频记录的是游戏的时间段的过程,我们停下来一帧帧看甚至可以看到残影



这个残影实际上就是我们眼睛无法感受到太快的图像自然产生的一种错觉,被视频忠实地保留在视频里面了,所以显得流畅

所以游戏因为自身的特殊性,要让人感觉图像是连续的,就只能通过两种办法实现
1.更多的帧数,多到人眼无法反应过来
2.动态模糊

动态模糊就是一种特殊的游戏渲染法,它的原理就是模拟动画的机制,把两帧之间的过程用渲染的方法模糊仿真出来,因此一些游戏30fps也能让人感觉很流畅
当然,这个也是造成很多人觉得眩晕的主要原因,帧数低可以让人的眼睛大量产生卡顿感的感觉,造成容易疲劳,加上动态模糊就更加了,很多人玩3d游戏会觉得晕,其实很大程度上都是这两个原因

而不用动态模糊的话,就要靠纯粹的帧数去凑了
很多人就是为了得到更加流畅的dnf体验,购买更加高端的显卡去拖这个游戏,把fps拖到300多
其实我也不好意思说这个行为是错误的,但是我也不赞成这种做法
fps300意味着显卡一秒要重复dc1000次的过程300次
对显卡的负载是很大的,况且我们人眼压根看不出那么多的帧数
我个人建议够用就可以了,没必要追求极限,这游戏压根不吃显卡,为了玩这个游戏买显卡是本末倒置了

锁帧是很好地让显卡负载降低的做法,如果流畅度足够的话,还是把这个选项勾上吧


以上就是dnf作为一个2d游戏的一些图像运作机制了,不知道各位经过了解之后会不会对2d游戏进行改观呢?
2d游戏并不是落后的代名词,相反,高精度的2d游戏占据硬盘容量超过20G简直是正常不过了
2d游戏的执行比起3d游戏来说更卡也是很常见的,dnf为例,尽管本身优化垃圾,但是也侧面看出了一点很多东西是“极限”,而不是“不想做”
实际上按现在dnf的情形来讲,已经很难取得突破了,所以说彻底的架构重组才是出路啊
这期的内容就到这里结束了


行动快感!地牢与战斗机
 

回到目录