为什么游戏画面会产生撕裂?垂直同步与防撕裂技术分析

为什么游戏画面会产生撕裂?垂直同步与防撕裂技术分析很多朋友在玩游戏的时候都可能遇到过下图这种画面撕裂的情况

很多朋友在玩游戏的时候都可能遇到过下图这种画面撕裂的情况。尤其是对于FPS玩家,这种撕裂在迅速转动镜头时非常明显。

077045fc81b62743820621bf36c294b3.png

不过通常游戏设置里面都会有相应的选项来进行调整,比如是否开启垂直同步,是否启用三级缓冲等,打开之后画面撕裂的问题就会有明显的改善。

除了垂直同步以外,我们在购买的显示器和显卡的时候也可能听说过G-Sync、FreeSync等相关的技术,那么这些概念到底是什么意思?他们又是如何解决画面撕裂的问题呢?

0b94e9b66b87e0af2ab8923b07eb8122.jpeg

撕裂原因

首先我们需要先从画面刷新的基本原理讲起。对于任何一个显示器,其屏幕画面的更新都不是瞬间完成的,而是要从上到下进行逐行扫描刷新,整个屏幕刷新一次是需要一定时间的。

华为手机支持960fps录制,本地显示器录了一段,可以明显看到逐行更新。

我们常说的60HZ显示器其实表示的是屏幕刷新率,也就是显示器每秒可以更新60次。但单次从第一行扫描到最后一行时间并不需要16.6ms(1s/60),也许5ms就可以搞定。

另一方面,屏幕要显示的画面数据其实来源于GPU的Buffer,而GPU往buffer里面写数据的速度与显示器是无关的。GPU产生帧率与显示器帧率往往不一致,如果不加以同步就必然产生撕裂,简单来说,GPU会在显示器读取buffer时把buffer改成下一帧内容,导致显示器上半屏是后一帧图像,下半屏是前一帧图像。

下面是在apex中关闭垂直同步录的,

可以看到其中有撕裂

3be5578275b26fcc5018514f96e4f2ca.png

双缓冲

双缓冲是显卡的渲染基本特性,GPU会使用两个buffer,每次渲染完后都把画面写入backbuffer。而显示器只从frontbuffer读取画面,通过交换指针来交换两个buffer,这个操作可认为是瞬间完成的。

6bf53b5b78124090d0348c79e91d14cf.png不过swapbuffer时,显示器还没读取完frontbuffer,依然会产生撕裂。

1dac4837393c19337825a9e4dd0f5923.png

垂直同步

双缓冲下,想要不撕裂,就需要保证显示器在显示完一个buffer后,再去swapbuffer,这就是垂直同步。简单讲,就是显示器在显示完后会向显卡发送一个v-sync信号。

不过垂直同步有两个明显的的缺点:

1.锁帧,这会把游戏帧率限制到显示器帧率。比如你使用的是60帧的显示器,那么无论你使用的是I9的CPU还是4090的显卡,在fps游戏中,玩家操作依然会有明显的延迟。比如下面情况(使用unrealInsight工具进行性能分析),开垂直同步锁了60帧之后,会发现CPU一直都在idle。

16db64f244df157c6154d43223640269.png

2.降帧。当GPU帧率低于60帧,或突然下降时,比如45帧,最终显示的帧率会变成30帧。

关于第2点,我们再进一步分析一下

理想情况:GPU输出帧率高于60帧,输出一帧画面后等v-sync信号,最终显示器顺序输出每帧图像

23818b21fe3a212a9098c2f4cd1fe07a.png

帧率低的时候:当游戏卡了一下,GPU不能在16.6ms内完成一帧时,显示器产生v-sync信号后,发现没新数据,下一帧就继续使用老数据,导致两次显示了同一帧。再等到下一个v-sync信号,GPU输出了第三帧画面,正常显示,我们会发现中间的第二帧画面丢失了。

6f8d0d4d0f007bff5a827d29ee33e107.png

另外考虑如果GPU稳定以45帧输出画面,那么每两个v-sync信号只有一个会显示新画面,最终显示器输出的是30帧。

三缓冲

对于低帧率和帧率波动情况,可以用三缓冲来缓解,当帧率高于显示器帧率时,依然是垂直同步锁帧方案。

728d7897b8944a07e3091fddf3542e8d.png

可以再加一个backbuffer,让GPU在完成一帧后不等垂直同步信号,接着运行,把数据写入另一个backbuffer。当swapbuffer时,顺序选取下一个buffer,相当于多了一个蓄水池。

d324e3446c974ee0d6226cefb40b2e06.png

b7cbc3bb7fe285f1095b6f007de23c6e.png

比如上图,GPU错过了第二个v-sync信号,就把图像缓存起来,第三个v-sync信号时就能显示第二帧图像了。

这里注意,注意GPU每帧输出的图像都必须顺序显示,中间不能丢。而且第一次GPU遇到卡顿的时候是无法避免丢失的,因为那个时候另一个backbuffer里面还没有东西。

