向应用添加空间环境

在 Jetpack XR SDK 中,空间环境是您可以添加到应用中以自定义虚拟场景背景的沉浸式环境。只有当应用处于全空间模式时,空间环境才会显示。

空间环境概览

SpatialEnvironment 用于管理应用的空间环境偏好设置。它是独立天空盒图片和 glTF 指定几何图形的复合图形。一次只能设置一个天空盒图片和一个 glTF 几何图形文件。

天空盒表示用户在虚拟场景中周围看到的图片,营造出远处背景环境(例如天空、山脉或城市景观)的错觉。用户无法与天空盒互动或靠近天空盒。Jetpack XR SDK 支持 OpenEXR 标准中的球形天空盒。除了为应用提供沉浸式背景之外,EXR 天空盒还会为应用加载的 3D 模型提供基于图片的照明 (IBL)。如需了解详情,请参阅关于使用 3D 模型的指南

空间环境还可以包含 glTF 标准中的 3D 几何图形内容。以这种方式加载的环境几何图形将自动与真实地板对齐。环境几何图形是一种非常棒的方式,可通过前景和中景元素通过视差效果融入天空盒,从而为环境增添真实感。

空间环境设计指南中,您可以了解可用于创建空间环境的不同类型的素材资源,以及如何创建安全且令人愉悦的空间环境。

您可以将应用的空间环境设置为以下三种配置之一:

  • 天空盒图片和 glTF 几何图形的组合。
  • 透视 Surface,其中显示的环境是来自设备朝外摄像头的实时画面。在完全不透明时,此穿透 Surface 会完全遮挡天空盒和几何图形。
  • 混合配置,其中透视 Surface 既不是完全不透明,也不是完全透明。在这种情况下,透视表面会变为半透明,并且 Alpha 会与其背后的天空盒和几何图形进行混合。

适用于空间环境的空间功能

导入和加载空间环境资源

Session 类中会异步加载空间环境的 glTF 和 EXR 资源。这些文件必须存储在 assets 文件夹中。

创建 glTF 资源

glTF 资源可以作为 GltfModel 创建,其中 glTF 会从本地文件加载。GltfModel 可用作空间应用环境的一部分。

// assume that session is a Session that has been previously created
val environmentGeometryFuture = session.createGltfResourceAsync("DayGeometry.glb")

val environmentGeometry = environmentGeometryFuture.await()

创建 EXR 图片资源

EXR 图片资源可以创建为 ExrImage,其中 EXR 会从本地文件加载。ExrImage 可用作空间应用环境的一部分,用于绘制天空盒。

// assume that session is a Session that has been previously created
val skyboxExrFuture = session.createExrImageResourceAsync("BlueSkybox.exr")

val skyboxExr = skyboxExrFuture.await()

为应用设置 SpatialEnvironmentPreference

setSpatialEnvironmentPreference 用于为应用设置首选空间环境。此方法仅设置偏好设置,不会立即发生更改,除非 isSpatialEnvironmentPreferenceActive 已设为 true。当设备进入可更改 XR 背景且 SpatialCapabilities.SPATIAL_CAPABILITY_APP_ENVIRONMENT 功能可用时,系统会自动显示应用的首选空间环境。

将偏好设置设为 null 会停用应用的首选空间环境,这意味着系统会改为显示默认系统环境。

如果给定的 SpatialEnvironmentPreference 不为 null,但其所有属性均为 null,则空间环境将由黑色天空盒和无几何图形组成。

如需在 SpatialEnvironment 状态发生变化时收到通知,请使用 addOnSpatialEnvironmentChangedListener

基本用法

此代码段会创建环境几何图形和天空盒资源,然后设置空间环境偏好设置。系统会记住此偏好设置,并在应用能够设置自己的环境时应用该设置。

// Assume that session is a Session that has been previously created

// Create a GLTFResource
val environmentGeometry = session.createGltfResourceAsync("DayGeometry.glb").await()

