虚拟现实与增强现实

引言:VR/AR/XR 的核心挑战

本章的核心是探讨虚拟现实 (Virtual Reality, VR)增强现实 (Augmented Reality, AR) 中的实时渲染技术。这两种技术统称为 XR (Extended Reality)

  • VR (虚拟现实): 完全替代现实世界,为用户创造一个全数字化的沉浸式环境。
  • AR (增强现实):数字信息叠加到现实世界之上,用户仍然能看到真实环境。
  • 渲染只是冰山一角: 成功的XR体验还依赖于高精度追踪、低延迟、舒适的光学设计、直观的输入设备等诸多因素。本笔记将聚焦于渲染相关的挑战。

21.1 设备与系统概述

核心观点

XR硬件形态多样,其核心区别在于计算能力追踪方式与现实世界的交互模式。理解这些硬件差异是进行针对性渲染优化的前提。

关键术语与分类

  • 头戴式显示器 (Head-Mounted Display, HMD): XR体验的核心设备,集成了显示屏、光学镜片和传感器。

  • 自由度 (Degrees of Freedom, DOF): 衡量追踪能力的关键指标。

    • 3-DOF: 只能追踪头部旋转(点头Yaw、俯仰Pitch、翻滚Roll)。适用于观看360度视频等静态场景。代表:早期的手机VR盒子 (Google Cardboard)。
    • 6-DOF: 不仅能追踪旋转,还能追踪头部位置(前后、左右、上下移动)。这是实现真正沉浸式交互的基础。代表:Oculus Rift, HTC Vive。
  • 追踪技术 (Tracking Technology): 决定系统如何定位HMD和控制器。

    • 由外向内追踪 (Outside-In Tracking): 外部传感器(如红外摄像头)追踪HMD上的标记点。优点是精度高、稳定。缺点是需要布置外部设备,活动范围受限。代表:Oculus Rift。
    • 由内向外追踪 (Inside-Out Tracking): HMD上的传感器(如摄像头)通过扫描和识别环境特征来确定自身位置。优点是无需外部设备,设置简单,活动范围大。缺点是对环境光照和特征有一定要求。代表:HTC Vive (Lighthouse系统)、HoloLens, Quest系列。
  • AR/MR 系统分类:

    • 视频穿透式AR (Video Passthrough / Mediated Reality): HMD上的摄像头捕捉现实世界,将画面与虚拟物体混合后显示在屏幕上。优点是可以更好地控制虚实融合(如虚拟物体可以完全遮挡真实物体)。缺点是现实世界画面存在延迟。代表:Quest 2/3的Passthrough功能。
    • 光学透视式AR (Optical See-Through): 用户通过半透明的显示屏直接看到现实世界,虚拟内容投射在显示屏上。优点是现实世界零延迟。缺点是虚拟物体通常是半透明的,无法显示纯黑色(只能增亮,不能减光)。代表:Microsoft HoloLens。
    • 移动端AR: 利用手机或平板的摄像头和传感器实现。代表:Apple的 ARKit 和 Google的 ARCore。它们的核心技术是即时定位与地图构建 (SLAM),能够识别平面(水平/垂直)并将虚拟物体“锚定”在现实空间中。

21.2 渲染相关的物理要素

核心观点

XR渲染的成败直接取决于能否克服物理和生理上的限制。延迟光学畸变视觉辐辏冲突是开发者必须面对和解决的三大核心物理问题。

21.2.1 延迟 (Latency)

这是VR中最关键、最致命的问题。

  • 核心观点: 高延迟是导致模拟病 (Simulation Sickness) 的罪魁祸首。目标是最大限度地缩短从用户头部运动到屏幕显示相应画面的时间。

  • 关键术语:

    • 动显延迟 (Motion-to-Photon, MTP Latency): 指从传感器检测到用户头部运动开始,到相应的新画面像素(光子)显示在屏幕上为止的总时间。
    • 模拟病 (Simulation Sickness): 当视觉系统(眼睛看到的)与前庭系统(内耳感知到的平衡和运动)信息不匹配时,产生的一种生理不适,症状包括头晕、恶心、出汗等。这种不适无法“硬抗”,只会越来越严重。
  • 重要指标:

    • 理想延迟: (用户几乎无法察觉)。
    • 可接受延迟上限: (超过此值,大部分用户会明确感知到延迟并可能产生不适)。
    • 对比: 传统PC游戏延迟通常在 或更高。VR要求极为苛刻。
    • 帧率要求: 主流VR系统通常要求 90 FPS,即每帧渲染时间约为
  • 解决策略:

    • 位姿预测 (Pose Prediction): 由于从获取输入到最终显示总有延迟,系统不会使用渲染开始时的头部姿态,而是预测当画面显示时头部将会处于的姿态。这种预测会在渲染管线的不同阶段(如物理模拟时、视图矩阵计算时、最终图像提交时)被多次、越来越精确地执行。
    • 应用层设计:
      • 提供静态参考物(如驾驶舱、虚拟鼻子)来稳定用户的视觉。
      • 避免强制性的相机移动、缩放或加速,将控制权始终交给用户。
      • 尽量使用恒定速度移动。

