WebXR 设置中的灯光

由于WebXR 设备 API依赖于其他技术(即WebGL以及基于它的框架)来执行场景的所有渲染、纹理和灯光,因此 WebXR 设置或场景与任何其他 WebGL 生成的显示器一样,也适用相同的通用灯光概念。

但是,在创建灯光代码时,尤其是在增强现实 (AR) 应用程序中,需要注意一些问题和细节。本指南将讨论这些主题。虽然本文简要提醒了灯光的一般工作原理,但它绝不是灯光教程或如何创建正确照明的 3D 场景的指南。

回顾:模拟 3D 中的灯光

虽然本文不是 3D 场景灯光方面的全面指南,但提供有关灯光一般工作原理的简要提醒仍然很有用。从根本上说,模拟虚拟场景中的灯光涉及计算每个光源有多少光在与场景中每个物体交互并反射后到达眼睛。

光的反射

图:显示反射角如何对应入射角的示意图。 显示反射角如何对应入射角的示意图。

我们看到的每个物体,之所以能看到,是因为该物体要么发射光,要么反射光(或者两者兼而有之)。入射光线——入射线——以称为入射角的角度到达。入射角 Θᵢ 是入射线与表面的法线向量之间的角度。

对于粗糙的表面,光线会向各个方向均匀反射。但是,光滑的镜面反射表面会将大部分光线反射到一个方向,其反射角 Θᵣ 等于入射角,只是它位于法线向量的另一侧。然后,反射线沿该角度偏离法线。这就是反射定律。这是阴影处理中许多内容的基础,并且在不同类型的灯光源的行为方式方面发挥作用。

当然,反射光线的颜色可能会因光线与表面的相互作用而改变强度和/或色调,但角度始终相同。

光源的组成部分

光源具有三个主要组成部分;每个组成部分本质上都是一种光

有三种光可以影响物体及其像素在查看器屏幕或头显上显示的颜色和亮度。

环境光

环境光是指不来自定义光源,而是存在于整个场景中的光。这种光以相同的强度从各个方向到达场景中的每个表面,然后向各个方向均匀反射。因此,环境光应用的效果在整个场景中都是普遍相等的。

图:只有环境光的球体。请注意,完全没有阴影来指示球体的深度。 只有环境光的球体。请注意,完全没有阴影来指示球体的深度。

环境光的效果是通过将光源的强度乘以像素位置处表面的反射率来计算的。无论它在场景中的位置或朝向如何,场景中每个像素的颜色和强度都以完全相同的方式受到影响。环境光通常用于防止阴影区域变得太暗,尽管它会影响整个场景;但是,场景中的环境光量应该非常低。

由于光的散射和散射在实时计算中可能很昂贵,尤其是在涉及多个光源的情况下,因此通常使用环境光来模拟场景中所有其他光源引起的散射光,而不是实际计算光散射的真实效果。但是,在执行此操作时,需要谨慎尝试将环境光与场景照明的真实效果相匹配。

环境光也可用于为场景应用颜色色调;例如,在玩家戴有一副特殊的黄色眼镜的游戏中,可以添加黄色环境光。

漫反射光

漫反射光是指从表面均匀且定向发射或反射的光。这是我们通常看到的大部分光。漫反射光来自特定位置或方向,并投射阴影。由于其方向性,面向漫反射光源的物体的表面将比其他表面更亮。

图:土卫六沐浴在阳光下,阳光来自左下方。 土卫六主要由太阳照亮,也有一些来自土星的反射光。这是漫反射光。

由于漫反射光的强度取决于入射角(表示光线到达表面的方向的向量与表面的法线向量或垂直于表面的向量之间的角度),因此物体反射的光的强度或亮度会根据表面相对于光源的方向而变化。

镜面反射光

镜面反射光是构成反射物体(如宝石、眼睛、闪亮的杯子和盘子等)上的高光的光。镜面反射光往往出现在光源最直接照射到表面的点上,形成明亮的光斑或方块。

图:美国宇航局卡西尼号航天器拍摄的照片,显示了土卫六表面甲烷湖上光的镜面反射。 美国宇航局卡西尼号航天器拍摄的照片,显示了土卫六表面甲烷湖上光的镜面反射。

每个光源都由环境光、漫反射光和/或镜面反射光的某种组合表示。WebGL 着色器程序获取每个光源的颜色、方向性、亮度和其他因素,并计算每个像素的最终颜色。

光源类型

有四种基本的光源类型。每一种都涉及虚拟光源,其与正在绘制的物体的距离和光波的方向性导致光源呈现出特定的特性。在大多数情况下,任何现实世界的光源都可以使用一种或多种这些光源类型来模拟。

环境光源

环境光源是描述场景中环境光水平和颜色的光源。虽然场景中可能有多个这样的光源,但你可能可以通过自己将它们组合成一个来稍微提高性能,因为无论如何,每个光源都会均匀地影响每个像素。

环境光源通常不对应于场景中的任何物体,也没有任何现实世界的对应物。

方向光源

