1+ #if UNITY_EDITOR
2+ using System ;
3+ using System . Collections . Generic ;
4+ using UnityEngine . Profiling ;
5+ using UnityEngine . SceneManagement ;
6+ using Unity . Collections ;
7+ using UnityEditor ;
8+
9+ namespace UnityEngine . Rendering . HighDefinition
10+ {
11+ /// <summary>
12+ /// A manager to enqueue extra probe rendering outside of probe volumes.
13+ /// </summary>
14+ public class AdditionalGIBakeRequestsManager
15+ {
16+ // The baking ID for the extra requests
17+ // TODO: Need to ensure this never conflicts with bake IDs from others interacting with the API.
18+ // In our project, this is ProbeVolumes.
19+ internal static readonly int s_BakingID = 912345678 ;
20+
21+ private static AdditionalGIBakeRequestsManager s_Instance = new AdditionalGIBakeRequestsManager ( ) ;
22+ /// <summary>
23+ /// Get the manager that governs the additional light probe rendering requests.
24+ /// </summary>
25+ public static AdditionalGIBakeRequestsManager instance { get { return s_Instance ; } }
26+
27+ private AdditionalGIBakeRequestsManager ( )
28+ {
29+ SubscribeOnBakeStarted ( ) ;
30+ }
31+
32+ ~ AdditionalGIBakeRequestsManager ( )
33+ {
34+ UnsubscribeOnBakeStarted ( ) ;
35+ }
36+
37+ private static List < SphericalHarmonicsL2 > m_SHCoefficients = new List < SphericalHarmonicsL2 > ( ) ;
38+ private static List < Vector3 > m_RequestPositions = new List < Vector3 > ( ) ;
39+ private static int m_FreelistHead = - 1 ;
40+
41+ private static readonly Vector2 s_FreelistSentinel = new Vector2 ( float . MaxValue , float . MaxValue ) ;
42+
43+ /// <summary>
44+ /// Enqueue a request for probe rendering at the specified location.
45+ /// </summary>
46+ /// <param name ="capturePosition"> The position at which a probe is baked.</param>
47+ /// <returns>An ID that can be used to retrieve the data once it has been computed</returns>
48+ public int EnqueueRequest ( Vector3 capturePosition )
49+ {
50+ Debug . Assert ( ComputeCapturePositionIsValid ( capturePosition ) ) ;
51+
52+ if ( m_FreelistHead >= 0 )
53+ {
54+ int requestID = m_FreelistHead ;
55+ Debug . Assert ( requestID < m_RequestPositions . Count ) ;
56+ m_FreelistHead = ComputeFreelistNext ( m_RequestPositions [ requestID ] ) ;
57+ m_RequestPositions [ requestID ] = capturePosition ;
58+ m_SHCoefficients [ requestID ] = new SphericalHarmonicsL2 ( ) ;
59+ return requestID ;
60+ }
61+ else
62+ {
63+ int requestID = m_RequestPositions . Count ;
64+ m_RequestPositions . Add ( capturePosition ) ;
65+ m_SHCoefficients . Add ( new SphericalHarmonicsL2 ( ) ) ;
66+ return requestID ;
67+ }
68+ }
69+
70+ /// <summary>
71+ /// Enqueue a request for probe rendering at the specified location.
72+ /// </summary>
73+ /// <param name ="requestID"> An ID that can be used to retrieve the data once it has been computed</param>
74+ /// <returns>An ID that can be used to retrieve the data once it has been computed</returns>
75+ public void DequeueRequest ( int requestID )
76+ {
77+ Debug . Assert ( requestID >= 0 && requestID < m_RequestPositions . Count ) ;
78+
79+ m_RequestPositions [ requestID ] = new Vector3 ( s_FreelistSentinel . x , s_FreelistSentinel . y , m_FreelistHead ) ;
80+ m_SHCoefficients [ requestID ] = new SphericalHarmonicsL2 ( ) ;
81+ m_FreelistHead = requestID ;
82+ }
83+
84+ private bool ComputeCapturePositionIsValid ( Vector3 capturePosition )
85+ {
86+ return ! ( ( capturePosition . x == s_FreelistSentinel . x ) && ( capturePosition . y == s_FreelistSentinel . y ) ) ;
87+ }
88+
89+ private int ComputeFreelistNext ( Vector3 capturePosition )
90+ {
91+ Debug . Assert ( ComputeRequestIsFree ( capturePosition ) ) ;
92+
93+ int freelistNext = ( int ) capturePosition . z ;
94+ Debug . Assert ( freelistNext >= - 1 && freelistNext < m_RequestPositions . Count ) ;
95+ return freelistNext ;
96+ }
97+
98+ private bool ComputeRequestIsFree ( int requestID )
99+ {
100+ Debug . Assert ( requestID >= 0 && requestID < m_RequestPositions . Count ) ;
101+ Vector3 requestPosition = m_RequestPositions [ requestID ] ;
102+ return ComputeRequestIsFree ( requestPosition ) ;
103+ }
104+
105+ private bool ComputeRequestIsFree ( Vector3 capturePosition )
106+ {
107+ return ( capturePosition . x == s_FreelistSentinel . x ) && ( capturePosition . y == s_FreelistSentinel . y ) ;
108+ }
109+
110+ /// <summary>
111+ /// 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.
112+ /// </summary>
113+ /// <param name ="requestID"> The request ID that has been given by the manager through a previous EnqueueRequest.</param>
114+ /// <param name ="sh"> The output SH coefficients that have been computed.</param>
115+ /// <returns>Whether the request for light probe rendering has been fulfilled and sh is valid.</returns>
116+ public bool RetrieveProbeSH ( int requestID , out SphericalHarmonicsL2 sh )
117+ {
118+ if ( requestID >= 0 && requestID < m_SHCoefficients . Count
119+ && ComputeCapturePositionIsValid ( m_RequestPositions [ requestID ] ) )
120+ {
121+ sh = m_SHCoefficients [ requestID ] ;
122+ return true ;
123+ }
124+ else
125+ {
126+ sh = new SphericalHarmonicsL2 ( ) ;
127+ return false ;
128+ }
129+ }
130+
131+ /// <summary>
132+ /// Update the capture location for the probe request.
133+ /// </summary>
134+ /// <param name ="requestID"> The request ID that has been given by the manager through a previous EnqueueRequest.</param>
135+ /// <param name ="newPositionnewPosition"> The position at which a probe is baked.</param>
136+ public int UpdatePositionForRequest ( int requestID , Vector3 newPosition )
137+ {
138+ if ( requestID >= 0 && requestID < m_RequestPositions . Count )
139+ {
140+ Debug . Assert ( ComputeCapturePositionIsValid ( m_RequestPositions [ requestID ] ) ) ;
141+ m_RequestPositions [ requestID ] = newPosition ;
142+ m_SHCoefficients [ requestID ] = new SphericalHarmonicsL2 ( ) ;
143+ return requestID ;
144+ }
145+ else
146+ {
147+ return EnqueueRequest ( newPosition ) ;
148+ }
149+ }
150+
151+ private void SubscribeOnBakeStarted ( )
152+ {
153+ UnsubscribeOnBakeStarted ( ) ;
154+ Lightmapping . bakeStarted += AddRequestsToLightmapper ;
155+ }
156+
157+ private void UnsubscribeOnBakeStarted ( )
158+ {
159+ Lightmapping . bakeStarted -= AddRequestsToLightmapper ;
160+ RemoveRequestsFromLightmapper ( ) ;
161+ }
162+
163+ internal void AddRequestsToLightmapper ( )
164+ {
165+ UnityEditor . Experimental . Lightmapping . SetAdditionalBakedProbes ( s_BakingID , m_RequestPositions . ToArray ( ) ) ;
166+
167+ Lightmapping . bakeCompleted -= OnAdditionalProbesBakeCompleted ;
168+ Lightmapping . bakeCompleted += OnAdditionalProbesBakeCompleted ;
169+ }
170+
171+ private void RemoveRequestsFromLightmapper ( )
172+ {
173+ UnityEditor . Experimental . Lightmapping . SetAdditionalBakedProbes ( s_BakingID , null ) ;
174+ }
175+
176+ private void OnAdditionalProbesBakeCompleted ( )
177+ {
178+ Lightmapping . bakeCompleted -= OnAdditionalProbesBakeCompleted ;
179+
180+ var sh = new NativeArray < SphericalHarmonicsL2 > ( m_RequestPositions . Count , Allocator . Temp , NativeArrayOptions . UninitializedMemory ) ;
181+ var validity = new NativeArray < float > ( m_RequestPositions . Count , Allocator . Temp , NativeArrayOptions . UninitializedMemory ) ;
182+ var bakedProbeOctahedralDepth = new NativeArray < float > ( m_RequestPositions . Count * 64 , Allocator . Temp , NativeArrayOptions . UninitializedMemory ) ;
183+
184+ UnityEditor . Experimental . Lightmapping . GetAdditionalBakedProbes ( s_BakingID , sh , validity , bakedProbeOctahedralDepth ) ;
185+
186+ SetSHCoefficients ( sh ) ;
187+ PushSHCoefficientsToReflectionProbes ( ) ;
188+
189+ sh . Dispose ( ) ;
190+ validity . Dispose ( ) ;
191+ bakedProbeOctahedralDepth . Dispose ( ) ;
192+ }
193+
194+ private void SetSHCoefficients ( NativeArray < SphericalHarmonicsL2 > sh )
195+ {
196+ Debug . Assert ( sh . Length == m_SHCoefficients . Count ) ;
197+ for ( int i = 0 ; i < sh . Length ; ++ i )
198+ {
199+ m_SHCoefficients [ i ] = sh [ i ] ;
200+ }
201+ }
202+
203+ private void PushSHCoefficientsToReflectionProbes ( )
204+ {
205+ List < HDProbe > hdProbes = HDProbe . GetInstances ( ) ;
206+ foreach ( var hdProbe in hdProbes )
207+ {
208+ hdProbe . TryUpdateLuminanceSHL2ForNormalization ( ) ;
209+ }
210+ }
211+ }
212+ }
213+ #endif
0 commit comments