using HTraceWSGI.Scripts.Globals; using HTraceWSGI.Scripts.Infrastructure; using HTraceWSGI.Scripts.Passes; using HTraceWSGI.Scripts.PassHandlers; using HTraceWSGI.Scripts.Pipeline; using HTraceWSGI.Scripts.Structs; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; #if UNITY_EDITOR using HTraceWSGI.Scripts.PipelinesConfigurator; using HTraceWSGI.Scripts.Patcher; using UnityEditor; #endif namespace HTraceWSGI.Scripts { [ExecuteInEditMode, DefaultExecutionOrder(100)] public class HTraceWSGI : MonoBehaviour, IPing { private GlobalIllumination _giOverrideComponent; private ScreenSpaceAmbientOcclusion _ambientOcclusionComponent; private Volume _volumeComponent; private PassService _passService; private CustomPassObject _prePassObject; private CustomPassObject _voxelObject; private CustomPassObject _mainPassObject; private CustomPassObject _finalPassObject; private VoxelsHandler _voxelsHandler; internal VoxelsHandler VoxelsHandler => _voxelsHandler; public GeneralData GeneralData = new GeneralData(); public VoxelizationData VoxelizationData = new VoxelizationData(); public ScreenSpaceLightingData ScreenSpaceLightingData = new ScreenSpaceLightingData(); [SerializeField] private DebugData DebugData = new DebugData(); [SerializeField] private bool _globalSettingsTab = true; [SerializeField] private bool _screenSpaceLightingTab = true; [SerializeField] private bool _wsgiTab = true; [SerializeField] private bool _debugTab = true; [SerializeField] private bool _showVoxelParams = true; [SerializeField] private bool _showUpdateOptions = true; private Light _prevDirLight; internal HDAdditionalLightData _additionalLightData; public bool Ping(CustomPassObject customPassObject) { return _passService.CustomPassObjectContains(customPassObject); } /// /// Forced scene voxelization /// public void VoxelizeNow() { VoxelizationRuntimeData.FullVoxelization = true; } private void OnEnable() { HResources.GeneralData = GeneralData; HResources.VoxelizationData = VoxelizationData; HResources.ScreenSpaceLightingData = ScreenSpaceLightingData; HResources.DebugData = DebugData; VoxelizationRuntimeData.FullVoxelization = true; VoxelizationRuntimeData.VoxelizationModeChanged = true; HExtensions.FillAttributeDictionary(); #if UNITY_EDITOR // Pipeleins feature will add after time //HRenderPipeline hRenderPipeline = HRenderer.CurrentHRenderPipeline; HPipelinesConfigurator.AlwaysIncludedShaders(); HPatcher.RenderPipelineRuntimeResourcesPatch(true); #endif InitComponents(); if (HExtensions.PipelineSupportsSSGI) Shader.EnableKeyword(HTraceNames.KEYWORD_SWITCHER); } private void InitComponents() { _passService = new PassService(this); _prePassObject = _passService.GetOrCreateCustomPassObject(CustomPassInjectionPoint.AfterOpaqueDepthAndNormal, passName: HTraceNames.HTRACE_PRE_PASS_NAME, priority: 10, layer: gameObject.layer, typeof(HTracePrePass)); _mainPassObject = _passService.GetOrCreateCustomPassObject(CustomPassInjectionPoint.AfterOpaqueDepthAndNormal, passName: HTraceNames.HTRACE_MAIN_PASS_NAME, priority: -20, layer: gameObject.layer, typeof(HTraceMainPass)); _finalPassObject = _passService.GetOrCreateCustomPassObject(CustomPassInjectionPoint.BeforePostProcess, passName: HTraceNames.HTRACE_FINAL_PASS_NAME, priority: -30, layer: gameObject.layer, typeof(HTraceFinalPass)); _voxelObject = _passService.GetOrCreateCustomPassObject(CustomPassInjectionPoint.AfterOpaqueDepthAndNormal, passName: HTraceNames.HTRACE_VOXEL_PASS_NAME, priority: -10, layer: gameObject.layer, typeof(VoxelizationPassConstant), typeof(VoxelizationPassPartial)); SetupVolume(); ((VoxelsHandler)_voxelObject.Handler).Initialize(_voxelObject.CustomPass); _voxelsHandler = (VoxelsHandler)_voxelObject.Handler; } private void Update() { // Hides SSGI volume when HTrace is added through "Add Component" if (_volumeComponent != null) _volumeComponent.hideFlags = HResources.DebugData.ShowBowels ? HideFlags.None : HideFlags.HideInInspector; #if UNITY_EDITOR if (HExtensions.PipelineSupportsSSGI == true) Shader.EnableKeyword(HTraceNames.KEYWORD_SWITCHER); else Shader.DisableKeyword(HTraceNames.KEYWORD_SWITCHER); if (gameObject.name != HTraceNames.HTRACE_NAME) gameObject.name = HTraceNames.HTRACE_NAME; #endif if (_prevDirLight != VoxelizationData.DirectionalLight) { _prevDirLight = VoxelizationData.DirectionalLight; _additionalLightData = VoxelizationData.DirectionalLight != null ? VoxelizationData.DirectionalLight.gameObject.GetComponent() : null; } VoxelizationRuntimeData.EvaluateHitLighting = ScreenSpaceLightingData.EvaluateHitLighting && HExtensions.PipelineSupportsScreenSpaceShadows && _additionalLightData != null && _additionalLightData.useScreenSpaceShadows == true; //_mainPassObject.CustomPassVolume.injectionPoint = (CustomPassInjectionPoint)DebugData.HInjectionPoint; } internal bool NeedToReallocForUI { get { if (_voxelObject == null || _voxelsHandler == null) return false; return _voxelsHandler.NeedToReallocForUI; } } internal void OnSceneGUI() { #if UNITY_EDITOR _voxelsHandler.OnSceneGUI(); #endif } private void OnDisable() { ((VoxelsHandler)_voxelObject.Handler).Release(); //((HTracePrePass)_prePassObject.CustomPass[0]).Release(); ((HTraceMainPass)_mainPassObject.CustomPass[0]).Release(); //((HTraceFinalPass)_finalPassObject.CustomPass[0]).Release(); _passService.Cleanup(); _passService = null; _volumeComponent.enabled = false; _giOverrideComponent = null; _ambientOcclusionComponent = null; VoxelizationRuntimeData.OnReallocTextures = null; Shader.DisableKeyword(HTraceNames.KEYWORD_SWITCHER); } #region SSGI override component ------------------------------------------------------------------------------------------------------ private void SetupVolume() { CreateSSGIOverrideComponent(); SetSSGIOverrideComponentSettings(); ChangeObjectWithSerialization(); } private void CreateSSGIOverrideComponent() { _volumeComponent = gameObject.GetComponent(); if (_volumeComponent == null) { _volumeComponent = gameObject.AddComponent(); } _volumeComponent.hideFlags = HResources.DebugData.ShowBowels ? HideFlags.None : HideFlags.HideInInspector; if (_volumeComponent.enabled == false) _volumeComponent.enabled = true; if (_volumeComponent.profile == null || _volumeComponent.profile.name.Contains("HTrace") == false) { //We can't crate it in runtime, because after build it will break. //it will call only in editor, but if someone changes it in runtime, we will override. _volumeComponent.profile = Resources.Load("HTRaceWSGI/Volume Profile HTrace"); } _volumeComponent.profile.TryGet(out _giOverrideComponent); } private void SetSSGIOverrideComponentSettings() { _volumeComponent.weight = 1; _volumeComponent.priority = 100; #if UNITY_EDITOR _volumeComponent.runInEditMode = true; #endif _giOverrideComponent.enable.overrideState = true; _giOverrideComponent.enable.value = true; _giOverrideComponent.tracing.overrideState = true; //_giOverrideComponent.tracing.value = RayCastingMode.RayMarching; //_giOverrideComponent.quality.value = (int) ScalableSettingLevelParameter.Level.High; _giOverrideComponent.quality.overrideState = true; _giOverrideComponent.quality.levelAndOverride = ((int)ScalableSettingLevelParameter.Level.Low, true); } private void ChangeObjectWithSerialization() { #if UNITY_EDITOR //Global illumination SerializedObject giVolumeSerializedObject = new SerializedObject(_giOverrideComponent); var m_MaxRaySteps = giVolumeSerializedObject.FindProperty("m_MaxRaySteps"); var m_OverrideState_m_MaxRaySteps = m_MaxRaySteps.FindPropertyRelative("m_OverrideState"); var m_Value_m_MaxRaySteps = m_MaxRaySteps.FindPropertyRelative("m_Value"); m_OverrideState_m_MaxRaySteps.boolValue = true; m_Value_m_MaxRaySteps.intValue = 0; // _giOverrideComponent.maxRaySteps = 0; var m_Denoise = giVolumeSerializedObject.FindProperty("m_Denoise"); var m_OverrideState_m_Denoise = m_Denoise.FindPropertyRelative("m_OverrideState"); var m_Value_m_Denoise = m_Denoise.FindPropertyRelative("m_Value"); m_OverrideState_m_Denoise.boolValue = true; m_Value_m_Denoise.boolValue = false; // _giOverrideComponent.denoise = false; var m_DenoiseSS = giVolumeSerializedObject.FindProperty("m_DenoiseSS"); var m_OverrideState_m_DenoiseSS = m_DenoiseSS.FindPropertyRelative("m_OverrideState"); var m_Value_m_DenoiseSS = m_DenoiseSS.FindPropertyRelative("m_Value"); m_OverrideState_m_DenoiseSS.boolValue = true; m_Value_m_DenoiseSS.boolValue = false; // _giOverrideComponent.denoiseSS = false; var m_FullResolution = giVolumeSerializedObject.FindProperty("m_FullResolution"); var m_OverrideState_m_FullResolution = m_FullResolution.FindPropertyRelative("m_OverrideState"); var m_Value_m_FullResolution = m_FullResolution.FindPropertyRelative("m_Value"); m_OverrideState_m_FullResolution.boolValue = true; m_Value_m_FullResolution.boolValue = true; // _giOverrideComponent.fullResolution = false; var fullResolutionSS = giVolumeSerializedObject.FindProperty("fullResolutionSS"); var m_OverrideState_fullResolutionSS = fullResolutionSS.FindPropertyRelative("m_OverrideState"); var m_Value_fullResolutionSS = fullResolutionSS.FindPropertyRelative("m_Value"); m_OverrideState_fullResolutionSS.boolValue = true; m_Value_fullResolutionSS.boolValue = true; // _giOverrideComponent.fullResolutionSS = false; var rayMiss = giVolumeSerializedObject.FindProperty("rayMiss"); var m_OverrideState_fallbackHierarchy = rayMiss.FindPropertyRelative("m_OverrideState"); var m_Value_fallbackHierarchy = rayMiss.FindPropertyRelative("m_Value"); m_OverrideState_fallbackHierarchy.boolValue = true; m_Value_fallbackHierarchy.enumValueIndex = (int)RayMarchingFallbackHierarchy.None; // _giOverrideComponent.rayMiss.value = RayMarchingFallbackHierarchy.None; giVolumeSerializedObject.ApplyModifiedProperties(); //Ambient Occlusion // SerializedObject aoVolumeSerializedObject = new SerializedObject(_ambientOcclusionComponent); // var intensity = aoVolumeSerializedObject.FindProperty("intensity"); // var m_OverrideState_intensity = intensity.FindPropertyRelative("m_OverrideState"); // var m_Value_intensity = intensity.FindPropertyRelative("m_Value"); // m_OverrideState_intensity.boolValue = true; // m_Value_intensity.floatValue = 0f; // // aoVolumeSerializedObject.ApplyModifiedProperties(); #endif } #endregion SSGI override component ------------------------------------------------------------------------------------------------------ #region UTILITIES -------------------------------------------------------------------------------------------------------------------------- #if UNITY_EDITOR private void OnTransformChildrenChanged() { foreach (Transform child in this.transform) { if (child.name == HTraceNames.HTRACE_PRE_PASS_NAME || child.name == HTraceNames.HTRACE_MAIN_PASS_NAME || child.name == HTraceNames.HTRACE_FINAL_PASS_NAME || child.name == HTraceNames.HTRACE_VOXEL_PASS_NAME || child.name == HTraceNames.HTRACE_VOXEL_CAMERA_NAME) continue; child.parent = null; Debug.Log($"Cann't add a \"{child.name}\" gameobject to HTraceWSGI."); } } #endif #endregion UTILITIES -------------------------------------------------------------------------------------------------------------------------- } }