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

namespace URP
{
    /// <summary>
    /// 设置我们扩展的shader全局变量
    /// 相关HLSL： #include "Assets/URP/Shader/HLSL/ShaderLibrary/Defines.hlsl"
    /// </summary>
    public class ShaderGlobalValues
    {

        public static float ms_Matrix_P_FOV = float.MaxValue;
        public static float ms_sceneBloomFactor = 1;
        public static float ms_roleBloomFactor = 1;
        public static float ms_skyBloomFactor = 1;

        //环境光：
        public static int glstate_lightmodel_ambient = Shader.PropertyToID("glstate_lightmodel_ambient");
        public static int unity_Ambient = Shader.PropertyToID("unity_Ambient");
        public static int unity_AmbientSky = Shader.PropertyToID("unity_AmbientSky");
        public static int unity_AmbientEquator = Shader.PropertyToID("unity_AmbientEquator");
        public static int unity_AmbientGround = Shader.PropertyToID("unity_AmbientGround");

        public static int _Matrix_Perspective = Shader.PropertyToID("_Matrix_P");
        public static int _Matrix_shadow_Perspective = Shader.PropertyToID("_Matrix_Shodw_P");

        public static readonly int _SceneBloomFactor = Shader.PropertyToID("_SceneBloomFactor");
        public static readonly int _RoleBloomFactor = Shader.PropertyToID("_RoleBloomFactor");
        public static readonly int _SkyBloomFactor = Shader.PropertyToID("_SkyBloomFactor");

        public static void ResetBloomFactor()
        {
            ms_sceneBloomFactor = 1;
            ms_roleBloomFactor = 1;
            ms_skyBloomFactor = 1;
        }

        public static void SetShadowValues(CommandBuffer cmd, float w, float h)
        {
            float fov = ms_Matrix_P_FOV;
            if (ms_Matrix_P_FOV != float.MaxValue)
            {
                fov = Mathf.Clamp(ms_Matrix_P_FOV, 0.01f, 179.0f);
            }

            if (ms_Matrix_P_FOV < 0.01)
            {
                fov = float.MaxValue;
            }

            var p = Matrix4x4.Perspective(fov, w / h, 0.01f, 1000);
            //p = GL.GetGPUProjectionMatrix(p, false);
            if (cmd == null)
            {
                Shader.SetGlobalMatrix(_Matrix_shadow_Perspective, p);
            }
            else
            {
                cmd.SetGlobalMatrix(_Matrix_shadow_Perspective, p);
            }
        }

        public static void SetValues(CommandBuffer cmd, Camera camera = null)
        {
            if (camera)
            {
                //float fov = 2f * Mathf.Rad2Deg * Mathf.Atan2(camera.orthographicSize, Mathf.Abs(camera.transform.position.z));

                float fov = ms_Matrix_P_FOV;
                if (ms_Matrix_P_FOV != float.MaxValue)
                {
                    fov = Mathf.Clamp(ms_Matrix_P_FOV, 0.01f, 179.0f);
                }

                if (ms_Matrix_P_FOV < 0.01)
                {
                    fov = float.MaxValue;
                }

                bool setFov = fov != float.MaxValue && camera.cameraType == CameraType.Game;
                var p = setFov ? Matrix4x4.Perspective(fov, camera.aspect, camera.nearClipPlane, camera.farClipPlane) : camera.projectionMatrix;
                //p = GL.GetGPUProjectionMatrix(p, false);
                if (cmd == null)
                {
                    Shader.SetGlobalMatrix(_Matrix_Perspective, p);
                }
                else
                {
                    cmd.SetGlobalMatrix(_Matrix_Perspective, p);
                }

                camera.ResetCullingMatrix();
                if (setFov && camera.fieldOfView < fov && camera.cameraType == CameraType.Game)
                {
                    //p = Matrix4x4.Perspective(fov, camera.aspect, camera.nearClipPlane, camera.farClipPlane);
                    camera.cullingMatrix = p * camera.worldToCameraMatrix;
                }
            }

            if (cmd == null)
            {
                Shader.SetGlobalColor(glstate_lightmodel_ambient, RenderSettings.ambientLight * 0.5f);
                Shader.SetGlobalColor(unity_Ambient, RenderSettings.ambientLight);
                Shader.SetGlobalColor(unity_AmbientSky, RenderSettings.ambientSkyColor);
                Shader.SetGlobalColor(unity_AmbientEquator, RenderSettings.ambientEquatorColor);
                Shader.SetGlobalColor(unity_AmbientGround, RenderSettings.ambientGroundColor);

                Shader.SetGlobalFloat(_SceneBloomFactor, ms_sceneBloomFactor);
                Shader.SetGlobalFloat(_RoleBloomFactor, ms_roleBloomFactor);
                Shader.SetGlobalFloat(_SkyBloomFactor, ms_skyBloomFactor);

                if (camera)
                {
                    var p = ms_Matrix_P_FOV == float.MaxValue ? camera.projectionMatrix : Matrix4x4.Perspective(ms_Matrix_P_FOV, camera.aspect, camera.nearClipPlane, camera.farClipPlane);
                    Shader.SetGlobalMatrix(_Matrix_Perspective, p);
                }
            }
            else
            {
                cmd.SetGlobalVector(glstate_lightmodel_ambient, RenderSettings.ambientLight * 0.5f);
                cmd.SetGlobalVector(unity_Ambient, RenderSettings.ambientLight);
                cmd.SetGlobalVector(unity_AmbientSky, RenderSettings.ambientSkyColor);
                cmd.SetGlobalVector(unity_AmbientEquator, RenderSettings.ambientEquatorColor);
                cmd.SetGlobalVector(unity_AmbientGround, RenderSettings.ambientGroundColor);

                cmd.SetGlobalFloat(_SceneBloomFactor, ms_sceneBloomFactor);
                cmd.SetGlobalFloat(_RoleBloomFactor, ms_roleBloomFactor);
                cmd.SetGlobalFloat(_SkyBloomFactor, ms_skyBloomFactor);
            }
        }
    }
}