21.2.2 光学 (Optics)

  • 核心观点: 为了实现宽视场角(FOV)和紧凑设计,VR头显使用了廉价但有明显光学缺陷的镜片。这些缺陷必须通过渲染端进行逆向校正。你渲染的图像并不是用户最终看到的图像。

  • 关键术语与技术:

    • 枕形畸变 (Pincushion Distortion): 这是物理镜片本身带来的光学效应,图像边缘向内弯曲,看起来像一个枕头。
    • 桶形畸变 (Barrel Distortion): 这是在渲染的最后阶段,通过一个后处理着色器 (Post-Process Shader) 对渲染图像施加的反向畸变。图像边缘被向外拉伸,看起来像一个木桶。当这个经过桶形畸变的图像通过带有枕形畸变的镜片观看时,最终在用户视网膜上会形成一个正常的、无畸变的图像。

      [渲染流程] 场景渲染 桶形畸变处理 显示在HMD屏幕 用户通过枕形畸变镜片观看 视网膜上成像正常

    • 色差校正 (Chromatic Aberration Correction): 镜片会像棱镜一样使不同颜色的光分离(尤其是在图像边缘)。校正方法与畸变类似:在渲染时人为地在相反方向上分离颜色通道,这样通过镜片后颜色就能重新汇合。
  • 显示方式:

    • 滚动显示 (Rolling Display): 逐行扫描显示。优点是延迟较低(渲染完一行就能发送一行)。缺点是快速转头时可能产生图像撕裂或“抖动”。
    • 全局显示 (Global Display): 整个画面准备好后一次性点亮。优点是图像稳定无撕裂。缺点是需要等待整帧渲染完成,延迟稍高。OLED 屏幕因其快速响应特性,是全局显示的理想选择。

21.2.3 立体视觉 (Stereopsis)

  • 核心观点: 提供双眼立体视觉不仅仅是渲染两个视角的图像那么简单。最大的挑战来自于人眼生理上的调节-辐辏冲突,这是导致视觉疲劳的主要原因。

  • 关键术语:

    • 瞳孔间距 (Interpupillary Distance, IPD): 用户双眼瞳孔之间的物理距离。正确设置IPD对于生成正确的立体视觉和避免不适至关重要。渲染相机之间的距离应与用户IPD匹配。
    • 调节-辐辏冲突 (Accommodation-Convergence Mismatch): 这是XR领域的一个核心生理难题。
      • 调节 (Accommodation): 人眼的晶状体为了将物体清晰地聚焦在视网膜上而改变形状的过程。在VR中,眼睛始终聚焦在物理屏幕上,所以调节距离是固定的(例如,Oculus Rift等效于看1.3米远的物体)。
      • 辐辏 (Vergence): 为了让双眼视线汇聚在同一个物体上,眼球向内或向外转动的过程。在VR中,当你看向不同深度的虚拟物体时,辐辏距离是变化的。
      • 冲突: 在现实世界中,“调节”和“辐辏”是联动反射。你看近处物体,晶状体变厚的同时,眼睛会向内汇聚。但在VR中,调节距离恒定,而辐辏距离在变,大脑的这种固有反射被打破,从而导致视觉疲劳和不适。
  • 实践建议:

    • 避免修改IPD来制造特效: 虽然改变虚拟IPD可以夸大或缩小世界的尺度感,但这极易导致用户眼睛疲劳。
    • 优化物体放置距离: 将用户需要长时间注视的核心交互物体放置在舒适区(书中建议为0.75米到3.5米之间),以减小调节-辐辏冲突带来的不适感。

21.3 API和硬件

核心观点

永远优先使用并信任设备供应商提供的SDK和API。 XR渲染的舒适性和性能依赖于大量精密的系统级校准和优化(如畸变、色差、时序控制等),个人从零实现极易导致用户产生严重不适。SDK为开发者屏蔽了底层硬件的复杂性,并提供了经过验证的优化方案。

VR渲染的基本流程 (通过SDK)

