#if UNITY_EDITOR #if NATIVE_ARRAYS #if UNITY_6000_0_OR_NEWER #if CORE_RP_1703 #define SUPPORTS_APV #endif #endif using UnityEngine; using UnityEngine.Rendering; using UnityEditor; using UnityEngine.SceneManagement; using UnityEditor.SceneManagement; using System.Reflection; using System.Collections.Generic; using Unity.Collections; #if SUPPORTS_APV public class ftAPVBaker : AdaptiveProbeVolumes.LightingBaker { int bakedProbeCount; int _stepCount; public override ulong currentStep => (ulong)bakedProbeCount; public override ulong stepCount => (ulong)_stepCount; public NativeArray irradianceResults; public NativeArray validityResults; public NativeArray masks; public override NativeArray irradiance => irradianceResults; public override NativeArray validity => validityResults; public override NativeArray occlusion => masks; bool occlusionRequested = false; bool disposeIrradiance = false; public bool irradianceSet = false; public bool masksSet = false; bool disposeMasks = false; bool anyStepsDone = false; bool finishOnStep = false; public override void Initialize(bool bakeProbeOcclusion, NativeArray probePositions, NativeArray bakedRenderingLayerMasks) { Initialize(bakeProbeOcclusion, probePositions); } public override void Initialize(bool bakeProbeOcclusion, NativeArray probePositions) { bakedProbeCount = 0; var positions = probePositions; _stepCount = positions.Length; anyStepsDone = false; finishOnStep = false; irradianceSet = false; masksSet = false; Debug.Log("Bakery APV baker initialized"); irradianceResults = new NativeArray(positions.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); validityResults = new NativeArray(positions.Length, Allocator.Persistent);//, NativeArrayOptions.UninitializedMemory); occlusionRequested = bakeProbeOcclusion; if (bakeProbeOcclusion) { masks = new NativeArray(positions.Length, Allocator.Persistent); } ftAPV.receivedPositions = probePositions; ftAPV.positionsUpdated = true; } public override bool Step() { anyStepsDone = true; if (finishOnStep) Finish(); return true; } public void Finish() { if (!anyStepsDone) { finishOnStep = true; return; } if (!irradianceSet && !masksSet) { AdaptiveProbeVolumes.Cancel(); // will cause a console error because nobody tested this function? at least it does the job } if (!irradianceSet) { irradianceResults = new NativeArray(_stepCount, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); disposeIrradiance = true; irradianceSet = true; } if (!masksSet && occlusionRequested) { masks = new NativeArray(_stepCount, Allocator.Persistent); disposeMasks = true; masksSet = true; } Debug.Log("APV bake finished for "+irradianceResults.Length+" SH probes, "+masks.Length+" occlusion probes, "+validityResults.Length+" validity results."); bakedProbeCount = _stepCount; } public override void Dispose() { if (disposeIrradiance) irradianceResults.Dispose(); if (disposeMasks) masks.Dispose(); validityResults.Dispose(); disposeIrradiance = disposeMasks = false; } } public class ftAPVSkyBaker : AdaptiveProbeVolumes.SkyOcclusionBaker { int bakedProbeCount; int _stepCount; public NativeArray skylightL1; public NativeArray skylightDir; public bool skyDataSet = false; public bool disposeData = false; public override ulong currentStep => (ulong)bakedProbeCount; public override ulong stepCount => (ulong)_stepCount; public override NativeArray occlusion => skylightL1; public override NativeArray shadingDirections => skylightDir; public override void Initialize(ProbeVolumeBakingSet bakingSet, NativeArray probePositions) { bakedProbeCount = 0; var positions = probePositions; _stepCount = positions.Length; Debug.Log("Bakery APV baker (sky occlusion) initialized"); ftAPV.skylightRequested = true; skyDataSet = false; } public override bool Step() { return true; } public void Finish() { if (!skyDataSet) { skylightL1 = new NativeArray(_stepCount, Allocator.Persistent); skylightDir = new NativeArray(_stepCount, Allocator.Persistent); disposeData = true; skyDataSet = true; } Debug.Log("APV (sky occlusion) bake finished for "+skylightL1.Length+" SH probes, "+skylightDir.Length+" directions."); bakedProbeCount = _stepCount; } public override void Dispose() { if (disposeData) { skylightL1.Dispose(); skylightDir.Dispose(); } disposeData = false; } } #endif public class ftAPV { #if SUPPORTS_APV static ftAPVBaker baker; static ftAPVSkyBaker bakerSky; #endif public static NativeArray receivedPositions; public static bool positionsUpdated; public static bool skylightRequested; public static float minVoxelSize = 0.5f; #if SUPPORTS_APV static ProbeVolumeBakingSet CreateOrReplaceAsset(ProbeVolumeBakingSet src, string path) { var dest = AssetDatabase.LoadAssetAtPath(path); if (dest == null) { AssetDatabase.CreateAsset(src, path); dest = src; } else { var guids = new List(); foreach(var guid in dest.sceneGUIDs) { guids.Add(guid); } for(int i=0; i(); bset.name = "BakeryBakingSet_" + GenerateLightingDataAssetName(); //bset.hideFlags = HideFlags.NotEditable | HideFlags.HideAndDontSave; var setDefFunc = bset.GetType().GetMethod("SetDefaults", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); if (setDefFunc == null) { Debug.LogError("Can't get ProbeVolumeBakingSet.SetDefaults()"); return false; } setDefFunc.Invoke(bset, null); if (bakingSet != null) { bset.minDistanceBetweenProbes = bakingSet.minDistanceBetweenProbes; bset.minRendererVolumeSize = bakingSet.minRendererVolumeSize; bset.probeOffset = bakingSet.probeOffset; bset.renderersLayerMask = bakingSet.renderersLayerMask; bset.simplificationLevels = bakingSet.simplificationLevels; } // Patch baking settings bset.skyOcclusion = skyOcclusion; minVoxelSize = bset.minDistanceBetweenProbes; // Save the baking set var mainScene = SceneManager.GetActiveScene(); string path = "Assets"; if (!string.IsNullOrEmpty(mainScene.path)) { path = (System.IO.Path.GetDirectoryName(mainScene.path) + "/" + mainScene.name); if (!System.IO.Directory.Exists(path)) System.IO.Directory.CreateDirectory(path); } path += "/" + bset.name + ".asset"; bset = CreateOrReplaceAsset(bset, path); //AssetDatabase.CreateAsset(bset, path); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); // Add active scene var sceneCount = EditorSceneManager.sceneCount; for(int j=0; j(otherSetPath); if (otherSet != null) { foreach(var sceneGUID in otherSet.sceneGUIDs) { if (sceneGUID == sceneToAddGUID) { if (EditorUtility.DisplayDialog("Bakery", "The scene " + scene.path + " is part of the Baking Set " + otherSetPath + ". Do you want to move the scene to a new set?", "OK", "Cancel")) { otherSet.RemoveScene(sceneGUID); if (!bset.TryAddScene(sceneToAddGUID)) { Debug.LogError("Scene " + scene.path + " was removed from Baking Set " + otherSetPath + ", but TryAddScene still failed."); return false; } else { Debug.Log("Scene " + scene.name + " moved to a new Baking Set"); solved = true; break; } } else { Debug.LogError("Scene " + scene.path + " is alreasy used in Baking Set " + otherSetPath + ". Delete the Baking Set or remove the scene from it."); return false; } } } if (solved) break; } } if (!solved) { Debug.LogError("ProbeVolumeBakingSet.TryAddScene() failed for unknown reason with scene " + scene.path); return false; } } } // Set as active ProbeReferenceVolume.instance.SetActiveBakingSet(bset); return true; } #endif public static bool Run(bool skyOcclusion) { #if SUPPORTS_APV if (!Setup(skyOcclusion)) return false; baker = new ftAPVBaker(); bakerSky = new ftAPVSkyBaker(); positionsUpdated = false; skylightRequested = false; AdaptiveProbeVolumes.SetLightingBakerOverride(baker); AdaptiveProbeVolumes.SetSkyOcclusionBakerOverride(skyOcclusion ? bakerSky : null); if (!AdaptiveProbeVolumes.BakeAsync()) { Debug.LogError("AdaptiveProbeVolumes.BakeAsync() failed"); return false; } #endif return true; } public static bool IsBaking() { #if SUPPORTS_APV return AdaptiveProbeVolumes.isRunning; #else return false; #endif } public static void SetSHs(NativeArray shs) { #if SUPPORTS_APV baker.irradianceResults = shs; baker.irradianceSet = true; #endif } public static void SetMasks(NativeArray masks) { #if SUPPORTS_APV baker.masks = masks; baker.masksSet = true; #endif } public static void SetSkyOcclusion(NativeArray skylightL1, NativeArray skylightDir) { #if SUPPORTS_APV bakerSky.skylightL1 = skylightL1; bakerSky.skylightDir = skylightDir; bakerSky.skyDataSet = true; #endif } public static void Finish() { #if SUPPORTS_APV baker.Finish(); bakerSky.Finish(); Cleanup(); #endif } public static void Cleanup() { #if SUPPORTS_APV AdaptiveProbeVolumes.SetLightingBakerOverride(null); AdaptiveProbeVolumes.SetSkyOcclusionBakerOverride(null); #endif } public static bool AnyAPVsInScene() { #if SUPPORTS_APV var anyAPVs = GameObject.FindObjectsOfType(); foreach(var apv in anyAPVs) { if (apv.enabled && apv.gameObject.activeInHierarchy) return true; } #endif return false; } } #endif #endif