东方吧 关注:658,582贴子:17,963,757

【弹幕程序科普计划】 第五篇 帧率控制(表)

只看楼主收藏回复

画张图镇楼,顺带吐槽B站兴趣圈域名。。。

【帧率控制(表)】
  从上次文章我们了解了同调弹幕所面临的技术问题,并介绍了两种针对性解决方案。今天将介绍第三种方案——通过改进帧率控制方法,将帧率恒定在60fps,消除累计误差,从而使同调弹幕成为可能。
  那么,我们先来看一下传统的帧率控制方法。
  对于STG这种按帧推进的游戏,要使游戏运行速度恒定,就必须使游戏帧率恒定。正常游戏帧率都是60fps。为了将游戏帧率稳定在这个数字,无非通过两种方法,一种是依靠垂直同步,一种是自己写代码通过定时器发出渲染信号。
  首先来看垂直同步。这个词大家可能很熟悉,但是并不一定知道这是指什么和什么同步。其实显示器的刷新率和游戏的帧率不是一回事。游戏的帧率可以变化,而显示器的刷新率总是60fps。或者说,显示器刷新的时间点与游戏渲染画面的时间点并不吻合。所谓垂直同步,就是将游戏渲染画面的时间点与显示器刷新画面的时间点同步起来。当开启垂直同步时,渲染出来的画面不是马上显示到屏幕上,而是会等待显卡的同步信号,接收到同步信号后再显示到屏幕。这个同步信号的频率必然和显示器的刷新率相等,如果显示器刷新率是60fps的话,开启垂直同步后游戏的帧率也会是60fps。所以开着垂直同步的话,就直接可以控制游戏帧率了。不过上次文章也说了,显示器刷新率其实也并不是那么可靠的数字,不一定是精确的60fps,而且开着垂直同步有时还会有一些负作用,所以游戏往往还是需要配备一套不使用垂直同步的帧率控制方法。
  如果不使用垂直同步的话,渲染出来的画面就不用等待同步信号而直接渲染至屏幕。那么要控制帧率的话,就必须通过定时器来控制渲染画面的时机。这个动作可以简单概括为“每隔16.667毫秒渲染一次画面”。理论上是非常简单,但实际上这个方法非常有讲究,包括精度问题、定时器的实现问题,不过这些不是今天的重点,我们先放一下。今天我们只谈一下传统的控制方法为什么不适合做同调弹幕。至于为什么不适合,其实原因很简单,因为这是一个增量式的控制。所谓“每隔16.667毫秒渲染一次画面”,也就是说从上一幅画面渲染开始,经过16.667毫秒后渲染下一幅画面,如果中间出现运算量过大,发生延时,则下一幅画面开始渲染的时间点就会推迟,之后的画面统一延后。这样的机制必然会形成累计误差,即使是很小的帧率波动,累计到后面,都足以破坏版面与BGM的同步性。
  至于怎么避免累计误差,这个思路也很简单。之所以会有累计误差是因为渲染时机是相对上一帧画面延后16.667毫秒确定的,如果渲染信号不是相对于上一帧画面而是相对于第一帧画面,就可以消除累计误差。这个逻辑可以简单表述为,如果当前时间为16.667毫秒的整数倍,就进行画面渲染。
  下图示意了传统帧率控制方法与改良后帧率控制方法的差异,其中横轴为时间轴,刻度表示渲染的时间点。当帧率稳定时,各渲染时间点间隔相等。当发生了一个延时或者卡顿时,传统方法会将之后的渲染画面相应延后,以保证当前帧率为60fps。而对于改进后的方法,整体的渲染时间点不受延时或卡顿影响,当发生延时或卡顿后,画面会以最大速度渲染,以追赶整体进度。

  在换个角度讲,传统方法是在保障当前帧率为60fps,而改良方法是在保障平均帧率为60fps。因此可以通过改良后的方法来消除累计误差,为同调弹幕提供技术支持。因为这种方法依据的时间不是上一帧的相对时间,而是绝对时间,所以我称它为绝对帧率控制法。
  不过,这种方法存在一个比较显而易见的问题。如果游戏发生了持续的延时或者说掉帧,那么之后游戏会持续地对画面进行极速渲染以追赶整体进度。举例来说,Boss某张符卡堆了10000颗子弹,游戏帧率掉到了30fps,持续了十几秒,这张符卡一过,全屏消弹后,游戏会为了追赶整体进度而持续极速渲染,为此游戏可能会持续几秒钟运行在几百fps。这样给玩家的体验就是游戏先掉帧掉了十几秒,然后又加速运行了若干秒。如果是传统的帧率控制方法,可能仅仅只是掉帧这个缺陷而已,而改良后的方法又多出了加速运行的问题,反而使事情更糟。为了防止这种情况发生,必须为这种帧率控制方法配套一种主动丢帧策略。当游戏卡了超过指定帧数后,主动放弃追赶整体进度。或者说,设置一个追赶最大值,当游戏掉帧后,全速渲染追赶整体进度时只能追赶指定帧数,如果超过这个指定值后,则放任其掉帧,延后游戏进度。
  关于这个指定值,如果设得太大会存在游戏加速问题,如果设得太小则会存在累计误差问题。极端情况,当其取为无穷大时,则效果和没有这个值一样,游戏会无限追赶整体进度;当其取0时,则效果和传统帧率控制方法一样,游戏在卡顿后不会追赶整体进度,从而形成累计误差。具体取多少合适,需要根据实际情况,根据个人喜好来定。这里提供一个经验数据,从《东方百花宴》到现在的《弹幕音乐绘》,我这里这个值设的都是10帧(166.667毫秒),也就是说,游戏会把10帧以内的瞬间延时给消化掉,10帧以内的瞬间延时都不会造成累计误差,但是更大程度的延时或卡顿就会造成累计误差了。从实际效果看,10帧这个容忍量大大提高了同调弹幕的可行性。
  这种帧率控制方法是我3年前制作《东方百花宴》的时候研究出来的,但是并不一定是我率先使用的。东方STG的资深玩家一定知道有个叫VP补丁的东西,可以用于消除东方早期几部作品的操作延时并稳定帧率。从VP补丁的现象看,有两点与这种帧率控制方法吻合,一个是帧率持续稳定在60fps无波动,另一个是使用了伪全屏。因此VP很可能就是使用了这种帧率控制方法。关于为什么要使用伪全屏,这牵涉到取消垂直同步后的画面缺陷,称为画面撕裂现象。至于什么是画面撕裂,其原因是什么,怎么解决,这些问题将在下次文章介绍。
  总结一下,加上上次文章所介绍了两种方法,总共讲解了三种支持同调弹幕的技术方案,分别为《Akashicverse》使用的“按帧推进和按时间推进相结合的版面控制逻辑”、《IKUSAAAAAAAN!》的“BGM重定位法”以及上文介绍的“绝对帧率控制法”。其中第一种方法由于会影响到Replay存储功能,有些得不偿失;第二种方法可以在任何情况下将BGM与版面强制同步,其缺点在于同步时BGM会发生卡顿现象;第三种方法可以消除小范围帧率波动带来的累计误差,其缺点在于不能使用垂直同步,画面会有一些缺陷。值得注意的是,第二种方法和第三种方法其实并不矛盾,可以共用。现在我这里还没有把BGM重定位法完全调通,不过说不定在《弹幕音乐绘》剧情篇完成时就会同时使用这两种方法,为同调弹幕加上双保险。
  最后还是要说一句,无论用什么技术手段来保证同步,都无法挽回画面持续卡顿及持续掉帧引起的后果。即使是《IKUSAAAAAAAN!》这种强制同步的方法,在持续掉帧时也会造成BGM断断续续,甚至支离破碎。因此在制作同调弹幕时,怎么合理控制弹量、合理布置特效,这依然是创作者必须经历的课题。