渲染一帧VR图像的典型工作流如下,几乎所有步骤都由SDK引导和处理:

  1. 预测显示时间: 向SDK询问下一帧图像将要被显示的精确时间。
  2. 获取预测位姿 (Pose Prediction): 基于上一步的未来时间,向SDK查询届时用户双眼的预测位置和方向。这是降低“动显延迟(MTP)”的关键一步。
  3. 双眼渲染: 使用SDK提供的双眼相机参数,将场景渲染到两个渲染目标 (Render Target) 中。
  4. 提交至合成器 (Compositor): 将渲染好的左右眼纹理提交给SDK的合成器
    • 合成器是系统级的渲染管理器,它负责将你的3D场景、UI层(可以是单目的)、系统通知等多个图层组合起来。
    • 它允许不同图层有不同的分辨率,例如,为了性能可以动态降低3D场景的分辨率,同时保持UI文字的清晰。
  5. 最终处理与显示: 合成器接管纹理后,执行最终的畸变校正色差校正等操作,然后将图像发送到HMD屏幕。

渲染管线核心优化

SDK内部通常集成了以下关键优化来降低GPU负载:

  • 隐藏区域网格 (Hidden Area Mesh):

    • 问题: 由于HMD镜片是圆形的,我们渲染出的矩形图像的四个角落实际上是用户永远看不到的。在这些区域上运行像素着色器是纯粹的浪费。
    • 解决方案: 在正式渲染场景前,SDK会提供一个“遮罩网格”。先将这个网格渲染到深度缓冲或模板缓冲中。这样,后续场景中所有被该网格遮挡的像素都会在像素着色器运行前被GPU硬件提前剔除,从而节省大量的填充率。
    • 效果: 在HTC Vive上,此技术能减少约 17% 的像素着色计算。
  • 畸变校正网格 (Distortion Correction Mesh):

    • 问题: 如果在后处理阶段,为屏幕上的每个像素都通过复杂公式计算畸变和色差校正,开销会非常大。
    • 解决方案: 更好的方法是渲染一个预先计算好畸变的网格。这个网格在顶点着色器中被正常渲染,但在其UV坐标上做了手脚。网格的UV坐标被预先计算,以反向抵消镜片的光学畸变。
    • 色差校正实现: 为了同时校正色差,该网格的每个顶点通常会包含三组独立的UV坐标,分别对应R、G、B三个颜色通道。在像素着色器中,使用这三组不同的UV对原始渲染纹理进行三次采样并组合,从而实现色差校正。
    • 效果: 这种方法效率远高于逐像素计算,并且还可以通过裁剪网格中最终不可见的部分,进一步节省开销。

21.3.1 立体渲染 (Stereo Rendering)

核心观点

立体渲染的开销并非简单地翻倍。很多渲染环节(如阴影、模拟、动画)是视图无关的。优化的核心在于减少视图相关的CPU开销(Draw Call)和GPU顶点处理开销

关键策略与技术

  • Draw Call 优化:

    • 基础方法 (低效): 先渲染完左眼,再渲染完右眼(状态切换开销加倍);或者每个物体提交两次绘制命令(Draw Call数量加倍)。
    • 推荐方案: 实例化 (Instancing): 使用单次Draw Call同时渲染左右眼两个实例。通过SV_InstanceID等变量在着色器中区分左右眼,并应用不同的视图/投影矩阵。这是目前最主流且高效的方案。
  • 硬件多视图扩展 (Hardware Multi-View Extensions):

    • 一些现代GPU(尤其是移动端)提供硬件级别的多视图渲染支持(如OpenGL ES的multi-view扩展)。开发者只需提交一次几何体,GPU硬件会自动将其广播到多个视图进行处理,极大地降低了CPU开销。
  • 多GPU方案 (Multi-GPU):

    • 基本思想: 一个GPU渲染一只眼睛,并行工作。
    • 广播 (Broadcasting): CPU提交一次Draw Call,该命令被广播到所有GPU上执行。每个GPU使用各自的常量缓冲区(包含不同的眼睛位置信息)进行渲染。这种方式的CPU开销几乎和单视图渲染相同。
  • 降低外围像素着色 (Peripheral Shading Reduction):

    • 问题根源: 经过光学畸变后,渲染图像中央区域的像素被放大,而外围区域的像素被压缩。这意味着我们在外围浪费了大量的像素着色性能,渲染了过高的细节。
    • 技术方案:
      • 多分辨率着色 (Multi-Resolution Shading): 将屏幕划分为一个网格(如3x3),中心区域使用全分辨率渲染,而周围的区域则以较低的分辨率渲染。
      • 镜头匹配着色 (Lens Matched Shading): 这是多分辨率着色的进化版。它使用多个倾斜的投影平面来更好地拟合镜头的畸变曲线,使得从中心到边缘的分辨率过渡更平滑。NVIDIA的同步多重投影 (Simultaneous Multi-Projection, SMP) 是实现此技术的关键硬件特性。
      • 径向密度遮罩 (Radial Density Masking): 一种应用层面的技巧,在图像外围以棋盘格等模式丢弃部分像素的渲染,然后在后处理中根据相邻像素进行插值重建。