这样偶尔有一帧卡,因为多了个缓冲,依然能以60hz输出图像给显示器。当GPU稳定45帧运行时,显示器也能以45帧输出图像,而不是30帧。

但这样也存在问题,帧的逻辑时间可能长短不一,但最终都以16.6ms间隔显示在屏幕上,想象一个匀速直线运动物体,前一帧移动了16ms的距离,后一帧移动了26ms的距离,那么反映到显示器上物体移动就不匀速了。目前看,这种情况无法避免,因为GPU输出的画面是对游戏世界的离散采样,只有让帧率足够高,才能缓解这种问题。

Apex里的垂直同步选项里可选双缓冲和三缓冲,而且解释也比较清楚。

23c91d3573601a41666cafc1463c6ecf.png

另外三缓冲不是游戏独有的技术,普通软件也能使用。安卓早期UI不流畅,因此在Project Butter中引入了vsync和三缓冲,app都可以使用该特性,也可以用开关mLayerTripleBufferingDisabled进行控制。

Android 之 Project Butter 详细介绍

https://www.jianshu.com/p/aea19baa3608

可变帧率显示器 G-sync Freesync

可变帧率显示器就是freesync和G-Sync技术,分别是AMD和英伟达的技术,要有对应显卡来让显示器帧率与GPU输出画面帧率同步。比如GPU在某段时刻的帧率分别是50,51,57,那么显示器也会立刻改变自己的显示帧率。这样可以做到延迟最低,也不会撕裂。那这个时候是不是还需要开启垂直同步呢?

开垂直同步

帧率依然会限制在屏幕最高帧率,只是GPU画面不需要等v-sync信号,显示延迟更低。

关垂直同步

不锁帧,GPU帧率低于显示器最高帧率时,也不会撕裂,GPU帧率高于显示器帧率,还会撕裂。

因此只要GPU帧率低于显示器帧率,垂直同步开关没影响,都是不撕裂+立即显示,就看游戏能不能跑到更高帧率了。

找了一台支持G-Sync的144hz显示器,关闭垂直同步,游戏稳定100hz左右,确实一直处于流畅状态,也没有撕裂。

3677118057625c364bda9e8e8bf45ece.png

FastSync/EnhancedSync

有没有办法在普通显示器上也实现既高帧率,又不撕裂?可以,回顾三缓冲方案,如果GPU帧率很高,可以在两次v-sync间输出两帧,那么就写入两个backbuffer,下一次v-sync来时,选取最新的backbuffer即可,另一个丢弃。这样就既开启了垂直同步,又不锁60帧,能尽快显示最新的画面。这种方式不妨称为FastSync。

cf271cb1a050d113dddc284af615c68d.png

这么做输入延迟高于关掉v-sync,但低于开v-sync,很适合fps游戏。

不过依然有最高帧率限制,在两次v-sync间如果把backbuffer都写满了,还是要等,最高帧率为(backbuffer数*显示器帧率)。假如一个游戏backbuffer开了3个,对于普通玩家的60帧显示器,最高帧率可以到达180,也基本够用了。

在虚幻引擎中,r.D3D12.UseAllowTearing和r.D3D12.SwapChainBufferCount分别控制了是否开启FastSync和backbuffer的数量。

863c0aab4ec5d23b37e1506e770bafc7.png

映射到对DX接口的操作在这里

8a48cf2fdbbf3e6b0bb81d578eaf46ca.png

如果使用了这种方式,注意开启防撕裂时要关闭垂直同步。

建议

  • 如果只是普通显示器,而且GPU帧率是显示器帧率的2倍或3倍,就使用FastSync/EnhancedSync。

  • 如果显示器支持freesync或G-Sync,fps游戏就不开垂直同步了。

  • 尽量不要使用双缓冲的v-sync,用三缓冲的。

参考:
Android 之 Project Butter 详细介绍:https://www.jianshu.com/p/aea19baa3608
什么是画面撕裂?垂直同步,G-sync,Freesync到底有啥用?:https://zhuanlan.zhihu.com/p/41848908
AMD:https://www.hardwaretimes.com/what-is-v-sync-should-you-turn-it-on-or-off/
垂直同步到底要不要开?:https://www.bilibili.com/video/BV16x411e7bp/

 往期文章推荐 

游戏开发技术系列【想做游戏开发,我应该会点啥?】

虚幻引擎技术系列【使用虚幻引擎4年,我想再谈谈他的网络架构】

游戏科普系列【盘点游戏中那些“欺骗玩家眼睛的开发技巧”】

C++面试系列【史上最全的C++/游戏开发面试经验总结】

我是Jerish,网易游戏工程师,6年从业经验。该公众号会定期输出技术干货和游戏科普的文章,关注我回复关键字可以获取游戏开发、操作系统、面试、C++、游戏设计等相关书籍和参考资料。

今天的文章为什么游戏画面会产生撕裂?垂直同步与防撕裂技术分析分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/79559.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注