方向光源是一种光源,它来自特定方向,但不是来自特定光源,因此它发出的光线彼此平行。此外,光的强度不会随着距离的变化而改变。这意味着方向光产生的阴影非常锐利,在光照和阴影之间存在本质上的瞬间过渡。

图:地球和月球都被太阳的方向光线半照亮。 伽利略号宇宙飞船从约630万公里外拍摄的照片,地球和月球都被太阳照亮了一半。

方向光最常见的例子是太阳。虽然太阳实际上是一个单独的(巨大的)物体,但它距离非常遥远,因此它发出的光线基本上是平行的。虽然阳光的强度确实会随着距离的增加而下降,但变化率非常低,只有在很远的距离才会注意到,因此阳光强度变化率通常对渲染 3D 场景没有影响。

点光源

点光源是一种位于特定位置的光源,向各个方向均匀辐射。灯泡、蜡烛等都是点光源的例子。物体越靠近点光源,它投射到该物体上的光就越亮。点光亮度下降的速率称为衰减,它是 WebGL 和其他照明系统中光源的可配置特性。

根据反射定律以及光线亮度随距离减小的这一事实,点光源发出的光线反射回来往往在最靠近光源的点最亮,越远越暗。即使表面是平的,最靠近光源的点也是中心,光线随着远离法线的角度变化而变得越来越长。

聚光灯源

聚光灯源(或聚光灯)是一种位于特定位置的光源,在其方向矢量的方向上发出锥形光束。一个锥度率参数定义了光线亮度在光锥边缘下降的速度,并且,与点光源一样,一个衰减参数控制光线随距离的衰减。

图:夜晚聚光灯照射在灰泥墙上的照片。 夜晚聚光灯照射在灰泥墙上的照片。

在光锥的边缘,光线完全停止影响表面。

照明的计算成本

为了可见,场景必须包含某种照明,因此所有或几乎所有场景都将至少有一个光源,并且可能有很多光源。每个光源都会大大增加确定每个显示像素的最终颜色和亮度所需的计算量。对每种光源类型执行着色比前一种光源类型更需要计算资源;因此,环境光是最便宜的应用,其次是方向光源、点光源,最后是聚光灯。

此外,照明的设计越精确,计算成本就越高。增加的阴影细节、体积光(即,可以在空气中看到的照明,例如阳光或天空中的聚光灯光束)以及其他照明效果可以为您的场景增添真实感和美感,但需要注意的是,要确保场景不会压垮 GPU。

计算光照像素的颜色

虽然一些图形库包含对光源对象的支持并自动为您计算和应用照明效果,但 WebGL 却没有。幸运的是,在您自己的顶点和片段着色器中应用照明并不困难。

对于场景中的每个多边形,顶点着色器程序确定顶点的颜色,然后片段着色器通过组合来自分配纹理的相应纹素、任何颜色色调或效果以及其他视觉数据来生成多边形中的每个像素。此时,将考虑场景的照明并根据像素进行相应的应用,然后再将像素存储到帧缓冲区中。

最终渲染场景中每个像素的颜色是使用一些复杂的数学计算得出的,这些计算会考虑诸如以下因素:

  • 给定对象几何体、观察者相对于每个多边形的的位置和方向等,对应于屏幕像素的纹理元素(映射到对象上的纹理中的像素;也称为纹素)的颜色。
  • 观察者位置和距离。
  • 表面材料和反射率。
  • 目标位置处表面的凹陷或凸起。
  • 场景中每个光源的位置、颜色、方向性和亮度。
  • 场景中任何环境光的颜色和亮度;这是均匀应用于整个场景的光,没有光源,因此没有阴影或亮度变化。
  • 光线从场景中其他表面反射的效果;反射光的颜色、方向性和亮度会影响光线照射到的像素的颜色。

您可以在文章WebGL 中的照明中了解更多关于如何在 WebGL 中执行照明的知识。

混合现实内容的灯光问题

除了在照明场景时需要应对的常见问题之外,VR 或 AR 使用案例在编写着色器时还会增加其他需要关注的方面。在本节中,我们提供了一些基本的混合现实照明指南,供您在构建、渲染和照明场景时参考。虽然其中一些在任何其他 3D 设置中也很有用,但大多数是特定于虚拟现实的,在某些情况下甚至更特定于增强现实。

由于您的场景旨在表示一个人或他们的化身可以存在于其中的环境,因此您应该尝试在光源的位置和呈现方面实现一定程度的一致性和真实感。显然,此准则存在例外情况,例如当您的场景表示超凡脱俗或外星环境时,或者当您的目标是创造令人不安的视觉效果时。

光源放置的真实感

如果可能,您应该尝试使虚拟光源对应于实际存在的物体。如果您有一个需要顶灯的虚拟房间,请在光源位置放置一个吊顶灯的模型。存在例外情况,例如为设置添加基线照明量的环境光,以及太阳,它是一种方向光(即,每条光线都平行,从天空中的某个地方发出,并在场景中的某个地方结束的光源)。

尝试将光源放置在适合设置和您尝试创建的情绪的真实位置。一个旨在让人感觉像自然光照、现实世界环境的场景不会有影棚灯光。它有阳光,可能还有从场景中的物体或水中反射的光线等等,但没有灯直接照射到场景中物体或人的脸上。