// Create an ExrImage for the skybox
val skyboxExr = session.createExrImageResourceAsync("BlueSkybox.exr").await()

val spatialEnvironmentPreference = SpatialEnvironmentPreference(skyboxExr, environmentGeometry)

val preferenceResult = session.spatialEnvironment.setSpatialEnvironmentPreference(spatialEnvironmentPreference)

if (preferenceResult ==  SpatialEnvironment.SetSpatialEnvironmentPreferenceChangeApplied()) {
   // The environment was successfully updated and is now visible, and any listeners
   // specified using addOnSpatialEnvironmentChangedListener will be notified.
} else if (preferenceResult == SpatialEnvironment.SetSpatialEnvironmentPreferenceChangePending()) {
    // The environment is in the process of being updated. Once visible, any listeners
   // specified using addOnSpatialEnvironmentChangedListener will be notified.
}

高级用法

对于需要对环境进行更精细控制的高级用例,您可以纳入 SpatialCapabilities 检查并实现 addOnSpatialEnvironmentChangedListener,以确定何时要设置空间环境偏好设置。

为应用的空间环境设置 PassthroughOpacityPreference

应用沉浸式虚拟背景的组件之一是透视 Surface。在这种情况下,显示的背景是来自设备朝外摄像头的实时画面。

setPassthroughOpacityPreference 用于为应用设置首选的透视不透明度。除非 SpatialCapabilities.SPATIAL_CAPABILITY_PASSTHROUGH_CONTROL 功能可用,否则此方法只会设置偏好设置,不会立即发生更改。当设备进入可更改透视不透明度的状态且 SpatialCapabilities.SPATIAL_CAPABILITY_PASSTHROUGH_CONTROL 功能可用时,系统会自动应用应用的首选透视不透明度。

透视不透明度偏好的值介于 0.0f(不透明度为零,透视 Surface 不可见)和 1.0f(完全不透明,透视 Surface 会隐藏空间环境)之间。setPassthroughOpacityPreference 参数是一个可为 null 的浮点值。将值设置为 null 表示应用没有透视不透明度偏好设置,并会将透视控制权返回给系统。

基本用法

以下代码段会设置透视不透明度偏好设置。系统会记住此偏好设置,并在应用能够设置透视不透明度时应用该设置。

// Assume that session is a Session that has been previously created

val preferenceResult = session.spatialEnvironment.setPassthroughOpacityPreference(1.0f)

if (preferenceResult ==  SpatialEnvironment.SetPassthroughOpacityPreferenceChangeApplied()) {
  // The passthrough opacity request succeeded and should be visible now, and any listeners specified using addOnPassthroughOpacityChangedListener
  // will be notified
} else if (preferenceResult == SpatialEnvironment.SetPassthroughOpacityPreferenceChangePending()) {
  // The passthrough opacity preference was successfully set, but not
  // immediately visible. The passthrough opacity change will be applied
  // when the activity has the
  // SpatialCapabilities.SPATIAL_CAPABILITY_PASSTHROUGH_CONTROL capability.
  // Then, any listeners specified using addOnPassthroughOpacityChangedListener
  // will be notified
}

高级用法

对于需要更精细地控制透视不透明度的更高级用例,您可以纳入 SpatialCapabilities 检查并实现 addOnPassthroughOpacityChangedListener,以确定何时设置透视不透明度偏好设置。

优化素材资源

在创建用于设置用户 SpatialEnvironment 的资源时,您需要确保资源能够实现高质量分辨率,同时保持合理的文件大小。您需要确保 glb 使用 mipmap 和 ktx2 纹理。您还需要注意 glb 文件中的多边形数量,因为多边形数量过多可能会导致不必要的功耗。大多数 SpatialEnvironment 实例的文件大小主要来自用于天空盒的图片。为确保图片经过优化,请通过优化工具(例如 ktx)运行资源。

确定当前的透视不透明度

val currentPassthroughOpacity =  session.spatialEnvironment.getCurrentPassthroughOpacity()

另请参阅