// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using UnityEngine;
namespace Microsoft.MixedReality.GraphicsTools
{
///
/// Displays a simulated shadow onto a canvas using projected shadowing.
///
[RequireComponent(typeof(RectTransform))]
public class CanvasShadow : MonoBehaviour
{
[Experimental]
[SerializeField]
[Tooltip("Enables real time shadow positioning")]
private bool Realtime = false;
[SerializeField]
[Tooltip("How much bigger the shadow should be than the caster (for soft edges)")]
private float Spread = 10.0f;
[SerializeField]
[Tooltip("Raise shadow off the backing shadow receiver (avoid z fighting)")]
private float BackingOffset = -0.01f;
[SerializeField]
[Tooltip("The Directional Light that is casting shadows")]
private Light Light;
private RectTransform _casterRectTransform;
private RectTransform _shadowRectTransform;
private Transform _lightTransform;
private Plane _shadowPlane = new Plane();
private Ray _lightDirectionRay = new Ray();
private Vector2 _sizeDelta = new Vector2();
private void Start()
{
Initialize();
UpdateShadow();
}
private void Update()
{
if (Realtime == false)
{
return;
}
UpdateShadow();
}
private void Initialize()
{
_casterRectTransform = transform.parent.gameObject.GetComponent();
_shadowRectTransform = GetComponent();
if (Light != null)
{
_lightTransform = Light.transform;
}
}
private void UpdateShadow()
{
if (_lightTransform == null)
return;
Vector3 shadowLocalPosition = _casterRectTransform.localPosition;
shadowLocalPosition.z = -_casterRectTransform.localPosition.z + BackingOffset;
_shadowRectTransform.localPosition = shadowLocalPosition;
_sizeDelta.Set(Spread, Spread);
_shadowRectTransform.sizeDelta = _sizeDelta;
_shadowPlane.SetNormalAndPosition(_shadowRectTransform.forward, _shadowRectTransform.position);
_lightDirectionRay.origin = _casterRectTransform.position;
_lightDirectionRay.direction = _lightTransform.forward;
float intersectDistance;
_shadowPlane.Raycast(_lightDirectionRay, out intersectDistance);
_shadowRectTransform.position = _lightDirectionRay.GetPoint(intersectDistance);
}
#if UNITY_EDITOR
[ContextMenu("Update Shadow")]
public void UpdateShadowInEditor()
{
Initialize();
UpdateShadow();
}
#endif
}
}