以下广告时间:
本系列过往文章将收录在弹幕音乐绘的哔哩哔哩兴趣圈中,欢迎关注
http://www.im9.com/community.html?community_id=12241
游戏《弹幕音乐绘》近期会开始刷存在感,以下是游戏宣传页面:
http://www.slimesmile.cc/
P.S. 近期B站圈子频繁抽风,如果之前的帖子不显示,可通过置顶索引贴来找到过往文章。


IP属地:上海1楼2017-02-04 18:28回复
    前排支持。


    IP属地:浙江来自Android客户端5楼2017-02-04 18:44
    回复
      2025-07-30 07:15:49
      广告
      不感兴趣
      开通SVIP免广告
      感谢讲解


      IP属地:上海来自Android客户端12楼2017-02-04 18:53
      回复
        都被机器人占领了,明明这么好的帖


        IP属地:上海15楼2017-02-04 19:00
        回复
          围观


          IP属地:福建来自Android客户端16楼2017-02-04 19:11
          回复
            东方吧该管管机器人了..好文


            17楼2017-02-04 19:15
            回复
              支持一个,玩夏夜祭就有游戏会加速跟上进度的感觉,没想到果然是这么一回事呢2333


              IP属地:广东18楼2017-02-04 19:17
              回复
                吃完晚饭回来看到一串机器人回复,不得不感叹一下现在人工智能发展迅速。。。


                IP属地:上海20楼2017-02-04 19:48
                回复
                  2025-07-30 07:09:49
                  广告
                  不感兴趣
                  开通SVIP免广告
                  感谢科普


                  IP属地:河北来自Android客户端21楼2017-02-05 10:58
                  回复
                    原来是这样,怪不得有时候游戏会出现超过60帧的情况


                    IP属地:江苏来自iPhone客户端23楼2017-02-05 11:36
                    回复
                      支持


                      IP属地:北京来自iPhone客户端24楼2017-02-05 12:05
                      回复
                        原来是这样子啊,感谢科普。玩夏夜祭的时候出现过弹幕掉帧减速后又突然加速超过60帧,老实说避弹的时候真的被突然的加速坑过。


                        IP属地:浙江来自iPhone客户端25楼2017-02-07 00:11
                        回复
                          支持


                          IP属地:四川来自Android客户端27楼2017-02-26 12:26
                          回复
                            如果有道中的话就不好控制音画同步了吧 击破boss时间不确定


                            IP属地:浙江来自Android客户端28楼2017-04-18 08:31
                            收起回复