延迟是AR/VR体验的基础

原文: http://blogs.valvesoftware.com/abrash/latency-the-sine-qua-non-of-ar-and-vr/

译者注: 原文发表于2012年, 尽管当时的一些硬件条件限制如今已经没有了, 但我们能够从中学习到AR/VR的延迟解决思路. 另外, 译文略过了显示器的发展史


假设没有足够低的延迟, 根本不可能带来好的体验, 也就说大脑不会把眼睛看到的虚拟画面当成真实的. 所谓的”真实”, 不是指你能不能用眼睛分辨出它们是否为虚拟的, 而是说你能不能在移动头, 眼睛或身体时, 感觉出它们与真实物体不一样. 这当中的关键是虚拟的物体在你移动时, 必须一直保持在正确的位置上.

假设从你转头開始到画面绘制在新的位置上花了太长的时间, 那画面就会偏移了非常远, 造成VR中的抖动或者拖影.

那多少延迟才算多呢? 比你想像的要少得多. 參考一下, 游戏时从鼠标移动到屏幕光标更新通常有50ms甚至很多其它的延迟. 个人经验, 大于20ms对于VR来说是不可接受的, 有研究表明15ms(甚至是7ms)是一个临界值.

AR/VR对延迟的要求比传统游戏高得多, 是由于它们要求在你移动时保持真实世界的稳定性. 而传统游戏对于你来说, 大脑觉得你是在看一幅图像. 当你移动时延迟会造成画面出现偏移, 而不是在它原本应该在的位置

假设你以60度/秒的速度转头(尽管这听起来非常快, 但实际上比較慢, 由于人能够每秒转头超过100度), 延迟是50ms, 分辨率是1K x 1K. 当你转头时, 虚拟画面是基于50ms前的数据显示的, 也就是说它们的位置已经落后了3度, 这比你伸直手臂后看到的拇指宽度都要大. 换一种说法, 物体的位置已经差了30个像素, 也就是说看起来是非常明显的.

当然能够通过预測把绘制位置画到正确的地方, 这在大多数情况下是表现良好的. 只是, 当突然出现方向的改变时, 这个差异甚至比没有预測时更大. 所以, 这样的做法相同会让人感觉到非常大的差异, 由于转向是常见的一种情况.

另外, 延迟看起来是直接与晕动症相关的, 延迟越大, 症状就越明显.

所以, 我们须要把延迟减少到20ms, 可能的话越少越好. 就算是20ms在现有的硬件条件下也是非常难达成的, 至于7ms, 眼下根本不可能. 让我们来看一下为什么.

以下这些就是画一次AR/VR图像所经过的步骤:

  1. 追踪头戴显示器的姿态, 也就是现实世界中的位置和朝向.
  2. 应用程序基于取得的姿态数据绘制立体的场景画面.
  3. 图形硬件须要把绘制的场景画面传输到头戴显示器的屏幕上. 这一步叫做扫描输出, 须要顺序地从上到下, 从左到右地读取帧缓存, 并把像素数据通过连接线(如HDMI)传输到屏幕上.
  4. 基于收到的像素数据, 屏幕的每一个像素才会開始发射光子.
  5. 在某个时刻, 屏幕须要为每一个像素停止发射特定的光子, 这是由于像素并非持续点亮的, 或者由于下一帧须要显示新的颜色.

在3D管线中还存在一些额外的帧缓存, 这里先忽略掉, 由于这不是产生一帧AR/VR画面的组成部分.

我们依次来看一下这三部分:

追踪延迟与採用的系统硬件高度相关. 一个IMU(3轴陀螺仪和3轴加速计)的延迟非常低, 差点儿相同是1ms, 可是有偏差. 特别是位置数据是来源于加速计的两次积分, 偏差更大. 基于摄像头的追踪不会有偏差, 可是它的延迟更高, 由于要捕捉图像, 传输到计算机, 并进行图像处理来计算姿态, 非常easy就花费了10-15ms. 当前有一种没有偏差的的低延迟系统硬件, 来自于NDI, 能够做到4ms的延迟, 就是我们用来做延迟追踪的.

