XR_ANDROID_light_estimation_cubemap
名称字符串
XR_ANDROID_light_estimation_cubemap
扩展类型
实例扩展程序
已注册的扩展程序编号
722
修订版本
1
批准状态
未批准
扩展程序和版本依赖项
XR_ANDROID_light_estimation
上次修改日期
2025-08-06
IP 状态
没有已知的 IP 权利主张。
创作贡献者
Salar Khan,Google
Scott Chung,Google
Jared Finder,Google
Spencer Quin,Google
Levana Chen,Google
Nihav Jain,Google
Jürgen Sturm,Google
概览
此扩展程序基于基本的 XR_ANDROID_light_estimation 扩展程序构建而成。它增加了对获取立方体贴图光照估计的支持,从而提供有关物理环境中光照的更详细估计。
备注
获取光照估计数据的机制与基本扩展相同,只不过在创建光照估计器句柄时,必须将 XrCubemapLightEstimatorCreateInfoANDROID 链接到 XrLightEstimatorCreateInfoANDROID。
检查系统功能
typedef struct XrSystemCubemapLightEstimationPropertiesANDROID {
XrStructureType type;
void* next;
XrBool32 supportsCubemapLightEstimation;
} XrSystemCubemapLightEstimationPropertiesANDROID;
成员说明
type是相应结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展程序中未定义任何此类结构。supportsCubemapLightEstimation是一个XrBool32,用于指示当前系统是否支持立方体贴图光照估测。
应用可以通过在调用 xrGetSystemProperties 时使用 XrSystemCubemapLightEstimationPropertiesANDROID 结构体扩展 XrSystemProperties 来检查系统是否能够支持立方体贴图光照估计。
如果运行时针对 supportsCubemapLightEstimation 返回 XR_FALSE,并且 XrCubemapLightEstimatorCreateInfoANDROID 已链接到 XrLightEstimatorCreateInfoANDROID,则运行时必须从 xrCreateLightEstimatorANDROID 返回 XR_ERROR_FEATURE_UNSUPPORTED。
有效使用情况(隐式)
- 必须先启用
XR_ANDROID_light_estimation_cubemap扩展程序,然后才能使用 XrSystemCubemapLightEstimationPropertiesANDROID -
type必须为XR_TYPE_SYSTEM_CUBEMAP_LIGHT_ESTIMATION_PROPERTIES_ANDROID -
next必须是NULL或指向结构链中下一个结构的有效指针
获取支持的立方体贴图分辨率
XrResult xrEnumerateCubemapLightingResolutionsANDROID(
XrInstance instance,
XrSystemId systemId,
uint32_t resolutionCapacityInput,
uint32_t* resolutionCountOutput,
uint32_t* resolutions);
参数说明
instance是之前创建的 XrInstance。systemId是之前由 xrGetSystem 检索到的XrSystemId,用于获取支持的立方体贴图分辨率。resolutionCapacityInput是一个uint32_t,用于指明resolutions数组中可存储的最大元素数量。resolutionCountOutput是指向uint32_t的指针,由运行时设置,用于指示运行时写入resolutions数组的元素数量。resolutions是一个uint32_t数组,由运行时填充支持的立方体贴图分辨率。
立方体贴图分辨率表示立方体贴图每个面的宽度和高度(以像素为单位)。双调用惯用法 然后,应用可以选择在创建光照估算器句柄时使用 XrCubemapLightEstimatorCreateInfoANDROID :: cubemapResolution 中的某个受支持的分辨率。应用必须根据所选分辨率和颜色格式,为 XrCubemapLightingDataANDROID 的图像缓冲区成员分配适当的内存量。
有效使用情况(隐式)
- 必须先启用
XR_ANDROID_light_estimation_cubemap扩展程序,然后才能调用 xrEnumerateCubemapLightingResolutionsANDROID -
instance必须是有效的 XrInstance 句柄 -
resolutionCountOutput必须是指向uint32_t值的指针 - 如果
resolutionCapacityInput不为0,则resolutions必须是指向resolutionCapacityInput个uint32_t值的数组的指针
返回代码
XR_SUCCESS
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_HANDLE_INVALIDXR_ERROR_INSTANCE_LOSTXR_ERROR_RUNTIME_FAILUREXR_ERROR_SIZE_INSUFFICIENTXR_ERROR_SYSTEM_INVALIDXR_ERROR_VALIDATION_FAILURE
获取支持的立方体贴图颜色格式
XrCubemapLightingColorFormatANDROID 枚举向运行时标识要使用的立方体贴图光照的颜色格式。
typedef enum XrCubemapLightingColorFormatANDROID {
XR_CUBEMAP_LIGHTING_COLOR_FORMAT_R32G32B32_SFLOAT_ANDROID = 1,
XR_CUBEMAP_LIGHTING_COLOR_FORMAT_R32G32B32A32_SFLOAT_ANDROID = 2,
XR_CUBEMAP_LIGHTING_COLOR_FORMAT_R16G16B16A16_SFLOAT_ANDROID = 3,
XR_CUBEMAP_LIGHTING_COLOR_FORMAT_MAX_ENUM_ANDROID = 0x7FFFFFFF
} XrCubemapLightingColorFormatANDROID;
枚举具有以下含义:
枚举说明
XR_CUBEMAP_LIGHTING_COLOR_FORMAT_R32G32B32_SFLOAT_ANDROID
一种具有 3 个通道的颜色格式,其中每个通道都是一个 32 位浮点值。
XR_CUBEMAP_LIGHTING_COLOR_FORMAT_R32G32B32A32_SFLOAT_ANDROID
一种具有 4 个通道的颜色格式,其中每个通道都是一个 32 位浮点值。
XR_CUBEMAP_LIGHTING_COLOR_FORMAT_R16G16B16A16_SFLOAT_ANDROID
一种具有 4 个通道的颜色格式,其中每个通道都是一个 16 位浮点值。
XrResult xrEnumerateCubemapLightingColorFormatsANDROID(
XrInstance instance,
XrSystemId systemId,
uint32_t colorFormatCapacityInput,
uint32_t* colorFormatCountOutput,
XrCubemapLightingColorFormatANDROID* colorFormats);
参数说明
instance是之前创建的 XrInstance。systemId是之前由 xrGetSystem 检索到的XrSystemId,用于获取支持的立方体贴图分辨率。colorFormatCapacityInput是一个uint32_t,用于指明colorFormats数组中可存储的最大元素数量。colorFormatCountOutput是指向uint32_t的指针,由运行时设置,用于指示运行时写入colorFormats数组的元素数量。colorFormats是一个 XrCubemapLightingColorFormatANDROID 数组,由运行时填充支持的立方体贴图颜色格式。
双调用惯用法 然后,应用可以选择在创建光照估算器句柄时使用 XrCubemapLightEstimatorCreateInfoANDROID :: colorFormat 中支持的颜色格式之一。应用必须根据所选的颜色格式为 XrCubemapLightingDataANDROID 的图像缓冲区成员分配适当的内存量。
有效使用情况(隐式)
- 必须先启用
XR_ANDROID_light_estimation_cubemap扩展程序,然后才能调用 xrEnumerateCubemapLightingColorFormatsANDROID -
instance必须是有效的 XrInstance 句柄 -
colorFormatCountOutput必须是指向uint32_t值的指针 - 如果
colorFormatCapacityInput不为0,则colorFormats必须是指向colorFormatCapacityInput个 XrCubemapLightingColorFormatANDROID 值的数组的指针
返回代码
XR_SUCCESS
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_HANDLE_INVALIDXR_ERROR_INSTANCE_LOSTXR_ERROR_RUNTIME_FAILUREXR_ERROR_SIZE_INSUFFICIENTXR_ERROR_SYSTEM_INVALIDXR_ERROR_VALIDATION_FAILURE
创建立方体贴图光照估算器句柄
typedef struct XrCubemapLightEstimatorCreateInfoANDROID {
XrStructureType type;
const void* next;
uint32_t cubemapResolution;
XrCubemapLightingColorFormatANDROID colorFormat;
XrBool32 reproject;
} XrCubemapLightEstimatorCreateInfoANDROID;
成员说明
type是相应结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。cubemapResolution是一个uint32_t,用于指示要使用的立方体贴图照明的分辨率。colorFormat是一个 XrCubemapLightingColorFormatANDROID,用于指示要使用的立方体贴图光照数据的颜色格式。reproject是一个XrBool32,用于指示是否应将立方体贴图光照重新投影到应用的基础空间。
XrCubemapLightEstimatorCreateInfoANDROID 结构描述了用于创建 XrLightEstimatorANDROID 句柄的信息,该句柄能够提供立方体贴图光照估计值。XrCubemapLightEstimatorCreateInfoANDROID 的 cubemapResolution 成员必须设置为 xrEnumerateCubemapLightingResolutionsANDROID 返回的分辨率之一。XrCubemapLightEstimatorCreateInfoANDROID 的 colorFormat 成员必须设置为 xrEnumerateCubemapLightingColorFormatsANDROID 返回的颜色格式之一。如果应用未将分辨率设置为支持的分辨率之一,或未将颜色格式设置为支持的颜色格式之一,则运行时必须从 xrCreateLightEstimatorANDROID 返回 XR_ERROR_FEATURE_UNSUPPORTED。
有效使用情况(隐式)
-
XR_ANDROID_light_estimation_cubemap扩展程序必须先启用,然后才能使用 XrCubemapLightEstimatorCreateInfoANDROID -
type必须为XR_TYPE_CUBEMAP_LIGHT_ESTIMATOR_CREATE_INFO_ANDROID -
next必须是NULL或指向结构链中下一个结构的有效指针 -
colorFormat必须是有效的 XrCubemapLightingColorFormatANDROID 值
立方体贴图光照估算值
typedef struct XrCubemapLightingDataANDROID {
XrStructureType type;
void* next;
XrLightEstimateStateANDROID state;
uint32_t imageBufferSize;
uint8_t* imageBufferRight;
uint8_t* imageBufferLeft;
uint8_t* imageBufferTop;
uint8_t* imageBufferBottom;
uint8_t* imageBufferFront;
uint8_t* imageBufferBack;
XrQuaternionf rotation;
XrTime centerExposureTime;
} XrCubemapLightingDataANDROID;
成员说明
type是相应结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。有效结构包括 XrAmbientLightANDROID、XrSphericalHarmonicsANDROID、XrDirectionalLightANDROID。state是表示光估测状态的 XrLightEstimateStateANDROID。imageBufferSize是一个uint32_t,用于指示立方体贴图中每个面图像缓冲区的字节大小。imageBufferRight是一个uint8_t缓冲区,包含立方体贴图的右侧面图像。imageBufferLeft是一个uint8_t缓冲区,包含立方体贴图的左侧面图像。imageBufferTop是一个uint8_t缓冲区,包含立方体贴图的顶部面图像。imageBufferBottom是一个uint8_t缓冲区,包含立方体贴图的底部表面图像。imageBufferFront是一个uint8_t缓冲区,包含立方体贴图的前面图像。imageBufferBack是一个uint8_t缓冲区,包含立方体贴图的背面图像。rotation是一个 XrQuaternionf,用于指示立方体贴图的旋转。centerExposureTime是一个XrTime,用于指示拍摄立方体贴图的时间。
此结构可以链接到 XrLightEstimateANDROID。如果使用 XrCubemapLightEstimatorCreateInfoANDROID 创建了光照估算器句柄,则运行时必须仅在 xrGetLightEstimateANDROID 中填充此结构。应用在创建光照估算器句柄时,必须为图像缓冲区分配适当的内存量,该内存量取决于在 XrCubemapLightEstimatorCreateInfoANDROID :: cubemapResolution 和 XrCubemapLightEstimatorCreateInfoANDROID :: colorFormat 中设置的值。应用必须将 XrCubemapLightingDataANDROID :: imageBufferSize 设置为每个面图像缓冲区的容量(以字节为单位)。如果应用未使用立方体贴图光照估计,或者 XrCubemapLightingDataANDROID :: imageBufferSize 不足以让运行时填充图像缓冲区,则运行时必须将 XrCubemapLightingDataANDROID :: state 设置为 XR_LIGHT_ESTIMATE_STATE_INVALID_ANDROID。
如果应用在创建光照估算器句柄时将 XrCubemapLightEstimatorCreateInfoANDROID :: reproject 设置为 XR_TRUE,则运行时必须将 XrCubemapLightingDataANDROID :: rotation 设置为单位旋转,并确保内部旋转的立方体贴图重新投影到应用基准空间中单位立方体贴图的各个面上。
光照立方体贴图的布局与 OpenGL 立方体贴图布局相同,如下图所示
图 24. 立方体贴图布局。
有效使用情况(隐式)
- 必须先启用
XR_ANDROID_light_estimation_cubemap扩展程序,然后才能使用 XrCubemapLightingDataANDROID -
type必须为XR_TYPE_CUBEMAP_LIGHTING_DATA_ANDROID -
next必须是NULL或指向结构链中下一个结构的有效指针 -
state必须是有效的 XrLightEstimateStateANDROID 值 -
imageBufferRight必须是指向imageBufferSizeuint8_t值数组的指针 -
imageBufferLeft必须是指向imageBufferSizeuint8_t值数组的指针 -
imageBufferTop必须是指向imageBufferSizeuint8_t值数组的指针 -
imageBufferBottom必须是指向imageBufferSizeuint8_t值数组的指针 -
imageBufferFront必须是指向imageBufferSizeuint8_t值数组的指针 -
imageBufferBack必须是指向imageBufferSizeuint8_t值数组的指针 -
imageBufferSize参数必须大于0
光照估计的示例代码
以下示例代码演示了如何从运行时获取所有可能的光照估计量
XrSession session; // Created at app startup
XrInstance instance; // Created at app startup
XrSpace appSpace; // Created previously.
XrSystemId systemId; // Retrieved previously by xrGetSystem
PFN_xrCreateLightEstimatorANDROID xrCreateLightEstimatorANDROID; // Created previously.
PFN_xrDestroyLightEstimatorANDROID xrDestroyLightEstimatorANDROID; // Created previously.
PFN_xrGetLightEstimateANDROID xrGetLightEstimateANDROID; // Created previously.
PFN_xrEnumerateCubemapLightingResolutionsANDROID xrEnumerateCubemapLightingResolutionsANDROID; // Created previously.
PFN_xrEnumerateCubemapLightingColorFormatsANDROID xrEnumerateCubemapLightingColorFormatsANDROID; // Created previously.
XrSystemCubemapLightEstimationPropertiesANDROID props = {
.type = XR_TYPE_SYSTEM_CUBEMAP_LIGHT_ESTIMATION_PROPERTIES_ANDROID};
XrSystemProperties base = {.type = XR_TYPE_SYSTEM_PROPERTIES,
.next = &props};
CHK_XR(xrGetSystemProperties(instance, systemId, &base));
if (!props.supportsCubemapLightEstimation) {
// Cubemap light estimation is not supported
}
uint32_t cubemapResolution = 0;
std::vector<uint32_t> supportedCubemapResolutions;
uint32_t resolutionCount;
CHK_XR(xrEnumerateCubemapLightingResolutionsANDROID(
instance, systemId, 0, &resolutionCount, nullptr));
supportedCubemapResolutions.resize(resolutionCount);
if (resolutionCount == 0) {
// No cubemap lighting supported
} else {
CHK_XR(xrEnumerateCubemapLightingResolutionsANDROID(
instance, systemId, 0, &resolutionCount, supportedCubemapResolutions.data()));
cubemapResolution = supportedCubemapResolutions[0];
}
uint32_t pixelCount = cubemapResolution * cubemapResolution;
XrCubemapLightingColorFormatANDROID colorFormat;
std::vector<XrCubemapLightingColorFormatANDROID> supportedColorFormats;
uint32_t colorFormatCount;
CHK_XR(xrEnumerateCubemapLightingColorFormatsANDROID(
instance, systemId, 0, &colorFormatCount, nullptr));
supportedColorFormats.resize(colorFormatCount);
if (colorFormatCount == 0) {
// No supported color formats for cubemap lighting. Cannot use cubemap
// light estimation.
} else {
CHK_XR(xrEnumerateCubemapLightingColorFormatsANDROID(
instance, systemId, 0, &colorFormatCount, supportedColorFormats.data()));
colorFormat = supportedColorFormats[0];
}
uint32_t pixelSize = 0;
switch (colorFormat) {
case XR_CUBEMAP_LIGHTING_COLOR_FORMAT_R32G32B32_SFLOAT_ANDROID:
pixelSize = 3 * sizeof(float);
break;
case XR_CUBEMAP_LIGHTING_COLOR_FORMAT_R32G32B32A32_SFLOAT_ANDROID:
pixelSize = 4 * sizeof(float);
break;
case XR_CUBEMAP_LIGHTING_COLOR_FORMAT_R16G16B16A16_SFLOAT_ANDROID:
pixelSize = 4 * sizeof(uint16_t);
break;
default:
// Should not happen since the color format was validated previously.
break;
}
uint32_t perFaceImageBufferSize = pixelCount * pixelSize;
XrLightEstimatorANDROID estimator;
XrCubemapLightEstimatorCreateInfoANDROID cubemapCreateInfo = {
.type = XR_TYPE_CUBEMAP_LIGHT_ESTIMATOR_CREATE_INFO_ANDROID,
.cubemapResolution = cubemapResolution,
.colorFormat = colorFormat,
.reproject = XR_TRUE
};
XrLightEstimatorCreateInfoANDROID basicCreateInfo = {
.type = XR_TYPE_LIGHT_ESTIMATOR_CREATE_INFO_ANDROID,
.next = &cubemapCreateInfo};
CHK_XR(xrCreateLightEstimatorANDROID(session, &basicCreateInfo, &estimator));
std::vector<uint8_t> cubemapBuffer(perFaceImageBufferSize * 6); // 6 faces * perFaceImageBufferSize
// Every frame
XrTime updateTime; // Time used for the current frame's simulation update.
XrLightEstimateGetInfoANDROID info = {
.type = XR_TYPE_LIGHT_ESTIMATE_GET_INFO_ANDROID,
.space = appSpace,
.time = updateTime,
};
XrCubemapLightingDataANDROID cubemap = {
.type = XR_TYPE_CUBEMAP_LIGHTING_DATA_ANDROID,
.next = nullptr,
.imageBufferSize = perFaceImageBufferSize,
.imageBufferRight = cubemapBuffer.data() + 0 * perFaceImageBufferSize,
.imageBufferLeft = cubemapBuffer.data() + 1 * perFaceImageBufferSize,
.imageBufferTop = cubemapBuffer.data() + 2 * perFaceImageBufferSize,
.imageBufferBottom = cubemapBuffer.data() + 3 * perFaceImageBufferSize,
.imageBufferFront = cubemapBuffer.data() + 4 * perFaceImageBufferSize,
.imageBufferBack = cubemapBuffer.data() + 5 * perFaceImageBufferSize,
};
XrDirectionalLightANDROID directionalLight = {
.type = XR_TYPE_DIRECTIONAL_LIGHT_ANDROID,
.next = &cubemap,
};
XrSphericalHarmonicsANDROID totalSh = {
.type = XR_TYPE_SPHERICAL_HARMONICS_ANDROID,
.next = &directionalLight,
.kind = XR_SPHERICAL_HARMONICS_KIND_TOTAL_ANDROID,
};
XrSphericalHarmonicsANDROID ambientSh = {
.type = XR_TYPE_SPHERICAL_HARMONICS_ANDROID,
.next = &totalSh,
.kind = XR_SPHERICAL_HARMONICS_KIND_AMBIENT_ANDROID,
};
XrAmbientLightANDROID ambientLight = {
.type = XR_TYPE_AMBIENT_LIGHT_ANDROID,
.next = &ambientSh,
};
XrLightEstimateANDROID estimate = {
.type = XR_TYPE_LIGHT_ESTIMATE_ANDROID,
.next = &ambientLight,
};
XrResult result = xrGetLightEstimateANDROID(estimator, &info, &estimate);
if (result == XR_SUCCESS &&
estimate.state == XR_LIGHT_ESTIMATE_STATE_VALID_ANDROID) {
// use cubemap, directionalLight, totalSh, ambientSh, and
// ambientLight if each struct has a valid state field
if (cubemap.state == XR_LIGHT_ESTIMATE_STATE_VALID_ANDROID) {
// use cubemap
if (cubemapCreateInfo.reproject == XR_TRUE) {
XrQuaternionf identityQuaternion = {0.0f, 0.0f, 0.0f, 1.0f};
assert(memcmp(&cubemap.rotation, &identityQuaternion, sizeof(XrQuaternionf)) == 0);
}
}
}
// When you want to disable light estimation
CHK_XR(xrDestroyLightEstimatorANDROID(estimator));
新命令
新结构
新枚举
新的枚举常量
XR_ANDROID_LIGHT_ESTIMATION_CUBEMAP_EXTENSION_NAMEXR_ANDROID_light_estimation_cubemap_SPEC_VERSION扩展 XrStructureType:
XR_TYPE_CUBEMAP_LIGHTING_DATA_ANDROIDXR_TYPE_CUBEMAP_LIGHT_ESTIMATOR_CREATE_INFO_ANDROIDXR_TYPE_SYSTEM_CUBEMAP_LIGHT_ESTIMATION_PROPERTIES_ANDROID
问题
版本历史记录
修订版 1,2025-12-05 (Salar Khan)
- 初始扩展程序说明