Skip to main content
Version: 10 Jul 2024

Light Estimation Example

This section includes an example of detecting environment lighting on the Magic Leap 2 headset.

Simple Example

This script queries estimate data when it is ready, updates the simulated lighting and renders a material with the cubemapped texture.

caution

This feature requires the CAMERA permission to be enabled in your project's Manifest Settings. (Edit > Project Settings > Magic Leap > Manifest Settings)

using UnityEngine;
using UnityEngine.XR.OpenXR;
using UnityEngine.XR.MagicLeap;
using MagicLeap.OpenXR.Features.LightEstimation;

public class LightEstimationSampleCode : MonoBehaviour
{
private MagicLeapLightEstimationFeature _lightEstimationFeature;

[SerializeField]
private Material _skyboxMaterial;

[SerializeField]
private Light _directionalLight;

private Vector3 _estimatedLightDirection = Vector3.zero;

private bool _permissionGranted;
private readonly MLPermissions.Callbacks permissionCallbacks = new MLPermissions.Callbacks();

private void Awake()
{
permissionCallbacks.OnPermissionDenied += OnPermissionDenied;
permissionCallbacks.OnPermissionGranted += OnPermissionGranted;
permissionCallbacks.OnPermissionDeniedAndDontAskAgain += OnPermissionDenied;
MLPermissions.RequestPermission(MLPermission.Camera, permissionCallbacks);
}

// Start is called before the first frame update
void Start()
{
if (!_permissionGranted)
return;

// Obtain the Light Estimation Feature.
_lightEstimationFeature = OpenXRSettings.Instance.GetFeature<MagicLeapLightEstimationFeature>();

// Create a variable that contains the resolution of each face on the cubemap and set it to 256x256.
HDRCubemapFaceResolution cubemapFaceResolution
= HDRCubemapFaceResolution.Resolution_256x256;

// Create the light estimation.
_lightEstimationFeature.CreateLightEstimation(cubemapFaceResolution);
}

// Update is called once per frame
void Update()
{
if (!_permissionGranted)
return;

if (IsLightEstimationDataReadyToBeObtained())
{
// Obtain the light estimation data.
EstimateData estimateData
= _lightEstimationFeature.GetLightEstimationEstimateData();

ProcessEstimateData(estimateData);
}

// Make the directional light in the scene point in the correct direction.
_directionalLight.transform.rotation = Quaternion.Lerp(_directionalLight.transform.rotation,
Quaternion.LookRotation(_directionalLight.transform.position + _estimatedLightDirection), 0.01f);
}

private void ProcessEstimateData(EstimateData estimateData)
{
// Create variables for the directional light.
_estimatedLightDirection = estimateData.DirectionalLight.Direction;
Color estimatedLightColor = estimateData.DirectionalLight.Color;

Debug.Log("Estimated Light Direction: " + _estimatedLightDirection.ToString());

// Set the color of the directional light in the scene.
_directionalLight.color = estimatedLightColor;

// Obtain the cubemap data. Learn more about cubemaps here:
// https://en.wikipedia.org/wiki/Cube_mapping
Cubemap cubemap = _lightEstimationFeature
.GetEstimateCubemap(estimateData.CubeMap.Pixels, // You can obtain the pixel data from the cubemap.
(int)estimateData.CubeMap.FaceDimension);

// Update our renderer with our cubemap data.
_skyboxMaterial.SetTexture("_Tex", cubemap);
RenderSettings.customReflectionTexture = cubemap;
}

bool IsLightEstimationDataReadyToBeObtained()
{
// In order to obtain light estimation data, you must first ensure that
// the light estimation feature has been created and that our light
// estimation data is ready to be obtained.
if (_lightEstimationFeature.LightEstimationCreated
&& _lightEstimationFeature.CheckEstimationEstimateReadiness())
{
return true;
}
else return false;
}

private void OnDestroy()
{
_lightEstimationFeature.DestroyLightEstimation();
}

private void OnPermissionDenied(string permission)
{
// Logic for permission not granted
Debug.LogError($"Camera permission denied.");
}

private void OnPermissionGranted(string permission)
{
_permissionGranted = true;
}
}