XR_ANDROID_light_estimation_cubemap
名稱字串
XR_ANDROID_light_estimation_cubemap
擴充功能類型
執行個體擴充功能
擴充功能註冊編號
722
修訂版本
1
批准狀態
未批准
擴充功能和版本依附元件
XR_ANDROID_light_estimation
上次修改日期
2025-08-06
IP 狀態
未發現任何智慧財產權聲明。
著作人
Google 的 Salar Khan
Google 的 Scott Chung
Google 的 Jared Finder
Google 的 Spencer Quin
Google 的 Levana Chen
Google 的 Nihav Jain
Google 的 Jürgen Sturm
總覽
這項擴充功能是以基本的 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陣列,執行階段會填入支援的立方體對應解析度。
立方體貼圖解析度是指立方體貼圖每個面的寬度和高度 (以像素為單位)。2 次呼叫慣用語:應用程式可以選擇在建立光線估算器控制代碼時,使用 XrCubemapLightEstimatorCreateInfoANDROID :: cubemapResolution 中支援的其中一種解析度。應用程式必須根據所選解析度和色彩格式,為 XrCubemapLightingDataANDROID 的圖像緩衝區成員分配適當的記憶體量。
有效用量 (隱含)
- 呼叫 xrEnumerateCubemapLightingResolutionsANDROID 前,
XR_ANDROID_light_estimation_cubemap擴充功能必須啟用 -
instance必須是有效的 XrInstance 控制代碼 -
resolutionCountOutput必須是指向uint32_t值的指標 - 如果
resolutionCapacityInput不是0,resolutions必須是指向resolutionCapacityInputuint32_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 的陣列,由執行階段填入支援的立方體對應顏色格式。
2 次呼叫慣用語:應用程式可以選擇在建立光線估算器控制代碼時,使用 XrCubemapLightEstimatorCreateInfoANDROID :: colorFormat 中支援的其中一種顏色格式。應用程式必須根據所選顏色格式,為 XrCubemapLightingDataANDROID 的圖像緩衝區成員分配適當的記憶體量。
有效用量 (隱含)
- 呼叫 xrEnumerateCubemapLightingColorFormatsANDROID 前,
XR_ANDROID_light_estimation_cubemap擴充功能必須啟用 -
instance必須是有效的 XrInstance 控制代碼 -
colorFormatCountOutput必須是指向uint32_t值的指標 - 如果
colorFormatCapacityInput不是0,colorFormats必須是指向colorFormatCapacityInputXrCubemapLightingColorFormatANDROID 值陣列的指標
傳回代碼
XR_SUCCESS
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_HANDLE_INVALIDXR_ERROR_INSTANCE_LOSTXR_ERROR_RUNTIME_FAILUREXR_ERROR_SIZE_INSUFFICIENTXR_ERROR_SYSTEM_INVALIDXR_ERROR_VALIDATION_FAILURE
建立 cubemap 燈光估算器控制代碼
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,或是指向結構體鏈結中下一個結構體的有效指標 -
colorFormatmust 是有效的 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)
- 擴充功能初始說明