﻿using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
using System;

using GraphicsFormat = UnityEngine.Experimental.Rendering.GraphicsFormat;

[Serializable, VolumeComponentMenu("Post-processing/Snapshot Pro (HDRP)/LightStreaks")]
public sealed class LightStreaks : CustomPostProcessVolumeComponent, IPostProcessComponent
{
    [Tooltip("Blur Strength.")]
    public ClampedIntParameter strength = new ClampedIntParameter(250, 1, 500);

    [Tooltip("Luminance Threshold - pixels above this luminance will glow.")]
    public ClampedFloatParameter luminanceThreshold = new ClampedFloatParameter(10.0f, 0.0f, 50.0f);

    Material m_Material;
    RTHandle tmp;

    public bool IsActive() => m_Material != null && strength.value > 1;

    // Remember to add this post process in the Custom Post Process Orders list 
    // (Project Settings > HDRP Default Settings).
    public override CustomPostProcessInjectionPoint injectionPoint => 
        CustomPostProcessInjectionPoint.BeforePostProcess;

    const string kShaderName = "SnapshotProHDRP/LightStreaks";

    public override void Setup()
    {
        if (Shader.Find(kShaderName) != null)
        {
            m_Material = new Material(Shader.Find(kShaderName));
        }
        else
        {
            Debug.LogError($"Unable to find shader '{kShaderName}' for the LightStreaks effect.");
        }
    }

    public override void Render(CommandBuffer cmd, HDCamera camera, RTHandle source, RTHandle destination)
    {
        if (m_Material == null)
        {
            return;
        }

        if(tmp == null)
        {
            const GraphicsFormat RTFormat = GraphicsFormat.R16G16B16A16_SFloat;
            tmp = RTHandles.Alloc(source.rt.width / 4, source.rt.height / 4, colorFormat: RTFormat);
        }

        m_Material.SetInt("_KernelSize", strength.value);
        m_Material.SetFloat("_Spread", strength.value / 7.5f);
        m_Material.SetFloat("_LuminanceThreshold", luminanceThreshold.value);

        m_Material.SetTexture("_InputTexture", source);

        HDUtils.DrawFullScreen(cmd, m_Material, tmp, shaderPassId: 0);

        m_Material.SetTexture("_OverlayTexture", tmp);

        HDUtils.DrawFullScreen(cmd, m_Material, destination, shaderPassId: 1);
    }

    public override void Cleanup()
    {
        CoreUtils.Destroy(m_Material);
        RTHandles.Release(tmp);
    }
}
