/// <summary> /// Compute the camera settings from the probe settings /// </summary> /// <param name="settings">The probe settings.</param> /// <param name="position">The probe position.</param> /// <param name="cameraSettings">The produced camera settings.</param> /// <param name="cameraPositionSettings">The produced camera position.</param> /// <param name="overrideSceneCullingMask">Override of the scene culling mask.</param> /// <param name="referenceFieldOfView">The reference field of view.</param> /// <param name="referenceAspect">The reference aspect ratio.</param> public static void ComputeCameraSettingsFromProbeSettings( ProbeSettings settings, ProbeCapturePositionSettings position, out CameraSettings cameraSettings, out CameraPositionSettings cameraPositionSettings, ulong overrideSceneCullingMask, float referenceFieldOfView = 90, float referenceAspect = 1 ) { // Copy settings cameraSettings = settings.cameraSettings; cameraPositionSettings = CameraPositionSettings.NewDefault(); // Update settings ProbeSettingsUtilities.ApplySettings( ref settings, ref position, ref cameraSettings, ref cameraPositionSettings, referenceFieldOfView, referenceAspect ); cameraSettings.culling.sceneCullingMaskOverride = overrideSceneCullingMask; }
/// <summary>Perform a rendering into <paramref name="target"/>.</summary> /// <example> /// How to perform standard rendering: /// <code> /// class StandardRenderingExample /// { /// public void Render() /// { /// // Copy default settings /// var settings = CameraRenderSettings.Default; /// // Adapt default settings to our custom usage /// settings.position.position = new Vector3(0, 1, 0); /// settings.camera.frustum.fieldOfView = 60.0f; /// // Get our render target /// var rt = new RenderTexture(128, 128, 1, GraphicsFormat.B8G8R8A8_SNorm); /// HDRenderUtilities.Render(settings, rt); /// // Do something with rt /// rt.Release(); /// } /// } /// </code> /// /// How to perform a cubemap rendering: /// <code> /// class CubemapRenderExample /// { /// public void Render() /// { /// // Copy default settings /// var settings = CameraRenderSettings.Default; /// // Adapt default settings to our custom usage /// settings.position.position = new Vector3(0, 1, 0); /// settings.camera.physical.iso = 800.0f; /// // Frustum settings are ignored and driven by the cubemap rendering /// // Get our render target /// var rt = new RenderTexture(128, 128, 1, GraphicsFormat.B8G8R8A8_SNorm) /// { /// dimension = TextureDimension.Cube /// }; /// // The TextureDimension is detected and the renderer will perform a cubemap rendering. /// HDRenderUtilities.Render(settings, rt); /// // Do something with rt /// rt.Release(); /// } /// } /// </code> /// </example> /// <param name="settings">Settings for the camera.</param> /// <param name="position">Position for the camera.</param> /// <param name="target">Target to render to.</param> /// <param name="staticFlags">Only used in the Editor fo cubemaps. /// This is bitmask of <see cref="UnityEditor.StaticEditorFlags"/> only objects with these flags will be rendered /// </param> public static void Render( CameraSettings settings, CameraPositionSettings position, Texture target, uint staticFlags = 0 ) { // Argument checking if (target == null) { throw new ArgumentNullException(nameof(target)); } var rtTarget = target as RenderTexture; var cubeTarget = target as Cubemap; switch (target.dimension) { case TextureDimension.Tex2D: if (rtTarget == null) { throw new ArgumentException("'target' must be a RenderTexture when rendering into a 2D texture"); } break; case TextureDimension.Cube: break; default: throw new ArgumentException("Rendering into a target of dimension " + $"{target.dimension} is not supported"); } var camera = NewRenderingCamera(); try { camera.ApplySettings(settings); camera.ApplySettings(position); switch (target.dimension) { case TextureDimension.Tex2D: { #if DEBUG Debug.LogWarning( "A static flags bitmask was provided but this is ignored when rendering into a Tex2D" ); #endif Assert.IsNotNull(rtTarget); camera.targetTexture = rtTarget; camera.Render(); camera.targetTexture = null; target.IncrementUpdateCount(); break; } case TextureDimension.Cube: { Assert.IsTrue(rtTarget != null || cubeTarget != null); var canHandleStaticFlags = false; #if UNITY_EDITOR canHandleStaticFlags = true; #endif // ReSharper disable ConditionIsAlwaysTrueOrFalse if (canHandleStaticFlags && staticFlags != 0) // ReSharper restore ConditionIsAlwaysTrueOrFalse { #if UNITY_EDITOR UnityEditor.Rendering.EditorCameraUtils.RenderToCubemap( camera, rtTarget, -1, (UnityEditor.StaticEditorFlags)staticFlags ); #endif } else { // ReSharper disable ConditionIsAlwaysTrueOrFalse if (!canHandleStaticFlags && staticFlags != 0) // ReSharper restore ConditionIsAlwaysTrueOrFalse { Debug.LogWarning( "A static flags bitmask was provided but this is ignored in player builds" ); } if (rtTarget != null) { camera.RenderToCubemap(rtTarget); } if (cubeTarget != null) { camera.RenderToCubemap(cubeTarget); } } target.IncrementUpdateCount(); break; } } } finally { CoreUtils.Destroy(camera.gameObject); } }
/// <summary> /// Apply <paramref name="settings"/> and <paramref name="probePosition"/> to /// <paramref name="cameraPosition"/> and <paramref name="cameraSettings"/>. /// </summary> /// <param name="settings">Settings to apply. (Read only)</param> /// <param name="probePosition">Position to apply. (Read only)</param> /// <param name="cameraSettings">Settings to update.</param> /// <param name="cameraPosition">Position to update.</param> public static void ApplySettings( ref ProbeSettings settings, // In Parameter ref ProbeCapturePositionSettings probePosition, // In parameter ref CameraSettings cameraSettings, // InOut parameter ref CameraPositionSettings cameraPosition, // InOut parameter float referenceFieldOfView = 90 ) { cameraSettings = settings.camera; // Compute the modes for each probe type PositionMode positionMode; bool useReferenceTransformAsNearClipPlane; switch (settings.type) { case ProbeSettings.ProbeType.PlanarProbe: positionMode = PositionMode.MirrorReferenceTransformWithProbePlane; useReferenceTransformAsNearClipPlane = true; ApplyPlanarFrustumHandling( ref settings, ref probePosition, ref cameraSettings, ref cameraPosition, referenceFieldOfView ); break; case ProbeSettings.ProbeType.ReflectionProbe: positionMode = PositionMode.UseProbeTransform; useReferenceTransformAsNearClipPlane = false; cameraSettings.frustum.mode = CameraSettings.Frustum.Mode.ComputeProjectionMatrix; cameraSettings.frustum.aspect = 1; cameraSettings.frustum.fieldOfView = 90; break; default: throw new ArgumentOutOfRangeException(); } // Update the position switch (positionMode) { case PositionMode.UseProbeTransform: { cameraPosition.mode = CameraPositionSettings.Mode.ComputeWorldToCameraMatrix; var proxyMatrix = Matrix4x4.TRS(probePosition.proxyPosition, probePosition.proxyRotation, Vector3.one); cameraPosition.position = proxyMatrix.MultiplyPoint(settings.proxySettings.capturePositionProxySpace); cameraPosition.rotation = proxyMatrix.rotation * settings.proxySettings.captureRotationProxySpace; // In case of probe baking, 99% of the time, orientation of the cubemap doesn't matters // so, we build one without any rotation, thus we don't have to change the basis // during sampling the cubemap. if (settings.type == ProbeSettings.ProbeType.ReflectionProbe) { cameraPosition.rotation = Quaternion.identity; } break; } case PositionMode.MirrorReferenceTransformWithProbePlane: { cameraPosition.mode = CameraPositionSettings.Mode.UseWorldToCameraMatrixField; ApplyMirroredReferenceTransform( ref settings, ref probePosition, ref cameraSettings, ref cameraPosition ); break; } } // Update the clip plane if (useReferenceTransformAsNearClipPlane) { ApplyObliqueNearClipPlane( ref settings, ref probePosition, ref cameraSettings, ref cameraPosition ); } // Propagate the desired custom exposure cameraSettings.probeRangeCompressionFactor = settings.lighting.rangeCompressionFactor; // Frame Settings Overrides switch (settings.mode) { default: case ProbeSettings.Mode.Realtime: cameraSettings.defaultFrameSettings = FrameSettingsRenderType.RealtimeReflection; break; case ProbeSettings.Mode.Baked: case ProbeSettings.Mode.Custom: cameraSettings.defaultFrameSettings = FrameSettingsRenderType.CustomOrBakedReflection; break; } switch (settings.type) { case ProbeSettings.ProbeType.ReflectionProbe: cameraSettings.customRenderingSettings = true; break; } }