-
Notifications
You must be signed in to change notification settings - Fork 772
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Probe Volumes: Reflection Probe Normalization by Probe Volumes added.…
… In order to enable, NormalizeReflectionProbeWithProbeVolume needs to be enabled in the Frame Settings for the Camera, and scenes need to be rebaked. Options exist on the ProbeVolumeController volume override. (#27) Co-authored-by: pastasfuture <nickb@bonfirestudios.com>
- Loading branch information
1 parent
d91cada
commit 60fb5ba
Showing
18 changed files
with
793 additions
and
97 deletions.
There are no files selected for viewing
213 changes: 213 additions & 0 deletions
213
...nity.render-pipelines.high-definition/Runtime/Lighting/AdditionalGIBakeRequestsManager.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,213 @@ | ||
#if UNITY_EDITOR | ||
using System; | ||
using System.Collections.Generic; | ||
using UnityEngine.Profiling; | ||
using UnityEngine.SceneManagement; | ||
using Unity.Collections; | ||
using UnityEditor; | ||
|
||
namespace UnityEngine.Rendering.HighDefinition | ||
{ | ||
/// <summary> | ||
/// A manager to enqueue extra probe rendering outside of probe volumes. | ||
/// </summary> | ||
public class AdditionalGIBakeRequestsManager | ||
{ | ||
// The baking ID for the extra requests | ||
// TODO: Need to ensure this never conflicts with bake IDs from others interacting with the API. | ||
// In our project, this is ProbeVolumes. | ||
internal static readonly int s_BakingID = 912345678; | ||
|
||
private static AdditionalGIBakeRequestsManager s_Instance = new AdditionalGIBakeRequestsManager(); | ||
/// <summary> | ||
/// Get the manager that governs the additional light probe rendering requests. | ||
/// </summary> | ||
public static AdditionalGIBakeRequestsManager instance { get { return s_Instance; } } | ||
|
||
private AdditionalGIBakeRequestsManager() | ||
{ | ||
SubscribeOnBakeStarted(); | ||
} | ||
|
||
~AdditionalGIBakeRequestsManager() | ||
{ | ||
UnsubscribeOnBakeStarted(); | ||
} | ||
|
||
private static List<SphericalHarmonicsL2> m_SHCoefficients = new List<SphericalHarmonicsL2>(); | ||
private static List<Vector3> m_RequestPositions = new List<Vector3>(); | ||
private static int m_FreelistHead = -1; | ||
|
||
private static readonly Vector2 s_FreelistSentinel = new Vector2(float.MaxValue, float.MaxValue); | ||
|
||
/// <summary> | ||
/// Enqueue a request for probe rendering at the specified location. | ||
/// </summary> | ||
/// <param name ="capturePosition"> The position at which a probe is baked.</param> | ||
/// <returns>An ID that can be used to retrieve the data once it has been computed</returns> | ||
public int EnqueueRequest(Vector3 capturePosition) | ||
{ | ||
Debug.Assert(ComputeCapturePositionIsValid(capturePosition)); | ||
|
||
if (m_FreelistHead >= 0) | ||
{ | ||
int requestID = m_FreelistHead; | ||
Debug.Assert(requestID < m_RequestPositions.Count); | ||
m_FreelistHead = ComputeFreelistNext(m_RequestPositions[requestID]); | ||
m_RequestPositions[requestID] = capturePosition; | ||
m_SHCoefficients[requestID] = new SphericalHarmonicsL2(); | ||
return requestID; | ||
} | ||
else | ||
{ | ||
int requestID = m_RequestPositions.Count; | ||
m_RequestPositions.Add(capturePosition); | ||
m_SHCoefficients.Add(new SphericalHarmonicsL2()); | ||
return requestID; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Enqueue a request for probe rendering at the specified location. | ||
/// </summary> | ||
/// <param name ="requestID"> An ID that can be used to retrieve the data once it has been computed</param> | ||
/// <returns>An ID that can be used to retrieve the data once it has been computed</returns> | ||
public void DequeueRequest(int requestID) | ||
{ | ||
Debug.Assert(requestID >= 0 && requestID < m_RequestPositions.Count); | ||
|
||
m_RequestPositions[requestID] = new Vector3(s_FreelistSentinel.x, s_FreelistSentinel.y, m_FreelistHead); | ||
m_SHCoefficients[requestID] = new SphericalHarmonicsL2(); | ||
m_FreelistHead = requestID; | ||
} | ||
|
||
private bool ComputeCapturePositionIsValid(Vector3 capturePosition) | ||
{ | ||
return !((capturePosition.x == s_FreelistSentinel.x) && (capturePosition.y == s_FreelistSentinel.y)); | ||
} | ||
|
||
private int ComputeFreelistNext(Vector3 capturePosition) | ||
{ | ||
Debug.Assert(ComputeRequestIsFree(capturePosition)); | ||
|
||
int freelistNext = (int)capturePosition.z; | ||
Debug.Assert(freelistNext >= -1 && freelistNext < m_RequestPositions.Count); | ||
return freelistNext; | ||
} | ||
|
||
private bool ComputeRequestIsFree(int requestID) | ||
{ | ||
Debug.Assert(requestID >= 0 && requestID < m_RequestPositions.Count); | ||
Vector3 requestPosition = m_RequestPositions[requestID]; | ||
return ComputeRequestIsFree(requestPosition); | ||
} | ||
|
||
private bool ComputeRequestIsFree(Vector3 capturePosition) | ||
{ | ||
return (capturePosition.x == s_FreelistSentinel.x) && (capturePosition.y == s_FreelistSentinel.y); | ||
} | ||
|
||
/// <summary> | ||
/// Retrieve the result of a capture request, it will return false if the request has not been fulfilled yet or the request ID is invalid. | ||
/// </summary> | ||
/// <param name ="requestID"> The request ID that has been given by the manager through a previous EnqueueRequest.</param> | ||
/// <param name ="sh"> The output SH coefficients that have been computed.</param> | ||
/// <returns>Whether the request for light probe rendering has been fulfilled and sh is valid.</returns> | ||
public bool RetrieveProbeSH(int requestID, out SphericalHarmonicsL2 sh) | ||
{ | ||
if (requestID >= 0 && requestID < m_SHCoefficients.Count | ||
&& ComputeCapturePositionIsValid(m_RequestPositions[requestID])) | ||
{ | ||
sh = m_SHCoefficients[requestID]; | ||
return true; | ||
} | ||
else | ||
{ | ||
sh = new SphericalHarmonicsL2(); | ||
return false; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Update the capture location for the probe request. | ||
/// </summary> | ||
/// <param name ="requestID"> The request ID that has been given by the manager through a previous EnqueueRequest.</param> | ||
/// <param name ="newPositionnewPosition"> The position at which a probe is baked.</param> | ||
public int UpdatePositionForRequest(int requestID, Vector3 newPosition) | ||
{ | ||
if (requestID >= 0 && requestID < m_RequestPositions.Count) | ||
{ | ||
Debug.Assert(ComputeCapturePositionIsValid(m_RequestPositions[requestID])); | ||
m_RequestPositions[requestID] = newPosition; | ||
m_SHCoefficients[requestID] = new SphericalHarmonicsL2(); | ||
return requestID; | ||
} | ||
else | ||
{ | ||
return EnqueueRequest(newPosition); | ||
} | ||
} | ||
|
||
private void SubscribeOnBakeStarted() | ||
{ | ||
UnsubscribeOnBakeStarted(); | ||
Lightmapping.bakeStarted += AddRequestsToLightmapper; | ||
} | ||
|
||
private void UnsubscribeOnBakeStarted() | ||
{ | ||
Lightmapping.bakeStarted -= AddRequestsToLightmapper; | ||
RemoveRequestsFromLightmapper(); | ||
} | ||
|
||
internal void AddRequestsToLightmapper() | ||
{ | ||
UnityEditor.Experimental.Lightmapping.SetAdditionalBakedProbes(s_BakingID, m_RequestPositions.ToArray()); | ||
|
||
Lightmapping.bakeCompleted -= OnAdditionalProbesBakeCompleted; | ||
Lightmapping.bakeCompleted += OnAdditionalProbesBakeCompleted; | ||
} | ||
|
||
private void RemoveRequestsFromLightmapper() | ||
{ | ||
UnityEditor.Experimental.Lightmapping.SetAdditionalBakedProbes(s_BakingID, null); | ||
} | ||
|
||
private void OnAdditionalProbesBakeCompleted() | ||
{ | ||
Lightmapping.bakeCompleted -= OnAdditionalProbesBakeCompleted; | ||
|
||
var sh = new NativeArray<SphericalHarmonicsL2>(m_RequestPositions.Count, Allocator.Temp, NativeArrayOptions.UninitializedMemory); | ||
var validity = new NativeArray<float>(m_RequestPositions.Count, Allocator.Temp, NativeArrayOptions.UninitializedMemory); | ||
var bakedProbeOctahedralDepth = new NativeArray<float>(m_RequestPositions.Count * 64, Allocator.Temp, NativeArrayOptions.UninitializedMemory); | ||
|
||
UnityEditor.Experimental.Lightmapping.GetAdditionalBakedProbes(s_BakingID, sh, validity, bakedProbeOctahedralDepth); | ||
|
||
SetSHCoefficients(sh); | ||
PushSHCoefficientsToReflectionProbes(); | ||
|
||
sh.Dispose(); | ||
validity.Dispose(); | ||
bakedProbeOctahedralDepth.Dispose(); | ||
} | ||
|
||
private void SetSHCoefficients(NativeArray<SphericalHarmonicsL2> sh) | ||
{ | ||
Debug.Assert(sh.Length == m_SHCoefficients.Count); | ||
for (int i = 0; i < sh.Length; ++i) | ||
{ | ||
m_SHCoefficients[i] = sh[i]; | ||
} | ||
} | ||
|
||
private void PushSHCoefficientsToReflectionProbes() | ||
{ | ||
List<HDProbe> hdProbes = HDProbe.GetInstances(); | ||
foreach (var hdProbe in hdProbes) | ||
{ | ||
hdProbe.TryUpdateLuminanceSHL2ForNormalization(); | ||
} | ||
} | ||
} | ||
} | ||
#endif |
11 changes: 11 additions & 0 deletions
11
...render-pipelines.high-definition/Runtime/Lighting/AdditionalGIBakeRequestsManager.cs.meta
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.