增强现实( AR )与透视
增强现实的支持方式因硬件不同而有所差异。
诸如 Magic Leap、TiltFive 等设备通过使用`“透视显示屏” <https://en.wikipedia.org/wiki/See-through_display>`__ 显示渲染结果,使得用户能同时看到虚拟与现实世界。
而另一方面, Quest、HTC Elite 和 Lynx R1 等设备通过一种称为视频透视(Video Passthrough)的技术实现这一功能:摄像头记录现实世界的画面作为渲染背景,在上面显示渲染结果。
备注
透视功能在不同平台上的实现方式也不尽相同。
在 Godot 4.3 中,我们实现了一种统一的方法,因此你无需担心这些差异,XRInterface 实现现在负责应用正确的平台依赖方法。
而对于 Meta Quest 和 HTC Elite 等头戴设备,你需要使用 `OpenXR vendors plugin v3.0.0 或更高版本插件<https://github.com/GodotVR/godot_openxr_vendors/releases>`__ 来启用视频透视功能。
为保证向后兼容,旧的透视 API 仍然可用,但推荐按照以下新说明进行操作。
环境混合模式
我们通过设置环境混合模式来配置 VR 或 AR 功能。该模式决定了(现实世界)环境与虚拟世界的融合方式。
混合模式 | 描述 |
---|---|
XR_ENV_BLEND_MODE_OPAQUE | 渲染的图像将是不透明的,我们看不到现实世界,只能看到 VR 世界。视频透视功能同样会被关闭。 |
XR_ENV_BLEND_MODE_ADDITIVE | 渲染的图像将以半透明的形式被添加到现实世界中。该模式通常用于无法遮挡现实世界的透视设备。如果同时在使用视频透视功能,透视会被启用。 |
XR_ENV_BLEND_MODE_ALPHA_BLEND | 渲染的图像将与现实世界进行 alpha 混合。在支持此功能的透视设备上,alpha 值将控制光学元件的透明度。在视频透视设备上,alpha 混合将应用于视频图像,并在适用时启用透视。 |
你可以通过 XRInterface 实例的 environment_blend_mode
属性来设置应用程序的环境混合模式。
同时,可以使用同一实例上的 get_supported_environment_blend_modes
属性来查询硬件支持的混合模式。
配置背景
当环境混合模式为 XR_ENV_BLEND_MODE_ALPHA_BLEND
时,必须将 Viewport 的 transparent_bg
属性设置为 true。而使用 XR_ENV_BLEND_MODE_ADDITIVE
混合模式时,应将背景颜色设置为黑色。
这两种解决方案都会导致背景渲染不再提供环境照明。因此,建议相应地调整环境设置,确保有足够的环境光来照亮场景。
备注
部分增强现实 SDK 确实会提供环境光信息——甚至是完整的辐射图——以允许在虚拟对象中模拟真实世界的反射。不过,目前 Godot XR 的核心尚不支持此功能,但可以通过插件来实现。
OpenXR 特定功能
在 OpenXR 选项卡中,你可以配置想要使用的默认混合模式。如果该模式可用,Godot 将在启动时选择此混合模式。如果不可用,Godot 将默认选择 XR 运行时提供的第一个支持的混合模式。
对于透视设备,OpenXR 需要配置额外的设置。这些设置依赖于平台,并通过 OpenXR 供应商插件提供。
举个例子,以下是 Meta Quest 所需的设置:
Passthrough
设置定义了是否支持或者需要启动视频透视功能。
The Boundary Mode
allows you to define whether the guardian is needed, disabling this fully requires passthrough to be enabled at all times.
Putting it together
综合以上内容,我们可以使用以下代码作为基础:
@onready var viewport : Viewport = get_viewport()
@onready var environment : Environment = $WorldEnvironment.environment
func switch_to_ar() -> bool:
var xr_interface: XRInterface = XRServer.primary_interface
if xr_interface:
var modes = xr_interface.get_supported_environment_blend_modes()
if XRInterface.XR_ENV_BLEND_MODE_ALPHA_BLEND in modes:
xr_interface.environment_blend_mode = XRInterface.XR_ENV_BLEND_MODE_ALPHA_BLEND
viewport.transparent_bg = true
elif XRInterface.XR_ENV_BLEND_MODE_ADDITIVE in modes:
xr_interface.environment_blend_mode = XRInterface.XR_ENV_BLEND_MODE_ADDITIVE
viewport.transparent_bg = false
else:
return false
environment.background_mode = Environment.BG_COLOR
environment.background_color = Color(0.0, 0.0, 0.0, 0.0)
environment.ambient_light_source = Environment.AMBIENT_SOURCE_COLOR
return true
func switch_to_vr() -> bool:
var xr_interface: XRInterface = XRServer.primary_interface
if xr_interface:
var modes = xr_interface.get_supported_environment_blend_modes()
if XRInterface.XR_ENV_BLEND_MODE_OPAQUE in modes:
xr_interface.environment_blend_mode = XRInterface.XR_ENV_BLEND_MODE_OPAQUE
else:
return false
viewport.transparent_bg = false
environment.background_mode = Environment.BG_SKY
environment.ambient_light_source = Environment.AMBIENT_SOURCE_BG
return true
阴影转不透明模式
阴影转不透明( Shadow to opacity )是 Godot 空间着色器的一种渲染模式,在 Godot 3 中专门为 AR 引入。这种特殊的渲染模式会根据表面阴影决定其透明程度:当表面越多地处于阴影中,表面就变得越不透明。而表面完全被照亮时,表面会变得完全透明,从而显示出真实世界。
但是,表面实际上是在不透明状态下渲染的。使用该模式会导致两个后果:
由于深度缓冲区和颜色缓冲区都被写入,即使表面完全透明,我们仍会遮挡其后方的几何体。
由于我们将表面在阴影中变得不透明,因此虚拟物体可以在现实世界的物体上投射阴影。
这使得以下应用场景成为可能:
你可以在现实世界的桌子周围渲染一个盒子网格,这样即使有虚拟物体放在桌子下面,桌子也能保持可见。虚拟物体会被正确地遮挡。当将虚拟物体放在现实世界的桌子上时,会在桌子上投下阴影。
在使用手部追踪功能渲染手部网格时,你可以使用这种渲染模式的着色器,以确保你的手能正确地遮挡虚拟物体。
以下着色器代码可以作为实现该功能的良好基础:
shader_type spatial;
render_mode blend_mix, depth_draw_opaque, cull_back, shadow_to_opacity;
void fragment() {
ALBEDO = vec3(0.0, 0.0, 0.0);
}
相关限制可能因 XR 接口的实现而有所不同。
该功能仍在完善中。