using System; namespace UnityEngine.PostProcessing { public sealed class EyeAdaptationComponent : PostProcessingComponentRenderTexture { public override bool active { get { return base.model.enabled && SystemInfo.supportsComputeShaders && !this.context.interrupted; } } public void ResetHistory() { this.m_FirstFrame = true; } public override void OnEnable() { this.m_FirstFrame = true; } public override void OnDisable() { foreach (RenderTexture obj in this.m_AutoExposurePool) { GraphicsUtils.Destroy(obj); } if (this.m_HistogramBuffer != null) { this.m_HistogramBuffer.Release(); } this.m_HistogramBuffer = null; if (this.m_DebugHistogram != null) { this.m_DebugHistogram.Release(); } this.m_DebugHistogram = null; } private Vector4 GetHistogramScaleOffsetRes() { EyeAdaptationModel.Settings settings = base.model.settings; float num = (float)(settings.logMax - settings.logMin); float num2 = 1f / num; float y = (float)(-(float)settings.logMin) * num2; return new Vector4(num2, y, Mathf.Floor((float)this.context.width / 2f), Mathf.Floor((float)this.context.height / 2f)); } public Texture Prepare(RenderTexture source, Material uberMaterial) { EyeAdaptationModel.Settings settings = base.model.settings; if (this.m_EyeCompute == null) { this.m_EyeCompute = Resources.Load("Shaders/EyeHistogram"); } Material material = this.context.materialFactory.Get("Hidden/Post FX/Eye Adaptation"); material.shaderKeywords = null; if (this.m_HistogramBuffer == null) { this.m_HistogramBuffer = new ComputeBuffer(64, 4); } if (EyeAdaptationComponent.s_EmptyHistogramBuffer == null) { EyeAdaptationComponent.s_EmptyHistogramBuffer = new uint[64]; } Vector4 histogramScaleOffsetRes = this.GetHistogramScaleOffsetRes(); RenderTexture renderTexture = this.context.renderTextureFactory.Get((int)histogramScaleOffsetRes.z, (int)histogramScaleOffsetRes.w, 0, source.format, RenderTextureReadWrite.Default, FilterMode.Bilinear, TextureWrapMode.Clamp, "FactoryTempTexture"); Graphics.Blit(source, renderTexture); if (this.m_AutoExposurePool[0] == null || !this.m_AutoExposurePool[0].IsCreated()) { this.m_AutoExposurePool[0] = new RenderTexture(1, 1, 0, RenderTextureFormat.RFloat); } if (this.m_AutoExposurePool[1] == null || !this.m_AutoExposurePool[1].IsCreated()) { this.m_AutoExposurePool[1] = new RenderTexture(1, 1, 0, RenderTextureFormat.RFloat); } this.m_HistogramBuffer.SetData(EyeAdaptationComponent.s_EmptyHistogramBuffer); int kernelIndex = this.m_EyeCompute.FindKernel("KEyeHistogram"); this.m_EyeCompute.SetBuffer(kernelIndex, "_Histogram", this.m_HistogramBuffer); this.m_EyeCompute.SetTexture(kernelIndex, "_Source", renderTexture); this.m_EyeCompute.SetVector("_ScaleOffsetRes", histogramScaleOffsetRes); this.m_EyeCompute.Dispatch(kernelIndex, Mathf.CeilToInt((float)renderTexture.width / 16f), Mathf.CeilToInt((float)renderTexture.height / 16f), 1); this.context.renderTextureFactory.Release(renderTexture); settings.highPercent = Mathf.Clamp(settings.highPercent, 1.01f, 99f); settings.lowPercent = Mathf.Clamp(settings.lowPercent, 1f, settings.highPercent - 0.01f); material.SetBuffer("_Histogram", this.m_HistogramBuffer); material.SetVector(EyeAdaptationComponent.Uniforms._Params, new Vector4(settings.lowPercent * 0.01f, settings.highPercent * 0.01f, Mathf.Exp(settings.minLuminance * 0.6931472f), Mathf.Exp(settings.maxLuminance * 0.6931472f))); material.SetVector(EyeAdaptationComponent.Uniforms._Speed, new Vector2(settings.speedDown, settings.speedUp)); material.SetVector(EyeAdaptationComponent.Uniforms._ScaleOffsetRes, histogramScaleOffsetRes); material.SetFloat(EyeAdaptationComponent.Uniforms._ExposureCompensation, settings.keyValue); if (settings.dynamicKeyValue) { material.EnableKeyword("AUTO_KEY_VALUE"); } if (this.m_FirstFrame || !Application.isPlaying) { this.m_CurrentAutoExposure = this.m_AutoExposurePool[0]; Graphics.Blit(null, this.m_CurrentAutoExposure, material, 1); Graphics.Blit(this.m_AutoExposurePool[0], this.m_AutoExposurePool[1]); } else { int num = this.m_AutoExposurePingPing; RenderTexture source2 = this.m_AutoExposurePool[++num % 2]; RenderTexture renderTexture2 = this.m_AutoExposurePool[++num % 2]; Graphics.Blit(source2, renderTexture2, material, (int)settings.adaptationType); this.m_AutoExposurePingPing = (num + 1) % 2; this.m_CurrentAutoExposure = renderTexture2; } if (this.context.profile.debugViews.IsModeActive(BuiltinDebugViewsModel.Mode.EyeAdaptation)) { if (this.m_DebugHistogram == null || !this.m_DebugHistogram.IsCreated()) { this.m_DebugHistogram = new RenderTexture(256, 128, 0, RenderTextureFormat.ARGB32) { filterMode = FilterMode.Point, wrapMode = TextureWrapMode.Clamp }; } material.SetFloat(EyeAdaptationComponent.Uniforms._DebugWidth, (float)this.m_DebugHistogram.width); Graphics.Blit(null, this.m_DebugHistogram, material, 2); } this.m_FirstFrame = false; return this.m_CurrentAutoExposure; } public void OnGUI() { if (this.m_DebugHistogram == null || !this.m_DebugHistogram.IsCreated()) { return; } Rect position = new Rect(this.context.viewport.x * (float)Screen.width + 8f, 8f, (float)this.m_DebugHistogram.width, (float)this.m_DebugHistogram.height); GUI.DrawTexture(position, this.m_DebugHistogram); } private ComputeShader m_EyeCompute; private ComputeBuffer m_HistogramBuffer; private readonly RenderTexture[] m_AutoExposurePool = new RenderTexture[2]; private int m_AutoExposurePingPing; private RenderTexture m_CurrentAutoExposure; private RenderTexture m_DebugHistogram; private static uint[] s_EmptyHistogramBuffer; private bool m_FirstFrame = true; private const int k_HistogramBins = 64; private const int k_HistogramThreadX = 16; private const int k_HistogramThreadY = 16; private static class Uniforms { internal static readonly int _Params = Shader.PropertyToID("_Params"); internal static readonly int _Speed = Shader.PropertyToID("_Speed"); internal static readonly int _ScaleOffsetRes = Shader.PropertyToID("_ScaleOffsetRes"); internal static readonly int _ExposureCompensation = Shader.PropertyToID("_ExposureCompensation"); internal static readonly int _AutoExposure = Shader.PropertyToID("_AutoExposure"); internal static readonly int _DebugWidth = Shader.PropertyToID("_DebugWidth"); } } }