using System;
using UnityEngine.Serialization;
namespace UnityEngine.Rendering.HighDefinition
{
///
/// A bit flag for each camera settings.
///
[Flags]
public enum CameraSettingsFields
{
/// No field
none = 0,
/// BufferClear.clearColorMode
bufferClearColorMode = 1 << 1,
/// BufferClear.backgroundColorHDR
bufferClearBackgroundColorHDR = 1 << 2,
/// BufferClear.clearDepth
bufferClearClearDepth = 1 << 3,
/// volumes.layerMask
volumesLayerMask = 1 << 4,
/// volumes.anchorOverride
volumesAnchorOverride = 1 << 5,
/// frustum.mode
frustumMode = 1 << 6,
/// frustum.aspect
frustumAspect = 1 << 7,
/// frustum.farClipPlane
frustumFarClipPlane = 1 << 8,
/// frustum.nearClipPlane
frustumNearClipPlane = 1 << 9,
/// frustum.fieldOfView
frustumFieldOfView = 1 << 10,
/// frustum.projectionMatrix
frustumProjectionMatrix = 1 << 11,
/// culling.useOcclusionCulling
cullingUseOcclusionCulling = 1 << 12,
/// culling.cullingMask
cullingCullingMask = 1 << 13,
/// culling.invertFaceCulling
cullingInvertFaceCulling = 1 << 14,
/// culling.renderingSettings
customRenderingSettings = 1 << 15,
/// flipYMode
flipYMode = 1 << 16,
/// frameSettings
frameSettings = 1 << 17,
/// probeLayerMask
probeLayerMask = 1 << 18
}
/// The overriden fields of a camera settings.
[Serializable]
public struct CameraSettingsOverride
{
///
/// Backed value.
///
public CameraSettingsFields camera;
}
/// Contains all settings required to setup a camera in HDRP.
[Serializable]
public struct CameraSettings
{
/// Defines how color and depth buffers are cleared.
[Serializable]
public struct BufferClearing
{
/// Default value.
[Obsolete("Since 2019.3, use BufferClearing.NewDefault() instead.")]
public static readonly BufferClearing @default = default;
/// Default value.
/// The default value.
public static BufferClearing NewDefault() => new BufferClearing
{
clearColorMode = HDAdditionalCameraData.ClearColorMode.Sky,
backgroundColorHDR = new Color32(6, 18, 48, 0),
clearDepth = true
};
/// Define the source for the clear color.
public HDAdditionalCameraData.ClearColorMode clearColorMode;
///
/// The color to use when
/// == .
///
[ColorUsage(true, true)]
public Color backgroundColorHDR;
/// True to clear the depth.
public bool clearDepth;
}
/// Defines how the volume framework is queried.
[Serializable]
public struct Volumes
{
/// Default value.
[Obsolete("Since 2019.3, use Volumes.NewDefault() instead.")]
public static readonly Volumes @default = default;
/// Default value.
/// The default value.
public static Volumes NewDefault() => new Volumes
{
layerMask = -1,
anchorOverride = null
};
/// The to use for the volumes.
public LayerMask layerMask;
/// If not null, define the location of the evaluation of the volume framework.
public Transform anchorOverride;
}
/// Defines the projection matrix of the camera.
[Serializable]
public struct Frustum
{
// Below 1e-5, it causes errors
// in `ScriptableShadowsUtility::GetPSSMSplitMatricesAndCulling`: "Expanding invalid MinMaxAABB"
// So we use 1e-5 as the minimum value.
/// The near clip plane value will be above this value.
public const float MinNearClipPlane = 1e-5f;
/// The far clip plane value will be at least above +
public const float MinFarClipPlane = 1e-4f;
/// Default value.
[Obsolete("Since 2019.3, use Frustum.NewDefault() instead.")]
public static readonly Frustum @default = default;
/// Default value.
/// The default value.
public static Frustum NewDefault() => new Frustum
{
mode = Mode.ComputeProjectionMatrix,
aspect = 1.0f,
farClipPlaneRaw = 1000.0f,
nearClipPlaneRaw = 0.1f,
fieldOfView = 90.0f,
projectionMatrix = Matrix4x4.identity
};
/// Defines how the projection matrix is computed.
public enum Mode
{
///
/// For perspective projection, the matrix is computed from ,
/// , and parameters.
///
/// Orthographic projection is not currently supported.
///
ComputeProjectionMatrix,
/// The projection matrix provided is assigned.
UseProjectionMatrixField
}
/// Which mode will be used for the projection matrix.
public Mode mode;
/// Aspect ratio of the frustum (width/height).
public float aspect;
///
/// Far clip plane distance.
///
/// Value that will be stored for the far clip plane distance.
/// IF you need the effective far clip plane distance, use .
///
[FormerlySerializedAs("farClipPlane")]
public float farClipPlaneRaw;
///
/// Near clip plane distance.
///
/// Value that will be stored for the near clip plane distance.
/// IF you need the effective near clip plane distance, use .
///
[FormerlySerializedAs("nearClipPlane")]
public float nearClipPlaneRaw;
///
/// Effective far clip plane distance.
///
/// Use this value to compute the projection matrix.
///
/// This value is valid to compute a projection matrix.
/// If you need the raw stored value, see instead.
///
public float farClipPlane => Mathf.Max(nearClipPlaneRaw + MinFarClipPlane, farClipPlaneRaw);
///
/// Effective near clip plane distance.
///
/// Use this value to compute the projection matrix.
///
/// This value is valid to compute a projection matrix.
/// If you need the raw stored value, see instead.
///
public float nearClipPlane => Mathf.Max(MinNearClipPlane, nearClipPlaneRaw);
/// Field of view for perspective matrix (for y axis, in degree).
[Range(1, 179.0f)]
public float fieldOfView;
/// Projection matrix used for mode.
public Matrix4x4 projectionMatrix;
/// Compute the projection matrix based on the mode and settings provided.
/// The projection matrix.
public Matrix4x4 ComputeProjectionMatrix()
{
return Matrix4x4.Perspective(HDUtils.ClampFOV(fieldOfView), aspect, nearClipPlane, farClipPlane);
}
///
/// Get the projection matrix used depending on the projection mode.
///
/// The projection matrix
public Matrix4x4 GetUsedProjectionMatrix()
{
switch (mode)
{
case Mode.ComputeProjectionMatrix: return ComputeProjectionMatrix();
case Mode.UseProjectionMatrixField: return projectionMatrix;
default: throw new ArgumentException();
}
}
}
/// Defines the culling settings of the camera.
[Serializable]
public struct Culling
{
/// Default value.
[Obsolete("Since 2019.3, use Culling.NewDefault() instead.")]
public static readonly Culling @default = default;
/// Default value.
/// The default value.
public static Culling NewDefault() => new Culling
{
cullingMask = -1,
useOcclusionCulling = true,
sceneCullingMaskOverride = 0
};
/// True when occlusion culling will be performed during rendering, false otherwise.
public bool useOcclusionCulling;
/// The mask for visible objects.
public LayerMask cullingMask;
/// Scene culling mask override.
public ulong sceneCullingMaskOverride;
}
/// Default value.
[Obsolete("Since 2019.3, use CameraSettings.defaultCameraSettingsNonAlloc instead.")]
public static readonly CameraSettings @default = default;
/// Default value.
/// The default value and allocate ~250B of garbage.
public static CameraSettings NewDefault() => new CameraSettings
{
bufferClearing = BufferClearing.NewDefault(),
culling = Culling.NewDefault(),
renderingPathCustomFrameSettings = FrameSettings.NewDefaultCamera(),
frustum = Frustum.NewDefault(),
customRenderingSettings = false,
volumes = Volumes.NewDefault(),
flipYMode = HDAdditionalCameraData.FlipYMode.Automatic,
invertFaceCulling = false,
probeLayerMask = ~0,
probeRangeCompressionFactor = 1.0f
};
/// Default camera settings.
public static readonly CameraSettings defaultCameraSettingsNonAlloc = NewDefault();
///
/// Extract the CameraSettings from an HDCamera
///
/// The camera to extract from
/// The CameraSettings
public static CameraSettings From(HDCamera hdCamera)
{
var settings = defaultCameraSettingsNonAlloc;
settings.culling.cullingMask = hdCamera.camera.cullingMask;
settings.culling.useOcclusionCulling = hdCamera.camera.useOcclusionCulling;
settings.culling.sceneCullingMaskOverride = HDUtils.GetSceneCullingMaskFromCamera(hdCamera.camera);
settings.frustum.aspect = hdCamera.camera.aspect;
settings.frustum.farClipPlaneRaw = hdCamera.camera.farClipPlane;
settings.frustum.nearClipPlaneRaw = hdCamera.camera.nearClipPlane;
settings.frustum.fieldOfView = hdCamera.camera.fieldOfView;
settings.frustum.mode = Frustum.Mode.UseProjectionMatrixField;
settings.frustum.projectionMatrix = hdCamera.camera.projectionMatrix;
settings.invertFaceCulling = false;
HDAdditionalCameraData add;
if (hdCamera.camera.TryGetComponent(out add))
{
settings.customRenderingSettings = add.customRenderingSettings;
settings.bufferClearing.backgroundColorHDR = add.backgroundColorHDR;
settings.bufferClearing.clearColorMode = add.clearColorMode;
settings.bufferClearing.clearDepth = add.clearDepth;
settings.flipYMode = add.flipYMode;
settings.renderingPathCustomFrameSettings = add.renderingPathCustomFrameSettings;
settings.renderingPathCustomFrameSettingsOverrideMask = add.renderingPathCustomFrameSettingsOverrideMask;
settings.volumes = new Volumes
{
anchorOverride = add.volumeAnchorOverride,
layerMask = add.volumeLayerMask
};
settings.probeLayerMask = add.probeLayerMask;
settings.invertFaceCulling = add.invertFaceCulling;
}
// (case 1131731) Camera.RenderToCubemap inverts faces
// Unity's API is using LHS standard when rendering cubemaps, so we need to invert the face culling
// in that specific case.
// We try to guess with a lot of constraints when this is the case.
var isLHSViewMatrix = hdCamera.camera.worldToCameraMatrix.determinant > 0;
var isPerspectiveMatrix = Mathf.Approximately(hdCamera.camera.projectionMatrix.m32, -1);
var isFOV45Degrees = Mathf.Approximately(hdCamera.camera.projectionMatrix.m00, 1)
&& Mathf.Approximately(hdCamera.camera.projectionMatrix.m11, 1);
if (isLHSViewMatrix && isPerspectiveMatrix && isFOV45Degrees)
settings.invertFaceCulling = true;
return settings;
}
/// Override rendering settings if true.
public bool customRenderingSettings;
/// Frame settings to use.
public FrameSettings renderingPathCustomFrameSettings;
/// Frame settings mask to use.
public FrameSettingsOverrideMask renderingPathCustomFrameSettingsOverrideMask;
/// Buffer clearing settings to use.
public BufferClearing bufferClearing;
/// Volumes settings to use.
public Volumes volumes;
/// Frustum settings to use.
public Frustum frustum;
/// Culling settings to use.
public Culling culling;
/// True to invert face culling, false otherwise.
public bool invertFaceCulling;
/// The mode to use when we want to flip the Y axis.
public HDAdditionalCameraData.FlipYMode flipYMode;
/// The layer mask to use to filter probes that can influence this camera.
public LayerMask probeLayerMask;
/// Which default FrameSettings should be used when rendering with these parameters.
public FrameSettingsRenderType defaultFrameSettings;
// Marked as internal as it is here just for propagation purposes, the correct way to edit this value is through the probe itself.
internal float probeRangeCompressionFactor;
[SerializeField]
[FormerlySerializedAs("renderingPath")]
[Obsolete("For data migration")]
internal int m_ObsoleteRenderingPath;
#pragma warning disable 618 // Type or member is obsolete
[SerializeField]
[FormerlySerializedAs("frameSettings")]
[Obsolete("For data migration")]
internal ObsoleteFrameSettings m_ObsoleteFrameSettings;
#pragma warning restore 618
internal Hash128 GetHash()
{
var h = new Hash128();
var h2 = new Hash128();
HashUtilities.ComputeHash128(ref bufferClearing, ref h);
HashUtilities.ComputeHash128(ref culling, ref h2);
HashUtilities.AppendHash(ref h2, ref h);
HashUtilities.ComputeHash128(ref customRenderingSettings, ref h2);
HashUtilities.AppendHash(ref h2, ref h);
HashUtilities.ComputeHash128(ref defaultFrameSettings, ref h2);
HashUtilities.AppendHash(ref h2, ref h);
HashUtilities.ComputeHash128(ref flipYMode, ref h2);
HashUtilities.AppendHash(ref h2, ref h);
HashUtilities.ComputeHash128(ref frustum, ref h2);
HashUtilities.AppendHash(ref h2, ref h);
HashUtilities.ComputeHash128(ref invertFaceCulling, ref h2);
HashUtilities.AppendHash(ref h2, ref h);
HashUtilities.ComputeHash128(ref probeLayerMask, ref h2);
HashUtilities.AppendHash(ref h2, ref h);
HashUtilities.ComputeHash128(ref probeRangeCompressionFactor, ref h2);
HashUtilities.AppendHash(ref h2, ref h);
HashUtilities.ComputeHash128(ref renderingPathCustomFrameSettings, ref h2);
HashUtilities.AppendHash(ref h2, ref h);
HashUtilities.ComputeHash128(ref renderingPathCustomFrameSettingsOverrideMask, ref h2);
HashUtilities.AppendHash(ref h2, ref h);
int volumeHash = volumes.GetHashCode();
h2 = new Hash128((ulong)volumeHash, 0);
HashUtilities.AppendHash(ref h2, ref h);
return h;
}
}
}