static public void CreateInfluenceVolumes(Vector3Int cellPos, Renderer[] renderers, ProbeVolume[] probeVolumes, ProbeReferenceVolumeAuthoring settings, Matrix4x4 cellTrans, out List <Volume> culledVolumes, out Dictionary <Scene, int> sceneRefs) { Volume cellVolume = new Volume(); cellVolume.corner = new Vector3(cellPos.x * settings.cellSize, cellPos.y * settings.cellSize, cellPos.z * settings.cellSize); cellVolume.X = new Vector3(settings.cellSize, 0, 0); cellVolume.Y = new Vector3(0, settings.cellSize, 0); cellVolume.Z = new Vector3(0, 0, settings.cellSize); cellVolume.Transform(cellTrans); // Keep track of volumes and which scene they originated from sceneRefs = new Dictionary <Scene, int>(); // Extract all influencers inside the cell List <Volume> influenceVolumes = new List <Volume>(); RenderersToVolumes(ref renderers, ref cellVolume, ref influenceVolumes, ref sceneRefs); NavPathsToVolumes(ref cellVolume, ref influenceVolumes, ref sceneRefs); ImportanceVolumesToVolumes(ref cellVolume, ref influenceVolumes, ref sceneRefs); LightsToVolumes(ref cellVolume, ref influenceVolumes, ref sceneRefs); // Extract all ProbeVolumes inside the cell List <Volume> indicatorVolumes = new List <Volume>(); ProbeVolumesToVolumes(ref probeVolumes, ref cellVolume, ref indicatorVolumes, ref sceneRefs); // Cull all influencers against ProbeVolumes culledVolumes = new List <Volume>(); CullVolumes(ref influenceVolumes, ref indicatorVolumes, ref culledVolumes); }
public void OnSceneGUI() { ProbeReferenceVolumeAuthoring pvra = target as ProbeReferenceVolumeAuthoring; if (Event.current.type == EventType.Layout) { pvra.DrawProbeGizmos(); } }
private static void OnBakeStarted() { if (ShaderConfig.s_EnableProbeVolumes == 1) { bakingReferenceVolumeAuthoring = GetCardinalAuthoringComponent(); if (bakingReferenceVolumeAuthoring == null) { Debug.Log("Scene(s) have multiple inconsistent ProbeReferenceVolumeAuthoring components. Please ensure they use identical profiles and transforms before baking."); return; } RunPlacement(); } }
private static void OnAdditionalProbesBakeCompleted() { UnityEditor.Experimental.Lightmapping.additionalBakedProbesCompleted -= OnAdditionalProbesBakeCompleted; var numCells = bakingCells.Count; // Fetch results of all cells for (int c = 0; c < numCells; ++c) { var cell = bakingCells[c]; if (cell.probePositions == null) { continue; } int numProbes = cell.probePositions.Length; Debug.Assert(numProbes > 0); var sh = new NativeArray <SphericalHarmonicsL2>(numProbes, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var validity = new NativeArray <float>(numProbes, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var bakedProbeOctahedralDepth = new NativeArray <float>(numProbes * 64, Allocator.Temp, NativeArrayOptions.UninitializedMemory); UnityEditor.Experimental.Lightmapping.GetAdditionalBakedProbes(cell.index, sh, validity, bakedProbeOctahedralDepth); cell.sh = new SphericalHarmonicsL1[numProbes]; cell.validity = new float[numProbes]; for (int i = 0; i < numProbes; ++i) { Vector4[] channels = new Vector4[3]; // compare to SphericalHarmonicsL2::GetShaderConstantsFromNormalizedSH channels[0] = new Vector4(sh[i][0, 3], sh[i][0, 1], sh[i][0, 2], sh[i][0, 0]); channels[1] = new Vector4(sh[i][1, 3], sh[i][1, 1], sh[i][1, 2], sh[i][1, 0]); channels[2] = new Vector4(sh[i][2, 3], sh[i][2, 1], sh[i][2, 2], sh[i][2, 0]); // It can be shown that |L1_i| <= |2*L0| // Precomputed Global Illumination in Frostbite by Yuriy O'Donnell. // https://media.contentapi.ea.com/content/dam/eacom/frostbite/files/gdc2018-precomputedgiobalilluminationinfrostbite.pdf // // So divide by L0 brings us to [-2, 2], // divide by 4 brings us to [-0.5, 0.5], // and plus by 0.5 brings us to [0, 1]. for (int channel = 0; channel < 3; ++channel) { var l0 = channels[channel][3]; if (l0 != 0.0f) { for (int axis = 0; axis < 3; ++axis) { channels[channel][axis] = channels[channel][axis] / (l0 * 4.0f) + 0.5f; Debug.Assert(channels[channel][axis] >= 0.0f && channels[channel][axis] <= 1.0f); } } } SphericalHarmonicsL1 sh1 = new SphericalHarmonicsL1(); sh1.shAr = channels[0]; sh1.shAg = channels[1]; sh1.shAb = channels[2]; cell.sh[i] = sh1; cell.validity[i] = validity[i]; } // Reset index UnityEditor.Experimental.Lightmapping.SetAdditionalBakedProbes(cell.index, null); DilateInvalidProbes(cell.probePositions, cell.bricks, cell.sh, cell.validity, bakingReferenceVolumeAuthoring.GetDilationSettings()); ProbeReferenceVolume.instance.cells[cell.index] = cell; } // Map from each scene to an existing reference volume var scene2RefVol = new Dictionary <Scene, ProbeReferenceVolumeAuthoring>(); foreach (var refVol in GameObject.FindObjectsOfType <ProbeReferenceVolumeAuthoring>()) { if (refVol.enabled) { scene2RefVol[refVol.gameObject.scene] = refVol; } } // Map from each reference volume to its asset var refVol2Asset = new Dictionary <ProbeReferenceVolumeAuthoring, ProbeVolumeAsset>(); foreach (var refVol in scene2RefVol.Values) { refVol2Asset[refVol] = ProbeVolumeAsset.CreateAsset(refVol.gameObject.scene); } // Put cells into the respective assets foreach (var cell in ProbeReferenceVolume.instance.cells.Values) { foreach (var scene in cellIndex2SceneReferences[cell.index]) { // This scene has a reference volume authoring component in it? ProbeReferenceVolumeAuthoring refVol = null; if (scene2RefVol.TryGetValue(scene, out refVol)) { var asset = refVol2Asset[refVol]; asset.cells.Add(cell); } } } // Connect the assets to their components foreach (var pair in refVol2Asset) { var refVol = pair.Key; var asset = pair.Value; refVol.volumeAsset = asset; if (UnityEditor.Lightmapping.giWorkflowMode != UnityEditor.Lightmapping.GIWorkflowMode.Iterative) { UnityEditor.EditorUtility.SetDirty(refVol); UnityEditor.EditorUtility.SetDirty(refVol.volumeAsset); } } UnityEditor.AssetDatabase.SaveAssets(); UnityEditor.AssetDatabase.Refresh(); foreach (var refVol in refVol2Asset.Keys) { if (refVol.enabled && refVol.gameObject.activeSelf) { refVol.QueueAssetLoading(); } } }
public override void OnInspectorGUI() { if (ShaderConfig.s_EnableProbeVolumes == 0) { EditorGUILayout.HelpBox("Warning: Probe Volumes are not enabled.\nIt is an highly experimental feature and disabled by default for this reason.\n Its functionality is subject to breaking changes and whole sale removal.\nIt is not recommended for use outside of for providing feedback.\n" + "It should not be used in production.\nTo enable, set:\nEnableProbeVolumes = 1\ninside of ShaderConfig.cs\and inside of the editor run:" + "\nEdit->Render Pipeline->Generate Shader Includes\nProbe Volumes feature must also be enabled here.", MessageType.Warning, wide: true); return; } serializedObject.Update(); var probeReferenceVolumes = FindObjectsOfType <ProbeReferenceVolumeAuthoring>(); bool foundInconsistency = false; if (probeReferenceVolumes.Length > 1) { foreach (var o1 in probeReferenceVolumes) { foreach (var o2 in probeReferenceVolumes) { if (!o1.profile.IsEquivalent(o2.profile) && !foundInconsistency) { EditorGUILayout.HelpBox("Multiple Probe Reference Volume components are loaded, but they have different profiles. " + "This is unsupported, please make sure all loaded Probe Reference Volume have the same profile or profiles with equal values.", MessageType.Error, wide: true); foundInconsistency = true; } if (foundInconsistency) { break; } } } } EditorGUI.BeginChangeCheck(); // The layout system breaks alignment when mixing inspector fields with custom layout'd // fields, do the layout manually instead int buttonWidth = 60; float indentOffset = EditorGUI.indentLevel * 15f; var lineRect = EditorGUILayout.GetControlRect(); var labelRect = new Rect(lineRect.x, lineRect.y, EditorGUIUtility.labelWidth - indentOffset, lineRect.height); var fieldRect = new Rect(labelRect.xMax, lineRect.y, lineRect.width - labelRect.width - buttonWidth, lineRect.height); var buttonNewRect = new Rect(fieldRect.xMax, lineRect.y, buttonWidth, lineRect.height); GUIContent guiContent = EditorGUIUtility.TrTextContent("Profile", "A reference to a profile asset."); EditorGUI.PrefixLabel(labelRect, guiContent); using (var scope = new EditorGUI.ChangeCheckScope()) { EditorGUI.BeginProperty(fieldRect, GUIContent.none, m_Profile); m_Profile.objectReferenceValue = (ProbeReferenceVolumeProfile)EditorGUI.ObjectField(fieldRect, m_Profile.objectReferenceValue, typeof(ProbeReferenceVolumeProfile), false); EditorGUI.EndProperty(); } if (GUI.Button(buttonNewRect, EditorGUIUtility.TrTextContent("New", "Create a new profile."), EditorStyles.miniButton)) { // By default, try to put assets in a folder next to the currently active // scene file. If the user isn't a scene, put them in root instead. var targetName = actualTarget.name; var scene = actualTarget.gameObject.scene; var asset = ProbeReferenceVolumeAuthoring.CreateReferenceVolumeProfile(scene, targetName); m_Profile.objectReferenceValue = asset; } m_VolumeAsset.objectReferenceValue = EditorGUILayout.ObjectField(s_DataAssetLabel, m_VolumeAsset.objectReferenceValue, typeof(ProbeVolumeAsset), false); DebugVisualizationGroupEnabled = EditorGUILayout.BeginFoldoutHeaderGroup(DebugVisualizationGroupEnabled, "Debug Visualization"); if (DebugVisualizationGroupEnabled) { m_DrawCells.boolValue = EditorGUILayout.Toggle("Draw Cells", m_DrawCells.boolValue); m_DrawBricks.boolValue = EditorGUILayout.Toggle("Draw Bricks", m_DrawBricks.boolValue); m_DrawProbes.boolValue = EditorGUILayout.Toggle("Draw Probes", m_DrawProbes.boolValue); EditorGUI.BeginDisabledGroup(!m_DrawProbes.boolValue); m_ProbeShading.enumValueIndex = EditorGUILayout.Popup("Probe Shading Mode", m_ProbeShading.enumValueIndex, ProbeShadingModes); EditorGUI.BeginDisabledGroup(m_ProbeShading.enumValueIndex != 1); m_Exposure.floatValue = EditorGUILayout.FloatField("Probe exposure", m_Exposure.floatValue); EditorGUI.EndDisabledGroup(); EditorGUI.EndDisabledGroup(); m_CullingDistance.floatValue = EditorGUILayout.FloatField("Culling Distance", m_CullingDistance.floatValue); } EditorGUILayout.EndFoldoutHeaderGroup(); DilationGroupEnabled = EditorGUILayout.BeginFoldoutHeaderGroup(DilationGroupEnabled, "Dilation"); if (DilationGroupEnabled) { m_Dilate.boolValue = EditorGUILayout.Toggle("Dilate", m_Dilate.boolValue); EditorGUI.BeginDisabledGroup(!m_Dilate.boolValue); m_MaxDilationSamples.intValue = EditorGUILayout.IntField("Max Dilation Samples", m_MaxDilationSamples.intValue); m_MaxDilationSampleDistance.floatValue = EditorGUILayout.FloatField("Max Dilation Sample Distance", m_MaxDilationSampleDistance.floatValue); DilationValidityThresholdInverted = EditorGUILayout.Slider("Dilation Validity Threshold", DilationValidityThresholdInverted, 0f, 1f); m_GreedyDilation.boolValue = EditorGUILayout.Toggle("Greedy Dilation", m_GreedyDilation.boolValue); EditorGUI.EndDisabledGroup(); } EditorGUILayout.EndFoldoutHeaderGroup(); if (EditorGUI.EndChangeCheck()) { Constrain(); serializedObject.ApplyModifiedProperties(); } }