玩家与光线交互的真实感

如果您的光源位于场景中,您可能应该尝试确保观看者的化身不能与光源发生物理上的交叉。结果可能会很奇怪。

如果观看者的化身旨在具有物理形态,则它应该有一个模型,即使观看者永远也看不到它,以便光线能够正确地与化身交互。至少,这意味着化身应该投射出合适的阴影;但是,根据诸如化身是否可见以及其模型的材质、纹理和其他属性(尤其是其反射率)等因素,化身可能还需要反射光线,以及可能影响从其反射的光线的颜色。

增强现实中的真实感

增强现实为照明对象引入了另一层复杂性,因为您的虚拟对象需要存在于具有自身光源的物理世界中。因此,您应该尽量使您的照明与现实世界的光源尽可能匹配。这使用称为照明估计的技术来完成。

相反,您应该尝试避免使用本身就是光源的虚拟对象,除非您准备创建可以将该照明投射到现实世界环境中的代码。将光线投射到现实世界物体上本质上与投射阴影相反。它可以实现,但没有得到广泛的实施。

灯光估算

照明估计是一种由增强现实平台使用的方法,用于尝试将场景中虚拟对象的光照与围绕观看者的现实世界的光照匹配。这涉及收集可能来自各种传感器(包括加速度计和指南针,如果可用)、相机以及可能的其他传感器的数据。其他数据使用地理位置 API收集,然后所有这些数据都通过算法和机器学习引擎来生成估计的光照信息。

目前,WebXR 不提供对照明估计的支持。但是,规范目前正在起草中,由 W3C 主导。您可以在包含在规范的 GitHub 存储库中的说明文档中了解所有关于提议的 API 以及关于照明估计概念的大量信息。

从本质上讲,照明估计收集有关光源以及场景中对象形状和方向的信息,以及有关它们制成材料的信息,然后返回可用于创建近似匹配现实世界照明虚拟光源对象的数据。

照明估计的工作原理的细节,尤其是在提议的 API 的上下文中,目前不在讨论范围之内。一旦 API 稳定下来,我们将使用详细信息更新此文档。

安全和隐私问题

为了收集所有这些数据以使用现实世界数据生成和应用虚拟对象的光照,存在许多潜在的安全问题。

当然,许多 AR 应用程序都非常清楚用户的位置。如果用户正在运行一个名为“参观卢浮宫”的应用程序,那么用户很有可能位于法国巴黎的卢浮宫博物馆。但浏览器需要采取许多步骤来使其难以在未经用户同意的情况下物理定位用户。

环境光传感器 API

使用环境光传感器 API收集光线数据会带来各种潜在的隐私问题。

  • 照明信息可以泄露给网络有关用户周围环境和设备使用模式的信息。此类信息可用于增强用户画像和行为分析数据。
  • 如果两个或多个设备访问使用相同第三方脚本的内容,则该脚本可用于关联照明信息以及它随时间的变化方式,以尝试确定设备之间的空间关系;例如,这理论上可能表明设备位于同一区域。

浏览器如何缓解这些问题

为了帮助减轻这些风险,WebXR 照明估计 API 规范要求浏览器报告的光照信息与真实值有所偏差。这可以通过多种方式实现。

球谐函数精度

浏览器可以通过降低指纹识别的精度来降低其风险。在执行实时渲染时——虚拟或增强现实应用程序都是如此——球谐光照用于简化和加速生成高度逼真的阴影和着色的过程。通过更改这些函数的精度,浏览器使数据变得不那么一致,并且重要的是,即使在相同的设置下,由两台计算机生成的数据也会有所不同。

解耦方向和光照

在使用地理位置信息确定方向和潜在位置信息的 AR 应用程序中,避免使这些信息与光照状态直接相关是浏览器保护用户免受指纹识别攻击的另一种方法。通过确保指南针方向和光线方向在靠近(或声称靠近)用户位置的每个设备上不相同,从而消除了基于用户周围光照状态查找用户的能力。

当浏览器提供有关非常明亮的定向光源的详细信息时,该光源可能代表太阳。此明亮光源的方向性与一天中的时间相结合,可用于确定用户的位置,而无需使用 Geolocation API。通过确保 AR 场景的坐标与指南针坐标不一致,并降低太阳光角度的精度,就可以不再使用此技术精确估计位置。

时间和空间滤波

假设攻击者使用建筑物的自动化照明系统以已知模式快速闪烁灯光。如果没有采取适当的预防措施,照明估算数据可用于检测此模式,从而确定用户是否在特定位置。这可以远程完成,也可以由位于同一房间但想要确定其他人是否也在同一房间的攻击者执行。

照明估算可用于未经许可获取用户信息的另一种情况:如果光传感器足够靠近用户的显示器以检测显示器内容引起的光照变化,则可以使用算法来确定用户是否正在观看特定视频,甚至可能识别用户正在观看的多个视频中的哪一个。

照明估算 API 规范要求所有用户代理执行时间和空间滤波,以模糊数据,使其无法用于定位用户或执行侧信道攻击

另请参阅