using UnityEngine;
using System;
#if CINEMACHINE_HDRP || CINEMACHINE_LWRP_7_0_0
#if CINEMACHINE_HDRP_7_0_0
using UnityEngine.Rendering.HighDefinition;
#else
#if CINEMACHINE_LWRP_7_0_0
using UnityEngine.Rendering.Universal;
#else
using UnityEngine.Experimental.Rendering.HDPipeline;
#endif
#endif
#endif
namespace Cinemachine
{
///
/// Describes the FOV and clip planes for a camera. This generally mirrors the Unity Camera's
/// lens settings, and will be used to drive the Unity camera when the vcam is active.
///
[Serializable]
[DocumentationSorting(DocumentationSortingAttribute.Level.UserRef)]
public struct LensSettings
{
/// Default Lens Settings
public static LensSettings Default = new LensSettings(40f, 10f, 0.1f, 5000f, 0);
///
/// This is the camera view in vertical degrees. For cinematic people, a 50mm lens
/// on a super-35mm sensor would equal a 19.6 degree FOV
///
[Range(1f, 179f)]
[Tooltip("This is the camera view in vertical degrees. For cinematic people, a 50mm lens "
+ "on a super-35mm sensor would equal a 19.6 degree FOV")]
public float FieldOfView;
///
/// When using an orthographic camera, this defines the half-height, in world
/// co-ordinates, of the camera view.
///
[Tooltip("When using an orthographic camera, this defines the half-height, in world "
+ "coordinates, of the camera view.")]
public float OrthographicSize;
///
/// The near clip plane for this LensSettings
///
[Tooltip("This defines the near region in the renderable range of the camera frustum. "
+ "Raising this value will stop the game from drawing things near the camera, which "
+ "can sometimes come in handy. Larger values will also increase your shadow resolution.")]
public float NearClipPlane;
///
/// The far clip plane for this LensSettings
///
[Tooltip("This defines the far region of the renderable range of the camera frustum. Typically "
+ "you want to set this value as low as possible without cutting off desired distant objects")]
public float FarClipPlane;
///
/// The dutch (tilt) to be applied to the camera. In degrees
///
[Range(-180f, 180f)]
[Tooltip("Camera Z roll, or tilt, in degrees.")]
public float Dutch;
///
/// This is set every frame by the virtual camera, based on the value found in the
/// currently associated Unity camera
///
public bool Orthographic { get; set; }
///
/// This is set every frame by the virtual camera, based on the value
/// found in the currently associated Unity camera
///
public Vector2 SensorSize { get; set; }
///
/// Sensor aspect, not screen aspect. For nonphysical cameras, this is the same thing.
///
public float Aspect { get { return SensorSize.y == 0 ? 1f : (SensorSize.x / SensorSize.y); } }
///
/// This is set every frame by the virtual camera, based on the value
/// found in the currently associated Unity camera
///
public bool IsPhysicalCamera { get; set; }
/// For physical cameras only: position of the gate relative to the film back
public Vector2 LensShift;
#if CINEMACHINE_HDRP
public int Iso;
public float ShutterSpeed;
[Range(HDPhysicalCamera.kMinAperture, HDPhysicalCamera.kMaxAperture)]
public float Aperture;
[Range(HDPhysicalCamera.kMinBladeCount, HDPhysicalCamera.kMaxBladeCount)]
public int BladeCount;
public Vector2 Curvature;
[Range(0, 1)]
public float BarrelClipping;
[Range(-1, 1)]
public float Anamorphism;
#endif
///
/// Creates a new LensSettings, copying the values from the
/// supplied Camera
///
/// The Camera from which the FoV, near
/// and far clip planes will be copied.
public static LensSettings FromCamera(Camera fromCamera)
{
LensSettings lens = Default;
if (fromCamera != null)
{
lens.FieldOfView = fromCamera.fieldOfView;
lens.OrthographicSize = fromCamera.orthographicSize;
lens.NearClipPlane = fromCamera.nearClipPlane;
lens.FarClipPlane = fromCamera.farClipPlane;
#if UNITY_2018_2_OR_NEWER
lens.LensShift = fromCamera.lensShift;
#endif
lens.SnapshotCameraReadOnlyProperties(fromCamera);
#if CINEMACHINE_HDRP
if (lens.IsPhysicalCamera)
{
var pc = new HDPhysicalCamera();
#if UNITY_2019_2_OR_NEWER
fromCamera.TryGetComponent(out var hda);
#else
var hda = fromCamera.GetComponent();
#endif
if (hda != null)
pc = hda.physicalParameters;
lens.Iso = pc.iso;
lens.ShutterSpeed = pc.shutterSpeed;
lens.Aperture = pc.aperture;
lens.BladeCount = pc.bladeCount;
lens.Curvature = pc.curvature;
lens.BarrelClipping = pc.barrelClipping;
lens.Anamorphism = pc.anamorphism;
}
#endif
}
return lens;
}
///
/// Snapshot the properties that are read-only in the Camera
///
/// The Camera from which we will take the info
public void SnapshotCameraReadOnlyProperties(Camera camera)
{
if (camera != null)
{
Orthographic = camera.orthographic;
SensorSize = new Vector2(camera.aspect, 1f);
#if UNITY_2018_2_OR_NEWER
IsPhysicalCamera = camera.usePhysicalProperties;
if (IsPhysicalCamera)
SensorSize = camera.sensorSize;
else
LensShift = Vector2.zero;
#endif
}
}
///
/// Snapshot the properties that are read-only in the Camera
///
/// The LensSettings from which we will take the info
public void SnapshotCameraReadOnlyProperties(ref LensSettings lens)
{
Orthographic = lens.Orthographic;
SensorSize = lens.SensorSize;
#if UNITY_2018_2_OR_NEWER
IsPhysicalCamera = lens.IsPhysicalCamera;
if (!IsPhysicalCamera)
LensShift = Vector2.zero;
#endif
}
///
/// Explicit constructor for this LensSettings
///
/// The Vertical field of view
/// If orthographic, this is the half-height of the screen
/// The near clip plane
/// The far clip plane
/// Camera roll, in degrees. This is applied at the end
/// after shot composition.
public LensSettings(
float fov, float orthographicSize,
float nearClip, float farClip, float dutch) : this()
{
FieldOfView = fov;
OrthographicSize = orthographicSize;
NearClipPlane = nearClip;
FarClipPlane = farClip;
Dutch = dutch;
#if CINEMACHINE_HDRP
Iso = 200;
ShutterSpeed = 0.005f;
Aperture = 16;
BladeCount = 5;
Curvature = new Vector2(2, 11);
BarrelClipping = 0.25f;
Anamorphism = 0;
#endif
}
///
/// Linearly blends the fields of two LensSettings and returns the result
///
/// The LensSettings to blend from
/// The LensSettings to blend to
/// The interpolation value. Internally clamped to the range [0,1]
/// Interpolated settings
public static LensSettings Lerp(LensSettings lensA, LensSettings lensB, float t)
{
t = Mathf.Clamp01(t);
LensSettings blendedLens = new LensSettings();
blendedLens.FarClipPlane = Mathf.Lerp(lensA.FarClipPlane, lensB.FarClipPlane, t);
blendedLens.NearClipPlane = Mathf.Lerp(lensA.NearClipPlane, lensB.NearClipPlane, t);
blendedLens.FieldOfView = Mathf.Lerp(lensA.FieldOfView, lensB.FieldOfView, t);
blendedLens.OrthographicSize = Mathf.Lerp(lensA.OrthographicSize, lensB.OrthographicSize, t);
blendedLens.Dutch = Mathf.Lerp(lensA.Dutch, lensB.Dutch, t);
blendedLens.Orthographic = lensA.Orthographic && lensB.Orthographic;
blendedLens.IsPhysicalCamera = lensA.IsPhysicalCamera || lensB.IsPhysicalCamera;
blendedLens.SensorSize = Vector2.Lerp(lensA.SensorSize, lensB.SensorSize, t);
blendedLens.LensShift = Vector2.Lerp(lensA.LensShift, lensB.LensShift, t);
#if CINEMACHINE_HDRP
blendedLens.Iso = Mathf.RoundToInt(Mathf.Lerp((float)lensA.Iso, (float)lensB.Iso, t));
blendedLens.ShutterSpeed = Mathf.Lerp(lensA.ShutterSpeed, lensB.ShutterSpeed, t);
blendedLens.Aperture = Mathf.Lerp(lensA.Aperture, lensB.Aperture, t);
blendedLens.BladeCount = Mathf.RoundToInt(Mathf.Lerp(lensA.BladeCount, lensB.BladeCount, t));;
blendedLens.Curvature = Vector2.Lerp(lensA.Curvature, lensB.Curvature, t);
blendedLens.BarrelClipping = Mathf.Lerp(lensA.BarrelClipping, lensB.BarrelClipping, t);
blendedLens.Anamorphism = Mathf.Lerp(lensA.Anamorphism, lensB.Anamorphism, t);
#endif
return blendedLens;
}
/// Make sure lens settings are sane. Call this from OnValidate().
public void Validate()
{
if (!Orthographic)
NearClipPlane = Mathf.Max(NearClipPlane, 0.001f);
FarClipPlane = Mathf.Max(FarClipPlane, NearClipPlane + 0.001f);
FieldOfView = Mathf.Clamp(FieldOfView, 0.01f, 179f);
#if CINEMACHINE_HDRP
ShutterSpeed = Mathf.Max(0, ShutterSpeed);
Aperture = Mathf.Clamp(Aperture, HDPhysicalCamera.kMinAperture, HDPhysicalCamera.kMaxAperture);
BladeCount = Mathf.Clamp(BladeCount, HDPhysicalCamera.kMinBladeCount, HDPhysicalCamera.kMaxBladeCount);
BarrelClipping = Mathf.Clamp01(BarrelClipping);
Curvature.x = Mathf.Clamp(Curvature.x, HDPhysicalCamera.kMinAperture, HDPhysicalCamera.kMaxAperture);
Curvature.y = Mathf.Clamp(Curvature.y, Curvature.x, HDPhysicalCamera.kMaxAperture);
Anamorphism = Mathf.Clamp(Anamorphism, -1, 1);
#endif
}
}
}