using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; using System; using UnityEngine.Experimental.Rendering; [Serializable, VolumeComponentMenu("Post-processing/Custom/Adaptation3")] public sealed class Adaptation3 : CustomPostProcessVolumeComponent, IPostProcessComponent { [Tooltip("Adaptation mode: Global - adapt to average scene light; Local - adapt to view; Dynamic - simulate adaptation speed.")] public Adaptation3ModeParameter mode = new Adaptation3ModeParameter(Adaptation3Mode.Local); [Tooltip("Light to dark adaptation speed (per second).")] public ClampedFloatParameter darkAdaptation = new ClampedFloatParameter(0.33f, 0f, 1f); [Tooltip("Dark to light adaptation speed (per second).")] public ClampedFloatParameter lightAdaptation = new ClampedFloatParameter(0.1f, 0f, 1f); [Tooltip("Maximum horizontal distance from center to consider value.")] public ClampedFloatParameter radiusX = new ClampedFloatParameter(0.8f, 0f, 1f); [Tooltip("Maximum vertical distance from center to consider value.")] public ClampedFloatParameter radiusY = new ClampedFloatParameter(0.8f, 0f, 1f); [Tooltip("Softness of weights.")] public ClampedFloatParameter radiusSoftness = new ClampedFloatParameter(0.5f, 0f, 10f); //[Tooltip("Threshold of scotopic/mesopic vision.")] //public FloatParameter darkThreshold = new FloatParameter(0.03f); //[Tooltip("Threshold of mesopic/photopic vision.")] //public FloatParameter lightThreshold = new FloatParameter(3f); [Tooltip("Maximum display luminance.")] public ClampedFloatParameter Ldisp = new ClampedFloatParameter(0f, 0f, 1000f); [Tooltip("Simulate colour sensitivity.")] public BoolParameter colour = new BoolParameter(true); [Tooltip("Clip values darker than limit.")] public FloatParameter clip = new FloatParameter(0f); public FloatParameter multiplier = new FloatParameter(1f); public FloatParameter average = new FloatParameter(1f); public enum Adaptation3Mode { Global = 0, Local = 1, Dynamic = 2 } [Serializable] public sealed class Adaptation3ModeParameter : VolumeParameter { public Adaptation3ModeParameter(Adaptation3Mode value, bool overrideState = false) : base(value, overrideState) { } } Material m_Material; ComputeShader m_Compute; LocalKeyword m_Colour; RTHandle m_Temp1024, m_Temp32, m_Params; RTHandle[] m_Adapt; int m_AdaptCount = 0; bool m_Ready = false; bool m_Active = false; public bool IsActive() => m_Ready && m_Active && Ldisp.value > 0.0f; // Do not forget to add this post process in the Custom Post Process Orders list (Project Settings > Graphics > HDRP Settings). // https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@15.0/manual/images/HDRP-frame-graph-diagram.png public override CustomPostProcessInjectionPoint injectionPoint => CustomPostProcessInjectionPoint.BeforeTAA; const string kShaderName = "Hidden/Shader/Adaptation3"; const string kComputeName = "Adaptation3"; public override void Setup() { var shader = Shader.Find(kShaderName); if (shader != null) m_Material = new Material(shader); else Debug.LogError($"Unable to find shader '{kShaderName}'. Post Process Volume Adaptation3 is unable to load."); m_Colour = shader.keywordSpace.FindKeyword("COLOUR_SPACE"); m_Compute = Resources.Load(kComputeName); if (m_Compute == null) Debug.LogError($"Unable to find compute shader '{kComputeName}'. Post Process Volume Adaptation3 is unable to load."); m_Temp1024 = RTHandles.Alloc( 1024, 1024, colorFormat: GraphicsFormat.R32G32_SFloat, enableRandomWrite: true, name: "Average Luminance Temp 1024" ); m_Temp32 = RTHandles.Alloc( 32, 32, colorFormat: GraphicsFormat.R32G32_SFloat, enableRandomWrite: true, name: "Average Luminance Temp 32" ); m_Params = RTHandles.Alloc( 1, 1, colorFormat: GraphicsFormat.R32G32_SFloat, enableRandomWrite: true, name: "Adaptation parameters texture" ); var adapt1 = RTHandles.Alloc( 1, 1, colorFormat: GraphicsFormat.R32_SFloat, enableRandomWrite: true, name: "Adaptation texture 1" ); var adapt2 = RTHandles.Alloc( 1, 1, colorFormat: GraphicsFormat.R32_SFloat, enableRandomWrite: true, name: "Adaptation texture 2" ); if (m_Temp1024 == null || m_Temp32 == null || m_Params == null || adapt1 == null || adapt2 == null) Debug.LogError("Unable to allocate temporary buffers for Adaptation3."); m_Adapt = new RTHandle[] { adapt1, adapt2 }; m_Ready = true; } protected override void OnEnable() { base.OnEnable(); m_Active = true; } protected override void OnDisable() { m_Active = false; base.OnDisable(); } public override void Render(CommandBuffer cmd, HDCamera camera, RTHandle source, RTHandle destination) { if (!m_Ready) return; var cs = m_Compute; cmd.BeginSample("Adaptation3"); var cur = m_Adapt[++m_AdaptCount % 2]; var prev = m_Adapt[++m_AdaptCount % 2]; m_AdaptCount = ++m_AdaptCount % 2; //Debug.Log($"Current frame {m_AdaptCount}"); int pass = 3; if (mode.value != Adaptation3Mode.Global) { // compute: source -> 1024 buffer cmd.SetComputeTextureParam(cs, pass, "_Source", source); // TODO cmd.Set...(cs, "_Weights", ...); cmd.SetComputeTextureParam(cs, pass, "_Output", m_Temp1024); cmd.DispatchCompute(cs, pass, 1024 / 8, 1024 / 8, 1); // compute: 1024 -> 32 buffer pass = 4; cmd.SetComputeTextureParam(cs, pass, "_Input", m_Temp1024); cmd.SetComputeTextureParam(cs, pass, "_Output", m_Temp32); cmd.DispatchCompute(cs, pass, 32, 32, 1); } // compute 2nd pass: 32 -> params pass = (int) mode.value; cmd.SetComputeVectorParam(cs, "_Params", new Vector4(multiplier.value, average.value, Ldisp.value, radiusSoftness.value)); cmd.SetComputeVectorParam(cs, "_Params2", new Vector4(darkAdaptation.value, lightAdaptation.value, radiusX.value, radiusY.value)); cmd.SetComputeTextureParam(cs, pass, "_Input", m_Temp32); cmd.SetComputeTextureParam(cs, pass, "_Previous", prev); cmd.SetComputeTextureParam(cs, pass, "_Current", cur); cmd.SetComputeTextureParam(cs, pass, "_Output", m_Params); cmd.DispatchCompute(cs, pass, 1, 1, 1); // apply display shader if (colour.value) m_Material.EnableKeyword("COLOUR_PROCESSING"); else m_Material.DisableKeyword("COLOUR_PROCESSING"); if (clip.value > 0f) m_Material.EnableKeyword("CLIP_DEBUG"); else m_Material.DisableKeyword("CLIP_DEBUG"); m_Material.SetTexture("_Adapt", m_Params); m_Material.SetFloat("_Mult", multiplier.value); m_Material.SetFloat("_Clip", clip.value); // DO NOT USE IN VR: cmd.Blit(source, destination, m_Material, 0); m_Material.SetTexture("_MainTex", source); HDUtils.DrawFullScreen(cmd, m_Material, destination); cmd.EndSample("Adaptation3"); } public override void Cleanup() { CoreUtils.Destroy(m_Material); } }