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; } } }