using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;

namespace URP
{
    /// <summary>
    /// ShadowMask烘培相关
    /// 相关HLSL： #include "Assets/URP/Shader/HLSL/ShaderLibrary/Shadow.hlsl"
    /// 
    /// 
    /// 
    /// 
    /// </summary>
    public class ShadowMask
    {
        public static readonly string MixedLightingShadowmask = "_MIXED_LIGHTING_SHADOWMASK";
        public static readonly string ShadowMaskKeyword = "SHADOWS_SHADOWMASK";

        public static int _LightShadowData = Shader.PropertyToID("_LightShadowData");
        public static int unity_ShadowFadeCenterAndType = Shader.PropertyToID("unity_ShadowFadeCenterAndType");

        //第一步：
        //在ForwardLights.InitializeLightConstants 末尾加入以下代码， ForwardLights.InitializeLightConstants 参数加入 CommandBuffer cmd = null
        /*
         //shadow mask
            if (light != null && light.bakingOutput.mixedLightingMode == MixedLightingMode.Shadowmask && light.bakingOutput.lightmapBakeType == LightmapBakeType.Mixed)
            {
                if (lightData.light.shadows != LightShadows.None)
                {
                    m_MixedLightingSetup = MixedLightingSetup.ShadowMask;
                }
                int channel = light.bakingOutput.occlusionMaskChannel;
                lightSpotDir.w = channel + 1;
            }

            //shadow mask
            var settings = UniversalRenderPipeline.asset;
            float dist = 0.01f;
            if (settings != null)
            {
                dist = Mathf.Clamp(settings.shadowDistance, 0.01f, float.MaxValue);
            }
            URP.ShadowMask.SetLightShadowData(cmd, light, dist);
        */

        //第二步：
        //在 UniversalRenderPipeline.SetSupportedRenderingFeatures中修改 mixedLightingModes ：
        /*
        mixedLightingModes = SupportedRenderingFeatures.LightmapMixedBakeModes.Subtractive | SupportedRenderingFeatures.LightmapMixedBakeModes.IndirectOnly | SupportedRenderingFeatures.LightmapMixedBakeModes.Shadowmask,

            //加入| PerObjectData.ShadowMask：
         static PerObjectData GetPerObjectLightFlags(int additionalLightsCount)
        {
            var configuration = PerObjectData.ReflectionProbes | PerObjectData.Lightmaps | PerObjectData.LightProbe | PerObjectData.LightData | PerObjectData.OcclusionProbe | PerObjectData.ShadowMask;
        
        }
             

        */

        public static void SetKeyword(CommandBuffer cmd, string keyword, bool state)
        {
            if (state)
                cmd.EnableShaderKeyword(keyword);
            else
                cmd.DisableShaderKeyword(keyword);
        }

        /// <summary>
        /// 第三步：
        /// 设置专用宏， 在 ForwardLights.Setup 中判断是否开启了 ShadowMask：  bool isSurportShadowmask = renderingData.lightData.supportsMixedLighting && m_MixedLightingSetup == MixedLightingSetup.ShadowMask;
        /// </summary>
        /// <param name="cmd"></param>
        /// <param name="isSurportShadowmask"></param>
        public static void SetupKeyword(CommandBuffer cmd, bool isSurportShadowmask, Camera camera)
        {
            //SetKeyword(cmd, "DIRLIGHTMAP_COMBINED", true);
            SetKeyword(cmd, MixedLightingShadowmask, isSurportShadowmask);
            SetKeyword(cmd, ShadowMaskKeyword, isSurportShadowmask);

            Shader.SetGlobalVector(unity_ShadowFadeCenterAndType, camera.transform.position);
        }

        /// <summary>
        /// 设置LightShadowData
        /// shadowDistance 从UniversalRenderPipeline.asset中获取
        /// </summary>
        /// <param name="cmd"></param>
        /// <param name="light"></param>
        /// <param name="shadowDistance"></param>
        public static void SetLightShadowData(CommandBuffer cmd, Light light, float shadowDistance = 0.01f)
        {
            if (cmd != null)
            {
                if (light.shadows != LightShadows.None)
                {
                    Vector4 _LightShadowData = Vector4.zero;
                    _LightShadowData.x = light.shadowStrength;

                    shadowDistance = Mathf.Clamp(shadowDistance, 0.01f, float.MaxValue);
                    _LightShadowData.y = shadowDistance;
                    _LightShadowData.z = 1 / shadowDistance;
                    _LightShadowData.w = light.shadowNearPlane;

                    cmd.SetGlobalVector(ShadowMask._LightShadowData, _LightShadowData);
                }
            }
        }
    }
}