渲染延迟取决于CPU和GPU的能力, 还有所要绘制场景的图形复杂度. 大多数游戏并不会一直保持60FPS, 所以它们的渲染延迟都会大于16ms, 这对于AR/VR来说已经太高了. 老一点的游戏能够执行的更快, 甚至能够达到几百FPS, 可是相对的它们的画面比較朴素. 所以, 这里我们假设渲染延迟是16ms.

渲染的画面一旦生成, 就须要传输到屏幕. 特定像素的延迟通过取决于使用的显示技术, 并且与画面相关. 可是对于最常见的扫描输出技术来说, 最坏的情况是从帧缓冲绘制完毕到更新到屏幕上会花掉一整帧的时间. 假设是60FPS, 那最坏的情况就是16ms. 比如, 假设一帧画面正好在扫描输出開始扫描最上面那行时绘制好, 那么最上面那一行差点儿就没有延迟, 但最以下那一行输出到屏幕上差点儿相同就有16ms的延迟(理论上不会有那么多, 每两帧之前是有空白时间的). 也就是说, 渲染完的画面数据更新到屏幕上大约有16ms的延迟.

有时像素数据能够在到达时马上显示出来, 就是使用激光和OLED的屏幕. 有时会被缓存起来再显示, 就像顺序制彩色LCOS, 红色是同一时候点亮的, 接下来 是绿色, 然后就是蓝色. 有时像素数据会马上应用, 可是距离可见的改变会一点延迟, 如LCD面板会花费几ms切换状态. 另一些电视机甚至会缓存多帧的画面用于图像处理. 接下来的讨论我会基于最优的情况, 也就是说我们使用的屏幕会在数据到达时马上把像素转化成光子.

一旦光子发射出去了, 差点儿不须要什么时间就能够到达你的眼睛. 可是另一个地方存在延迟, 那就是像素产生的光子停止到达你眼睛的时间. 这看起来好像没什么影响, 但当你戴着显示器时是影响非常大的. 由于一个像素状态持续的时间越长, 那它就距离正确的位置越远, 也就是残影越严重. 从延迟的角度来看, 像射线扫描那样亮一下就灭, 远比OLED或LCD那样一整帧的时间都亮着要好得多. 非常多OLED和LCD显示器的残影现象比CRT要高, 这个问题比較复杂, 这里就不展开讨论了, 我们暂且假设这部分的延迟是零. 只是须要明白的是, 假设持续时间不为零, 那么对于60帧来说, 最坏的情况是额外多了16ms的延迟.

所以现的总延迟是4+16+16=36ms, 离20ms还差非常多, 更不用说7ms了.

所以, 要想达到理想的延迟, 有一些规则必须做出改变.

在追踪阶段, 比較直观的方式是通过传感器融合光学追踪和IMU. IMU能够提供低延迟的状态, 而光学追踪能够用于修正IMU的偏差. 做好这个是十分具有挑战性的, 并且市面上也没有现成的可用方案, 所以仅仅能对硬件规则做出一些改变. 合理实现的话, 传感器融合能够减少追踪延迟1ms左右.

对于渲染来说, 除了简化场景外差点儿没有什么能够做的. 对于PC来说, 仅仅有5年前的游戏画面才干满足3-5ms的渲染延迟. 当然, 假设你想做能够到处走动的AR, 那须要在移动处理器上实现非常低的延迟, 也许仅仅能做到2000年左右的游戏画质. 这就是为什么我觉得AR另一段非常长的路要走.

好了, 经过两个阶段, 我们减少了4-6ms, 非常不错! 但如今我们须要把渲染的像素显示到屏幕上, 这是须要改变硬件规则的地方, 由于60帧率的显示器须要大约16ms把数据扫描到屏幕上, 这就成了我们减少延迟到20ms以下差点儿不可逾越的障碍.

我之所以说”差点儿”, 是由于这在理论上是有可能实现的, 就是”与光束比赛”(仅仅是打个比如, 对于CRT来说才有电子光束): 每条或每块扫描线的渲染正好在读取它们之前进行. 这个方法(对于缓存整帧或顺序制LCOS是不起作用的)能够把延迟减少足够多, 前提是保证每条或每块扫描线在这些像素扫描输出之前渲染完毕, 通常大约几毫秒. 通过”与光束比赛”, 是有可能把整体的延迟减少到梦幻般的7ms.