21.3.2 注视点渲染 (Foveated Rendering)

核心观点

这项技术模仿人眼的生理特性,只在用户视线聚焦的中心区域(中央凹)进行高质量、高分辨率渲染,而在广阔的周边视觉区域则降低渲染质量,从而在不牺牲可感知画质的前提下,大幅节省GPU资源。

关键术语与依赖

  • 中央凹 (Fovea): 人眼视网膜上视觉最敏锐、感光细胞最密集的一小块区域。我们看到的清晰细节都来自于此。
  • 扫视 (Saccades): 人眼为了观察物体而进行的极其快速的跳跃式运动,速度极高(可达每秒900度)。
  • 关键依赖: 高速、低延迟的眼动追踪 (Eye Tracking): 要实现真正的注视点渲染,系统必须能实时、准确地知道用户的眼睛正在看哪里。这是该技术最大的硬件挑战。

分类

  • 动态注视点渲染 (Dynamic Foveated Rendering):

    • 需要眼动追踪硬件支持。
    • 渲染质量最高的区域会实时跟随用户的注视点移动。
    • 这是最理想、也是节约性能潜力最大的形式。
  • 固定注视点渲染 (Fixed Foveated Rendering):

    • 无需眼动追踪。
    • 假设用户大部分时间在注视屏幕中心。因此,它永久性地将屏幕中心区域设置为高质量渲染,外围区域设置为低质量渲染。
    • 实际上,上一节提到的多分辨率着色镜头匹配着色就是固定注视点渲染的具体实现技术。

21.4 渲染技术:VR/AR中的“禁区”与“改造区”

核心观点

为传统单屏幕设计的渲染技术,在VR/AR中可能完全失效,甚至引发用户的生理不适。开发者必须严格审查并调整渲染管线中的每一个环节,以适应立体视觉和HMD的特性。一切以用户的舒适度沉浸感为最高优先级。

需要避免或谨慎使用的技术

  • UI/HUD 设计:

    • 问题: 如果HUD元素在左右眼屏幕上的位置完全相同,它在感知上会处于“无限远处”。但这与它绘制在所有物体之上的事实产生深度冲突,导致用户难以聚焦,眼睛疲劳。
    • 解决方案:
      1. 将HUD元素渲染在虚拟世界中的某个深度上(例如,固定在玩家前方几米处)。
      2. 动态深度: 将HUD元素的深度动态地调整到其朝向方向上最近的物体表面之后。
      3. 最佳实践: 将UI信息融入到游戏世界中,例如做在玩家角色的手臂设备或驾驶舱的仪表盘上。
  • 法线贴图 (Normal Mapping):

    • 问题: 法线贴图本质上是在一个平面上伪造光照细节。在立体视觉下,当用户靠近观察或从侧面看时,缺乏真实几何位移的“假象”会被轻易识破。
    • 适用场景: 可用于微小细节(如皮革纹理)或远处物体
    • 禁忌场景: 绝对不要用它来模拟大的几何起伏(如大块的石头)。
    • 替代方案: 对于需要真实立体感的表面,应使用成本更高但效果正确的视差遮蔽贴图 (Parallax Occlusion Mapping)位移贴图 (Displacement Mapping)
  • 广告牌/公告板 (Billboards/Impostors):

    • 问题: 传统的广告牌是始终朝向镜头的2D平面,在立体视觉下其“纸片感”会暴露无遗。
    • 替代方案: 考虑使用简化的3D网格体积渲染技术。
  • 屏幕空间效果 (Screen-Space Effects):

    • 问题: SSAO、SSR等依赖于单视图深度缓冲区的技术,在立体渲染中会出问题,因为一只眼睛的信息无法正确用于另一只眼睛,导致反射、阴影等效果在双眼之间不匹配。
    • 替代方案: 优先使用反射探针 (Reflection Probes) 等非屏幕空间技术。
  • 后期处理效果 (Post-Processing Effects):

    • 运动模糊 (Motion Blur): 绝对禁用。VR显示器本身通过低余晖技术解决了运动模糊问题,人为添加只会造成不必要的图像模糊和不适。
    • 景深 (Depth of Field): 绝对禁用。人眼会自然地聚焦,人为模糊场景的一部分会与用户的视觉意图冲突,极易引发模拟病。
    • 泛光/镜头光晕 (Bloom/Lens Flare): 需要基于双眼各自的视图和深度来独立计算,否则效果会看起来像“贴在屏幕上”。
  • 抗锯齿 (Anti-Aliasing):

    • 问题: VR中较低的像素密度(每度视角像素数)和用户头部的微小移动会加剧锯齿和闪烁。
    • 首选方案: MSAA (多重采样抗锯齿): 它能提供最清晰、最稳定的图像,是VR渲染的首选。4x MSAA 是一个很好的起点。
    • 慎用方案: TAA (时间性抗锯齿): 尽管TAA在传统游戏中很流行,但它带来的图像模糊和拖影在VR中通常是不可接受的。只有在能严格控制其副作用的情况下才考虑使用(如Sony的某些实践)。

