using System; using System.Collections; using DDD.Utility; using Sirenix.OdinInspector; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; public enum RendererFeatureName { None = 0, GrayscaleRenderPassFeature } public enum VolumeType { None = 0, Global, Player } public class PostProcessingManager : Singleton { [SerializeField] private Volume _globalVolume; [SerializeField] private Volume _playerVolume; [SerializeField] private UniversalRenderPipelineAsset _currentRenderPipeline; [SerializeField] private ScriptableRendererData _currentRenderData; private Coroutine _lowHpVignetteCoroutine; // LowHpVignette [Title("LowHpVignette")] [SerializeField] private bool _isLerpIntensity = true; [SerializeField] private float _startIntensity = 0.15f; [SerializeField, ShowIf("@_isLerpIntensity")] private float _endIntensity = 0.2f; [SerializeField, ShowIf("@_isLerpIntensity")] private float _lerpTime = 1f; protected override void OnAwake() { InitializeComponents(); } protected override void OnApplicationQuit() { ToggleRendererFeature(RendererFeatureName.GrayscaleRenderPassFeature, false); } [Button("컴포넌트 초기화")] private void InitializeComponents() { _currentRenderPipeline = (UniversalRenderPipelineAsset)GraphicsSettings.currentRenderPipeline; _currentRenderData = _currentRenderPipeline.rendererDataList[0]; _globalVolume = GetComponent(); _playerVolume = transform.Find("PlayerVolume").GetComponent(); } public void ToggleRendererFeature(RendererFeatureName featureName, bool value) { foreach (var element in _currentRenderData.rendererFeatures) { if (!string.Equals(element.name, featureName.ToString())) continue; element.SetActive(value); return; } Debug.Log($"{featureName}과 일치하는 기능이 없습니다."); } public void ToggleEffect(bool value, VolumeType volumeType) where T : VolumeComponent { Volume currentVolume = null; switch (volumeType) { case VolumeType.None: break; case VolumeType.Global: currentVolume = _globalVolume; break; case VolumeType.Player: currentVolume = _playerVolume; break; default: throw new ArgumentOutOfRangeException(nameof(volumeType), volumeType, null); } if (!currentVolume) { Debug.LogError($"VolumeType : {volumeType}의 {currentVolume}이 존재하지 않습니다."); return; } var effect = GetEffect(volumeType); if (!effect) { print(typeof(T) + "효과가 없습니다."); return; } effect.active = value; } private T GetEffect(VolumeType volumeType) where T : VolumeComponent { Volume currentVolume = null; switch (volumeType) { case VolumeType.None: break; case VolumeType.Global: currentVolume = _globalVolume; break; case VolumeType.Player: currentVolume = _playerVolume; break; default: throw new ArgumentOutOfRangeException(nameof(volumeType), volumeType, null); } if (!currentVolume) { Debug.LogError($"VolumeType : {volumeType}의 {currentVolume}이 존재하지 않습니다."); return null; } currentVolume.profile.TryGet(out T effect); return effect; } public void LowHpVignette() { Utils.StartUniqueCoroutine(this, ref _lowHpVignetteCoroutine, LowHpVignetteCoroutine()); } public void DefaultHpVignette() { Utils.EndUniqueCoroutine(this, ref _lowHpVignetteCoroutine); ToggleEffect(false, VolumeType.Player); } private IEnumerator LowHpVignetteCoroutine() { var vignette = GetEffect(VolumeType.Player); vignette.intensity.value = _startIntensity; vignette.active = true; if (!_isLerpIntensity) yield break; var elapsedTime = 0f; var addTime = Time.deltaTime; while (true) { vignette.intensity.value = Mathf.Lerp(_startIntensity, _endIntensity, elapsedTime / _lerpTime); if (elapsedTime > _lerpTime) { addTime = -Time.deltaTime; } else if (elapsedTime < 0) { addTime = Time.deltaTime; } elapsedTime += addTime; yield return null; } } public void DepthOfFieldButton(bool active) => ToggleEffect(active, VolumeType.Global); }