//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
//**************** Copyright (c) 2016 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************//
namespace BansheeEngine
{
/** @addtogroup Rendering
* @{
*/
///
/// Component that illuminates a portion of the scene covered by the light.
///
[RunInEditor]
public sealed class Light : ManagedComponent
{
private NativeLight _nativeLight;
[SerializeField]
private SerializableData serializableData = new SerializableData();
///
/// Returns the non-component version of Light that is wrapped by this component.
///
internal NativeLight Native
{
get { return _nativeLight; }
}
///
/// Light type that determines how are elements near it illuminated.
///
public LightType Type
{
get { return _nativeLight.Type; }
set { _nativeLight.Type = value; serializableData.type = value; }
}
///
/// Color emitted from the light.
///
public Color Color
{
get { return _nativeLight.Color; }
set { _nativeLight.Color = value; serializableData.color = value; }
}
///
/// Range at which the light contribution fades out to zero. Use to provide
/// a radius automatically dependant on light intensity. The radius will cut-off light contribution and therefore
/// manually set very small radius can end up being very physically incorrect.
///
public float AttenuationRadius
{
get { return _nativeLight.AttenuationRadius; }
set { _nativeLight.AttenuationRadius = value; serializableData.attenuationRadius = value; }
}
///
/// Radius of the light source. If non-zero then this light represents an area light, otherwise it is a punctual
/// light. Area lights have different attenuation then punctual lights, and their appearance in specular reflections
/// is realistic. Shape of the area light depends on light type:
/// - For directional light the shape is a disc projected on the hemisphere on the horizon. This parameter
/// represents angular radius (in degrees) of the disk and should be very small (think of how much space the Sun
/// takes on the sky - roughly 0.5 degrees).
/// - For radial light the shape is a sphere and the radius is the radius of the sphere.
/// - For spot lights the shape is a disc oriented in the direction of the spot light and the radius is the radius
/// of the disc.
///
public float SourceRadius
{
get { return _nativeLight.SourceRadius; }
set { _nativeLight.SourceRadius = value; serializableData.sourceRadius = value; }
}
///
/// Determines the power of the light source.This will be luminous flux for radial & spot lights, luminance for
/// directional lights with no area, and illuminance for directional lights with area(non-zero source radius).
///
public float Intensity
{
get { return _nativeLight.Intensity; }
set { _nativeLight.Intensity = value; serializableData.intensity = value; }
}
///
/// Total angle covered by a spot light. Ignored by other light types.
///
public Degree SpotAngle
{
get { return _nativeLight.SpotAngle; }
set { _nativeLight.SpotAngle = value; serializableData.spotAngle = value; }
}
///
/// Falloff angle covered by a spot light. Falloff angle determines at what point does light intensity starts
/// linearly falling off as the angle approaches the total spot angle. Ignored by other light types.
///
public Degree SpotFalloffAngle
{
get { return _nativeLight.SpotFalloffAngle; }
set { _nativeLight.SpotFalloffAngle = value; serializableData.spotFalloffAngle = value; }
}
///
/// If enabled the property will automatically be controlled in order to provide
/// reasonable light radius, depending on its intensity.
///
public bool UseAutoAttenuation
{
get { return _nativeLight.UseAutoAttenuation; }
set { _nativeLight.UseAutoAttenuation = value; serializableData.useAutoAttenuation = value; }
}
///
/// Determines does this light cast a shadow when rendered.
///
public bool CastsShadow
{
get { return _nativeLight.CastsShadow; }
set { _nativeLight.CastsShadow = value; serializableData.castShadows = value; }
}
///
/// Returns world space bounds that completely encompass the light's area of influence.
///
public Sphere Bounds
{
get { Native.UpdateTransform(SceneObject); return Native.Bounds; }
}
private void OnReset()
{
if (_nativeLight != null)
_nativeLight.OnDestroy();
_nativeLight = new NativeLight(SceneObject);
// Restore saved values after reset
_nativeLight.Color = serializableData.color;
_nativeLight.SpotAngle = serializableData.spotAngle;
_nativeLight.SpotFalloffAngle = serializableData.spotFalloffAngle;
_nativeLight.AttenuationRadius = serializableData.attenuationRadius;
_nativeLight.SourceRadius = serializableData.sourceRadius;
_nativeLight.Intensity = serializableData.intensity;
_nativeLight.Type = serializableData.type;
_nativeLight.CastsShadow = serializableData.castShadows;
_nativeLight.UseAutoAttenuation = serializableData.useAutoAttenuation;
}
private void OnUpdate()
{
_nativeLight.UpdateTransform(SceneObject);
}
private void OnDestroy()
{
_nativeLight.OnDestroy();
}
///
protected internal override bool CalculateBounds(out AABox box, out Sphere sphere)
{
sphere = Bounds;
Vector3 extents = new Vector3(sphere.Radius, sphere.Radius, sphere.Radius);
box = new AABox(sphere.Center - extents, sphere.Center + extents);
return true;
}
///
/// Holds all data the light component needs to persist through serialization.
///
[SerializeObject]
private class SerializableData
{
public Color color = Color.White;
public Degree spotAngle = new Degree(45);
public Degree spotFalloffAngle = new Degree(40);
public float attenuationRadius = 10.0f;
public float sourceRadius = 0.0f;
public float intensity = 5.0f;
public LightType type = LightType.Radial;
public bool castShadows = false;
public bool useAutoAttenuation = true;
}
}
/** @} */
}