21.4.1 抖动 (Judder) 与补偿技术

核心观点

抖动是VR体验的头号杀手。当应用无法按时生成新帧(掉帧)时,画面会产生一种断续、卡顿的视觉瑕疵,严重破坏沉浸感并引发不适。为了对抗抖动,现代VR系统都内置了强大的“安全网”——异步重投影技术

关键术语与技术

  • 掉帧 (Dropped Frame): 应用程序未能在显示器刷新之前完成一帧的渲染和提交。

  • 抖动 (Judder): 由于掉帧或延迟,用户头部移动时看到的画面出现明显的卡顿、频闪或拖影现象。

  • 时间扭曲 (Timewarp) - 旋转补偿:

    • 做什么: 在一帧图像即将显示前的最后一刻,根据最新的头部旋转数据,对已渲染好的图像进行一次快速的2D扭曲。
    • 原理: 就像把一张照片贴在一个球体内部,当你转头时,系统不是重新拍一张照片,而是把现有的照片“扭”一下来匹配你的新朝向。
    • 优点: 速度极快(通常<0.5ms),能极大地降低感知延迟,有效补偿旋转运动。
  • 空间扭曲 (Spacewarp) / 位置时间扭曲 - 位置补偿:

    • 做什么: 基于深度信息,对图像进行3D重投影,以补偿用户的头部位置(平移)变化。
    • 原理: 将上一帧图像的每个像素,利用其深度信息“投射”回3D空间,然后根据用户头部的新位置,将这些3D点重新“拍”一张照片。
    • 挑战: 当头部移动导致原本被遮挡的物体暴露出来时,会产生**“遮挡解除”瑕疵 (Disocclusion Artifacts)**,即出现一些系统不知道该用什么内容填充的空白区域。
  • 异步重投影 (Asynchronous Reprojection):

    • 这是核心! 上述的Timewarp和Spacewarp都运行在一个独立于应用渲染线程的、高优先级的异步线程上。
    • 工作流程:
      1. 应用正常渲染,并尝试在90 FPS下提交每一帧。
      2. 如果应用成功提交了新的一帧,异步线程就用这一帧进行最后的校正并显示。
      3. 如果应用没能按时提交新帧(掉帧了),异步线程会放弃等待,立即拿上一帧的图像,结合最新的头部追踪数据,执行Timewarp/Spacewarp操作,生成一个“合成帧”并显示。
    • 最终效果: 即便应用程序的帧率掉到了45 FPS,用户看到的画面依然能以90 FPS的刷新率平滑地响应头部运动,尽管画面内容会是“一半真一半假”。

21.4.2 计时 (Timing) 与管线优化

核心观点

为了稳定地达到高帧率,必须精细地管理CPU和GPU的协作,让GPU永远“有活干”,最大限度地减少其空闲等待时间。

关键技术

  • 延迟锁存 (Late Latching): 一种将最新的头部姿态数据在最后一刻才提供给GPU的技术。CPU不断地将追踪数据写入一个GPU可访问的缓冲区,GPU则在真正需要这些数据进行渲染或扭曲时,才去“锁存”最新的值,确保了姿态数据的时效性。

  • 运行启动 (Running Start) / 自适应提前队列 (Adaptive Queue Ahead):

    • 问题: 在一个朴素的管线中,CPU准备好下一帧的命令后提交给GPU,GPU执行完后通知CPU,CPU再开始准备下下一帧。这中间存在GPU等待CPU的空闲间隙。
    • 解决方案: 这是一个预测性的调度策略。CPU会预估GPU完成当前帧所需的时间,并提前将下一帧的渲染命令提交到队列中。目标是让GPU刚一完成手头的工作,就能无缝衔接地开始处理下一帧的任务,从而消除空闲,最大化吞吐量。