非常不幸, 与光束比赛须要一种非正规的底层渲染方式, 由于每条或每块扫描线是分开渲染的, 并且在游戏的时间线并非在同一个点. 每块必须准确地在扫描输出时渲染, 否则与光束比赛就没有不论什么意义了. 这意味着你并非每16.6ms渲染一次, 而是每次仅仅渲染一小块. 假设屏幕被切割成16块, 那样的话每1毫秒就须要渲染一块. 既然还是有那么多像素要渲染, 那整个场景的数据结构相同也须要分块传输到指定区域. 这花费的时间应该比正常的帧渲染要高一点, 也就是说场景复杂度须要减少, 保证能够在3-5ms内画完. 想还原现代的3D游戏和真实度, 变得异常困难.

与光束赛跑另一个问题, 那就是须要避免区块之间在视觉上出现边界. 这可能是无法接受的, 由于就算是一些细线, 也会使人分散注意力. 为了解决问题, 须要扭曲一些线段来接合. 显然, 这些线段的数量越多, 产生的瑕疵越少, 当然性能开销就越大. 假设取得平衡, 与光束家赛跑就变得可行了, 可是它会添加复杂度和性能开销, 对于减少显示延迟来说, 这并非一个明智的的方案, 也许从根本上我就是错误的.

也许更简单的可行方案是把显示刷新率提高到120Hz, 这能够马上把显示延迟减少到8ms左右, 整体的延迟达到12-14ms. 既然我们能够渲染到200-333 FPS, 渲染是没有问题的, 那240Hz会更好, 整体的延迟会减少到8-10ms.

高帧率还能够提升显示质量, 像我之前说的, 能够减少晕动症. 如今仅仅有一个问题: 适用于头戴显示器的高刷新率显示屏多半还不存在.

举个样例, 如今的Oculus Rift原型机使用了LCD的手机屏幕做显示器. 这是能够理解的, 由于手机屏幕的产量巨大, 所以它们非常廉价并且广泛使用. 可是手机屏幕并没有理由执行在120Hz, 由于这对用户来说没故意处, 也就没有人会生产120Hz的手机屏幕面板. 理论上这当然能够做到, OLED也是, 但除非VR市场足够大驱动厂商进行面板设计, 或者高价进行定制, 否则市面上是不会出现的.

另一个相关的潜在方案: 在不提高帧率的前提下, 提升扫描输出的速度(也就是像素数据转化为光子的速度). 比如, 假设图形芯片能够在8ms内扫描输出一帧缓存, 而帧率仍然是60Hz, 那么扫描输出能够在半帧的时间内完毕, 剩下的8ms就不会有数据了. 假设显示屏能够在数据到达时马上转化为光子, 那整体的延迟就能够减少8ms, 就算实际的帧率还是60Hz. 当然, 更高的扫描输出速度能够获得更好的效果. 这个途径不会像提高帧率带来的显示质量的提升, 但它既不会提升渲染的负担, 也不会减少渲染的质量. 跟高帧率一样, 这种方法仅仅对AR/VR有意义, 所以须要显示屏技术的革命才会使它变成现实.

除了与光束比赛之外, 在现有的硬件条件下是没有方法达到足够低的显示延迟的, 这须要足够高的分辨率, 足够低的价格, 合适的图像大小, 小巧的体积和足够轻的质量, 还有适合消费级别AR/VR的像素养量. (你还会面临VR的宽视角和AR的透视挑战.) 有一个人须要站出来改变硬件规则, 这样显示延迟才干够下降. 尽管不easy, 但迟早会出现的, 问题是何时, 何人. 我希望VR市场会随着Rift的公布而起飞, 那显示延迟减少的日子也就不远了.

假设你一直以为AR/VR仅仅是简单地在眼镜内显示一幅图像的话, 我希望这篇文章能够让你明白呈现真实的虚拟图像有多么复杂, 我们眼下还处于蜻蜓点水的阶段.

上一篇:netty源码解解析(4.0)-6 线程模型-IO线程EventLoopGroup和NIO实现(一)


下一篇:一步一步学Python(1) 基本逻辑控制举例和编码风格规范