//#define TEMPLY_COMMENT
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;

namespace X2Engine
{
    public class EnvProfileTexture
    {
        enum TextureLoadState
        {
            Unload,
            Loading,
            Loaded
        }
        private string path;
        private string name;
        private string suffix;
        private float timeLastUse;
        private TextureLoadState state;
        private Texture texture;

        public Texture Texture
        {
            get
            {
                if (null == path || null == name || null == suffix)
                    return null;
                //#if SCENE_EDITOR && UNITY_EDITOR
                //if (state == TextureLoadState.Unload)
                //{
                //    string assetPath = string.Concat("Assets/Asset/", path, name, suffix);
                //    texture = UnityEditor.AssetDatabase.LoadAssetAtPath<Texture>(assetPath);

                //    state = TextureLoadState.Loaded;
                //}
                //#else
               
                if (state == TextureLoadState.Unload)
                {
                    string assetPath = string.Concat(path, name);

                    //string realPath = "Assets/AssetBundles/Asset/" + assetPath + suffix;
                    
                    if (Application.isPlaying)
                        texture = ResourceManager.Instance.Load<Texture>("Asset/" + assetPath, suffix) as Texture;
#if UNITY_EDITOR
                    else
                    {
                        if (assetPath.Contains("Assets/AssetBundles/Asset/") == false)
                            assetPath = "Assets/AssetBundles/Asset/" + assetPath;
                        texture = UnityEditor.AssetDatabase.LoadAssetAtPath<Texture>(assetPath + suffix);
                    }
#endif
                    if (null == texture)
                        Debug.LogWarning("envProfile TextureLoad Failed:" + path + name + suffix);
                    if (null != texture)
                        state = TextureLoadState.Loaded;
                }
                //#endif
                timeLastUse = Time.time;
                return texture;
            }
        }

        public EnvProfileTexture(string assetPath)
        {
            if (null != assetPath && assetPath.Length > 0)
            {
                path = System.IO.Path.GetDirectoryName(assetPath);//filePath;
                path = path.Replace('\\', '/');
                path += "/";
                name = System.IO.Path.GetFileNameWithoutExtension(assetPath);//fileName;
                suffix = System.IO.Path.GetExtension(assetPath);//fileExtension;
            }
            else
            {
                path = name = suffix = null;
            }
            state = TextureLoadState.Unload;
            texture = null;
        }

        public void CheckIfNeedUnloadTex()
        {
//#if SCENE_EDITOR
            // 随便瞎b写几行，免得报warning
            //var now = Time.time;
            //if (now - timeLastUse > 5.0f)
            //    return;
//#else
            if (state == TextureLoadState.Loaded)
            {
                var now = Time.time;
                if (now - timeLastUse > 5.0f)
                {
                    texture = null;
                    state = TextureLoadState.Unload;
               }
           }
//#endif
        }
    }

    //[Serializable]
    //public struct EnvProfileTexPath
    //{
    //    public string path;
    //    public string name;
    //    public string suffix;
    //}

    [Serializable]
    public struct SunSettings
    {
        public bool enable;

        [Range(0, 360f)]
        public float sunDirection;
        [Range(0, 180f)]
        public float sunEquator;
        [Range(0, 360f)]
        public float moonDirection;
        [Range(0, 180f)]
        public float moonEquator;
        [Range(0, 24f)]
        public float timeline;

        public Color sunColor;
        public float sunIntensity;
        public float sunInDirectionIntensity;

        public Color charactorLightColor0;
        public float charactorLightIntensity0;
        public Color charactorLightColor1;
        public float charactorLightIntensity1;
#if TEMPLY_COMMENT
        // ProFlare Begin
        public ProFlareAsset proFlareAsset;
        public float GlobalScale;
        public bool MultiplyScaleByTransformScale;
        public float GlobalBrightness;
        public Color GlobalTintColor;
        // Proflare End
#endif

        public float bakedLighterStength;
        public float bakedEnvGIStrength;

        [Range(0, 24f)]
        public float shadowStrength;

        public void LerpUnclamped(ref SunSettings left, ref SunSettings right, float t)
        {
            if (left.enable || right.enable)
                enable = true;
            else
                enable = false;

            sunDirection = Mathf.LerpUnclamped(left.sunDirection, right.sunDirection, t);
            sunEquator = Mathf.LerpUnclamped(left.sunEquator, right.sunEquator, t);
            moonDirection = Mathf.LerpUnclamped(left.moonDirection, right.moonDirection, t);
            moonEquator = Mathf.LerpUnclamped(left.moonEquator, right.moonEquator, t);
            timeline = Mathf.LerpUnclamped(left.timeline % 24, right.timeline, t);

            sunColor = Color.LerpUnclamped(left.sunColor, right.sunColor, t);
            sunIntensity = Mathf.LerpUnclamped(left.sunIntensity, right.sunIntensity, t);

            charactorLightColor0 = Color.LerpUnclamped(left.charactorLightColor0, right.charactorLightColor0, t);
            charactorLightIntensity0 = Mathf.LerpUnclamped(left.charactorLightIntensity0, right.charactorLightIntensity0, t);
            charactorLightColor1 = Color.LerpUnclamped(left.charactorLightColor1, right.charactorLightColor1, t);
            charactorLightIntensity1 = Mathf.LerpUnclamped(left.charactorLightIntensity1, right.charactorLightIntensity1, t);
#if TEMPLY_COMMENT
            // ProFlare Begin
            proFlareAsset = t < 0.5f ? left.proFlareAsset : right.proFlareAsset;
            GlobalScale = t < 0.5f ? left.GlobalScale : right.GlobalScale;
            MultiplyScaleByTransformScale = t < 0.5f ? left.MultiplyScaleByTransformScale : right.MultiplyScaleByTransformScale;
            GlobalBrightness = t < 0.5f ? left.GlobalBrightness : right.GlobalBrightness;
            GlobalTintColor = t < 0.5f ? left.GlobalTintColor : right.GlobalTintColor;
            // Proflare End
#endif
            bakedLighterStength = Mathf.LerpUnclamped(left.bakedLighterStength, right.bakedLighterStength, t);
            bakedEnvGIStrength = Mathf.LerpUnclamped(left.bakedEnvGIStrength, right.bakedEnvGIStrength, t);
            shadowStrength = Mathf.LerpUnclamped(left.shadowStrength, right.shadowStrength, t);
        }
    }
    [Serializable]
    public struct AmbientLightProbeSH
    {
        public void InitData()
        {
            if (_data == null || _data.Length < 1)
                _data = new float[3 * 9];
        }
        public float[] _data ;

        public void SetData(UnityEngine.Rendering.SphericalHarmonicsL2 SHL2)
        {                
            for(int rgb = 0; rgb < 3; ++rgb)
                for(int j = 0; j < 9; ++j)
                {
                    _data[rgb * 9 + j] = SHL2[rgb, j];
                }
        }

        public void GiveData( ref UnityEngine.Rendering.SphericalHarmonicsL2 SHL2)
        {
            if(_data == null || _data.Length < 1)
            {
                //X2Interface.LogHelper.LogWarning("cube sky data is null!!");
                return;
            }
            for (int rgb = 0; rgb < 3; ++rgb)
                for (int j = 0; j < 9; ++j)
                {
                    SHL2[rgb,j] = _data[rgb * 9 + j];
                }
        }
    }

    public class InterLightProbe
    {
       public UnityEngine.Rendering.SphericalHarmonicsL2 SHL2;
       public bool bInit = false;
    }

    [Serializable]
    public struct AmbientSettings
    {
        public bool enable;
        public enum kAmbientSourceType
        {
            Skybox = 0,
            Trilight = 1,
            Flat = 3,
            CubeSkyColor = 4,
        }
        public kAmbientSourceType source;
        public Color skyColor;
        public Color equatorColor;
        public Color groundColor;
        [Range(0f, 8f)]
        public float intensity;
        [Range(0f, 1f)]
        public float reflectionIntensity;

        //up down color is skyColor groundColor
        public Color frontColor;
        public Color backColor;
        public Color leftColor;
        public Color rightColor;
        public bool bUseThisSH;

        public bool bCubeSkyDirty;
        public bool bToBakeGI;

        public Material bakeSkyMat;

        // save data
        public AmbientLightProbeSH ambientSH ;

        public InterLightProbe interLightProbe
        {
            get
            {
                if (_interLightProbe == null)
                {
                    _interLightProbe = new InterLightProbe();
                }
                return _interLightProbe;
            }
            set
            {
                _interLightProbe = value;
            }
        }
        // runtime lerp Probe
        private InterLightProbe _interLightProbe;

        //is character Ambient
        private bool bCharacterAmbient;

        public bool CharacterAmbient
        {
            get
            {
                return bCharacterAmbient;
            }
            set
            {
                bCharacterAmbient = value;
            }
        }

        //public void InitInterLightProbe()
        //{
        //    if(interLightProbe == null)
        //    {
        //        interLightProbe = new InterLightProbe();
        //    }
        //}
        public void SetLightProbeFromData()
        {
            //if(bCharacterAmbient)
            //{
            //    if (!interLightProbe.bInit)
            //    {
            //        ambientSH.GiveData(ref interLightProbe.SHL2);
            //        interLightProbe.bInit = true;
            //    }

            //    return;
            //}


            //if (source == kAmbientSourceType.CubeSkyColor)
            //{

            //    if (!interLightProbe.bInit)
            //    {
            //        ambientSH.GiveData(ref interLightProbe.SHL2);
            //        interLightProbe.bInit = true;
            //    }

            //}


            if (!interLightProbe.bInit)
            {
                ambientSH.GiveData(ref interLightProbe.SHL2);
                interLightProbe.bInit = true;
            }
        }

        private void CopySHData(ref AmbientSettings ambientSetting)
        {
            if (ambientSetting.ambientSH._data == null || ambientSetting.ambientSH._data.Length < 1)
                return;

            ambientSH.InitData();
            int nLenth = ambientSetting.ambientSH._data.Length;
            for (int i = 0; i < nLenth; ++i)
            {
                ambientSH._data[i] = ambientSetting.ambientSH._data[i];
            }
        }
        public void SetCubeDirty()
        {
            if (source == kAmbientSourceType.CubeSkyColor)
                bCubeSkyDirty = true;
        }
        //其实是浅拷贝了 现在
        public void DeepClone(ref AmbientSettings other)
        {
            other.SetLightProbeFromData();
            //InterLightProbe oldInterLightProbe = this.interLightProbe;            
            this = other;
            //interLightProbe不可能为null
            //if (oldInterLightProbe != null && interLightProbe == null)
            //{
            //    this.interLightProbe = oldInterLightProbe;
            //}
            ////CopySHData(ref other);
            //SetLightProbeFromData();
        }
        public void LerpUnclamped(ref AmbientSettings left, ref AmbientSettings right, float t)
        {
            // bool bNeedDirtyCubeSky = false;

            if (EnvironmentSystem.instance.editorMode)
                return;

            if (left.enable || right.enable)
                enable = true;
            else
                enable = false;

            //// Character Ambient
            //if(left. bCharacterAmbient)
            //{
            //    left.SetLightProbeFromData();
            //    right.SetLightProbeFromData();
            //    if (left.interLightProbe != null && right.interLightProbe != null)
            //    {
            //        interLightProbe.SHL2 = left.interLightProbe.SHL2 * (1.0f - t) + right.interLightProbe.SHL2 * t;
            //        interLightProbe.bInit = true;
            //    }
            //    return;
            //}

            if (left.source == right.source)
            {
                source = left.source;
            }
            else
            {
                var newSource = t < 0.5 ? left.source : right.source;
                source = newSource;
            }


            left.SetLightProbeFromData();
            right.SetLightProbeFromData();
            if (left.interLightProbe != null && right.interLightProbe != null)
            {
                interLightProbe.SHL2 = left.interLightProbe.SHL2 * (1.0f - t) + right.interLightProbe.SHL2 * t;
                interLightProbe.bInit = true;
            }

            return;

            /*
            ///////////////////////////////////////////////////////////////
            bCubeSkyDirty = false;

            if (left.source == right.source)
            {
                source = left.source;
                var newSkyColor = Color.LerpUnclamped(left.skyColor, right.skyColor, t);
                equatorColor = Color.LerpUnclamped(left.equatorColor, right.equatorColor, t);
                var newGroundColor = Color.LerpUnclamped(left.groundColor, right.groundColor, t);
                intensity = Mathf.LerpUnclamped(left.intensity, right.intensity, t);

                if(source == kAmbientSourceType.CubeSkyColor)
                {
                    var newFrontColor = Color.LerpUnclamped(left.frontColor, right.frontColor, t);
                    var newBackColor = Color.LerpUnclamped(left.backColor, right.backColor, t);
                    var newLeftColor = Color.LerpUnclamped(left.leftColor, right.leftColor, t);
                    var newRightColor = Color.LerpUnclamped(left.rightColor, right.rightColor, t);

                    if (!Color.Equals(newSkyColor, skyColor))
                    {
                        skyColor = newSkyColor;
                        SetCubeDirty();
                    }
                    if (!Color.Equals(newGroundColor, groundColor))
                    {
                        groundColor = newGroundColor;
                        SetCubeDirty();
                    }
                    if (!Color.Equals(newFrontColor, frontColor))
                    {
                        frontColor = newFrontColor;
                        SetCubeDirty();
                    }
                    if (!Color.Equals(newBackColor, backColor))
                    {
                        backColor = newBackColor;
                        SetCubeDirty();
                    }
                    if (!Color.Equals(newLeftColor, leftColor))
                    {
                        leftColor = newLeftColor;
                        SetCubeDirty();
                    }
                    if (!Color.Equals(newRightColor, rightColor))
                    {
                        rightColor = newRightColor;
                        SetCubeDirty();
                    }

                }
                else
                {
                    skyColor = newSkyColor;
                    groundColor = newGroundColor;
                }



                if (source == kAmbientSourceType.CubeSkyColor && bCubeSkyDirty && right.source == kAmbientSourceType.CubeSkyColor)
                {
                    SetLightProbeFromData();

                    right.SetLightProbeFromData();

                    if (interLightProbe != null && right.interLightProbe != null)
                    {
                        interLightProbe.SHL2 = interLightProbe.SHL2 * (1.0f - t) + right.interLightProbe.SHL2 * t;
                        interLightProbe.bInit = true;
                    }
                    //right.SetLightProbeFromData();

                }

                //X2Interface.LogHelper.Log("Ambient lerp t:" + t.ToString());
            }
            else
            {
               var newSource = t < 0.5? left.source : right.source;
               var newSkyColor = t < 0.5 ? left.skyColor : right.skyColor;
                equatorColor = t < 0.5 ? left.equatorColor : right.equatorColor;
                var newGroundColor = t < 0.5 ? left.groundColor : right.groundColor;
                intensity = t < 0.5 ? left.intensity : right.intensity;

                var newFrontColor = t < 0.5 ? left.frontColor : right.frontColor;
                var newBackColor = t < 0.5 ? left.backColor : right.backColor;
                var newLeftColor = t < 0.5 ? left.leftColor : right.leftColor;
                var newRightColor = t < 0.5 ? left.rightColor : right.rightColor;

                if (source != newSource )
                {
                    source = newSource;
                    SetCubeDirty();
                }
                
                if (!Color.Equals(newSkyColor, skyColor))
                {
                    skyColor = newSkyColor;
                    SetCubeDirty();
                }
                if (!Color.Equals(newGroundColor, groundColor))
                {
                    groundColor = newGroundColor;
                    SetCubeDirty();
                }

                if (source == kAmbientSourceType.CubeSkyColor)
                {

                    if (!Color.Equals(newFrontColor, frontColor))
                    {
                        frontColor = newFrontColor;
                        SetCubeDirty();
                    }
                    if (!Color.Equals(newBackColor, backColor))
                    {
                        backColor = newBackColor;
                        SetCubeDirty();
                    }
                    if (!Color.Equals(newLeftColor, leftColor))
                    {
                        leftColor = newLeftColor;
                        SetCubeDirty();
                    }
                    if (!Color.Equals(newRightColor, rightColor))
                    {
                        rightColor = newRightColor;
                        SetCubeDirty();
                    }
                }

                //t > 0.5
                if (source == kAmbientSourceType.CubeSkyColor && bCubeSkyDirty  && t <0.5 )
                {
                    
                    SetLightProbeFromData();
                    //right.SetLightProbeFromData();

                }
                else if(source == kAmbientSourceType.CubeSkyColor && bCubeSkyDirty && t >= 0.5)
                {
                    CopySHData(ref right);

                    right.SetLightProbeFromData();

                    if (interLightProbe != null && right.interLightProbe != null)
                    {
                        interLightProbe.SHL2 = right.interLightProbe.SHL2;
                    }
                }
                //X2Interface.LogHelper.Log("Ambient lerp t:" + t.ToString());

            }
            reflectionIntensity = Mathf.LerpUnclamped(left.reflectionIntensity, right.reflectionIntensity, t);
*/
        }


    }

    [Serializable]
    public struct SkyBoxSettings
    {
        public bool enable;
        public float exposure;
        public float rotation;
        //public Texture texture;
        public string texPath;

        public bool isFog;

        private EnvProfileTexture skyTexture;

        private float m_blend;

        public float Blend
        {
            get
            {
                return 1.0f - m_blend; //bhe blend is revert
            }
        }

        public EnvProfileTexture SkyTexture
        {
            get
            {
                if (null == skyTexture)
                    skyTexture = new EnvProfileTexture(texPath);
                return skyTexture;
            }
            set
            {
                skyTexture = value;
            }
        }

        public void LerpUnclamped(ref SkyBoxSettings left, ref SkyBoxSettings right, float t)
        {
            if (left.enable || right.enable)
                enable = true;
            else
                enable = false;

            m_blend = 1.0f - t; // bhe blend is revert
            if (m_blend < 0)
                m_blend = 0;
            if (m_blend > 1)
                m_blend = 1;

            if (right.enable && !left.enable)
            {
                //texture = right.texture;
                if(string.Compare(texPath, right.texPath) != 0)
                {
                    texPath = right.texPath;
                    skyTexture = right.skyTexture;
                }
               
                exposure = Mathf.LerpUnclamped(0, right.exposure, t);
                rotation = right.rotation;
                enable = true;
                isFog = right.isFog;

            }
            else if (left.enable && !right.enable)
            {
                if (string.Compare(texPath, left.texPath) != 0)
                {
                    //texture = left.texture;
                    texPath = left.texPath;
                    skyTexture = left.skyTexture;
                }
                exposure = Mathf.LerpUnclamped(left.exposure, 0, t);
                rotation = left.rotation;
                enable = true;
                isFog = left.isFog;
            }
            else if (left.enable && right.enable)
            {
                if (string.Compare(texPath, right.texPath) != 0)
                {
                    texPath = right.texPath;
                    skyTexture = right.skyTexture;
                }
                exposure = left.exposure * (1.0f - t) + right.exposure * t;
                rotation = right.rotation;
                isFog = right.isFog;

                //if (t >= 0.5f)
                //{
                //    //texture = left.texture;
                //    texPath = left.texPath;
                //    skyTexture = left.skyTexture;
                //    exposure = right.exposure * (t * 2f - 1f);
                //    rotation = right.rotation;
                //    enable = true;
                //}
                //else
                //{
                //    //texture = left.texture;
                //    texPath = left.texPath;
                //    skyTexture = left.skyTexture;
                //    exposure = left.exposure * ((1f - t) * 2f - 1f);
                //    rotation = left.rotation;
                //    enable = true;
                //}
            }
            else
            {
                //texture = null;
                texPath = null;
                skyTexture = null;
                exposure = 0;
                rotation = 0;
                enable = false;
                m_blend = 1;
                isFog = true;
            }

        }

        public void CopyDiffentFrom(ref SkyBoxSettings right)
        {
            if (string.Compare(texPath, right.texPath) != 0)
            {
                texPath = right.texPath;
                skyTexture = right.skyTexture;
            }

            exposure = right.exposure;
            rotation = right.rotation;
            enable = right.enable;
        }

    }
   

    [Serializable]
    public struct AtmosphericScatteringSettings
    {
        public bool enable;

        // 太阳
        public bool enableSunDisk;
        public Vector3 sunIrradiance;
        public float sunDiameter;
        public float sunBrightness;
        // 月亮
        public bool enableMoon;
        public float moonAlbedo;
        public float moonContrast;
        public float moonDiameter;
        public float moonIrradiance;
        public Color moonLightColor;
        public Vector2 moonLightSource;
        // 大气散射
        public float brightnessPower; // 亮度
        public float maxAltitudeKm; // 相机最高海度
        public float maxDistanceKm; // 最远可视距离
        public Vector3 rayleigh; // 瑞丽系数
        // 大气层
        public float ozoneStrength; // 臭氧
        public Color baseOzone; // 臭氧颜色
        public float emissivity; // 辐射系数
        public float planetRadiusKm; // 地球半径
        public float atmosphereThicknessKm; // 大气层厚度
        // 星空
        public bool enableStar;
        public int maxStarMagnitude; // 星星密度
        public float starBrightness;  // 星星亮度
        public float starLight;
        public bool enableMilkyWay;
        public float backgroundBrightness; // 背景亮度
        public float backgroundOffset; // 偏移
        public float backgroundRotation; // 旋转
        // 天空颜色
        
        public float blendToColours;
        public Color zenith;
        public Color horizon;
        // 雾效
        public float haze; // 雾浓度
        public float hazeBaseKm; // 雾消散起点
        public float hazeScaleKm; // 雾标尺高度
        public float hazeEccentricity; // 雾离心率
        public Vector3 mie; // 米散射系数
        public bool autoMie; // 自动计算米散射系数
        // HeightFog
        public Color fogColor;
        public float fogDensity;
        public float fogHalfDensityHeight;
        public float fogHeightOffset;
        public float fogStartDistance;
        public float fogRange;

        
        public bool CompareScatteringParam(ref AtmosphericScatteringSettings other)
        {
            if (moonIrradiance != other.moonIrradiance) return false;
            if (moonLightColor != other.moonLightColor) return false;
            if (sunIrradiance != other.sunIrradiance) return false;
            if (maxAltitudeKm != other.maxAltitudeKm) return false;
            if (maxDistanceKm != other.maxDistanceKm) return false;
            if (rayleigh != other.rayleigh) return false;
            if (ozoneStrength != other.ozoneStrength) return false;
            if (baseOzone != other.baseOzone) return false;
            if (emissivity != other.emissivity) return false;
            if (planetRadiusKm != other.planetRadiusKm) return false;
            if (atmosphereThicknessKm != other.atmosphereThicknessKm) return false;
            if (starLight != other.starLight) return false;
            if (blendToColours != other.blendToColours) return false;
            if (zenith != other.zenith) return false;
            if (horizon != other.horizon) return false;
            if (haze != other.haze) return false;
            if (hazeBaseKm != other.hazeBaseKm) return false;
            if (hazeScaleKm != other.hazeScaleKm) return false;
            if (hazeEccentricity != other.hazeEccentricity) return false;
            if (mie != other.mie) return false;
            return true;
        }

        public void LerpUnclamped(ref AtmosphericScatteringSettings left, ref AtmosphericScatteringSettings right, float t)
        {
            if (left.enable || right.enable)
                enable = true;
            else
                enable = false;

            if (left.enableSunDisk || right.enableSunDisk)
                enableSunDisk = true;
            else
                enableSunDisk = false;

            if (left.enableMoon || right.enableMoon)
                enableMoon = true;
            else
                enableMoon = false;

            if (left.enableStar || right.enableStar)
                enableStar = true;
            else
                enableStar = false;

            if (left.enableMilkyWay || right.enableMilkyWay)
                enableMilkyWay = true;
            else
                enableMilkyWay = false;


            sunIrradiance = Vector3.LerpUnclamped(left.sunIrradiance, right.sunIrradiance, t);
            sunDiameter = Mathf.LerpUnclamped(left.sunDiameter, right.sunDiameter, t);
            sunBrightness = Mathf.LerpUnclamped(left.sunBrightness, right.sunBrightness, t);

            moonAlbedo = Mathf.LerpUnclamped(left.moonAlbedo, right.moonAlbedo, t);
            moonContrast = Mathf.LerpUnclamped(left.moonContrast, right.moonContrast, t);
            moonDiameter = Mathf.LerpUnclamped(left.moonDiameter, right.moonDiameter, t);
            moonIrradiance = Mathf.LerpUnclamped(left.moonIrradiance, right.moonIrradiance, t);
            moonLightColor = Color.LerpUnclamped(left.moonLightColor, right.moonLightColor, t);
            moonLightSource = Vector2.LerpUnclamped(left.moonLightSource, right.moonLightSource, t);

            brightnessPower = Mathf.LerpUnclamped(left.brightnessPower, right.brightnessPower, t);
            maxAltitudeKm = Mathf.LerpUnclamped(left.maxAltitudeKm, right.maxAltitudeKm, t);
            maxDistanceKm = Mathf.LerpUnclamped(left.maxDistanceKm, right.maxDistanceKm, t);
            rayleigh = Vector3.LerpUnclamped(left.rayleigh, right.rayleigh, t);

            ozoneStrength = Mathf.LerpUnclamped(left.ozoneStrength, right.ozoneStrength, t);
            baseOzone = Color.LerpUnclamped(left.baseOzone, right.baseOzone, t);
            emissivity = Mathf.LerpUnclamped(left.emissivity, right.emissivity, t);
            planetRadiusKm = Mathf.LerpUnclamped(left.planetRadiusKm, right.planetRadiusKm, t);
            atmosphereThicknessKm = Mathf.LerpUnclamped(left.atmosphereThicknessKm, right.atmosphereThicknessKm, t);

            //maxStarMagnitude = Math.LerpUnclamped(left.maxStarMagnitude, right.maxStarMagnitude, t);
            starBrightness = Mathf.LerpUnclamped(left.starBrightness, right.starBrightness, t);
            starLight = Mathf.LerpUnclamped(left.starLight, right.starLight, t);
            backgroundBrightness = Mathf.LerpUnclamped(left.backgroundBrightness, right.backgroundBrightness, t);
            backgroundOffset = Mathf.LerpUnclamped(left.backgroundOffset, right.backgroundOffset, t);
            backgroundRotation = Mathf.LerpUnclamped(left.backgroundRotation, right.backgroundRotation, t);

            blendToColours = Mathf.LerpUnclamped(left.blendToColours, right.blendToColours, t);
            if (left.blendToColours > 0 && right.blendToColours > 0)
            {
                zenith = Color.LerpUnclamped(left.zenith, right.zenith, t);
                horizon = Color.LerpUnclamped(left.horizon, right.horizon, t);
            }
            else if (left.blendToColours > 0 && right.blendToColours == 0)
            {
                zenith = left.zenith;
                horizon = left.horizon;
            }
            else if (left.blendToColours == 0 && right.blendToColours > 0)
            {
                zenith = right.zenith;
                horizon = right.horizon;
            }
            else
            {
                zenith = Color.black;
                horizon = Color.black;
            }

            haze = Mathf.LerpUnclamped(left.haze, right.haze, t);
            hazeBaseKm = Mathf.LerpUnclamped(left.hazeBaseKm, right.hazeBaseKm, t);
            hazeScaleKm = Mathf.LerpUnclamped(left.hazeScaleKm, right.hazeScaleKm, t);
            hazeEccentricity = Mathf.LerpUnclamped(left.hazeEccentricity, right.hazeEccentricity, t);
            mie = Vector3.LerpUnclamped(left.mie, right.mie, t);

            if (left.fogDensity < 0.0001f)
            {
                fogDensity = Mathf.LerpUnclamped(left.fogDensity, right.fogDensity, t);
                fogColor = right.fogColor;
                fogHalfDensityHeight = right.fogHalfDensityHeight;
                fogHeightOffset = right.fogHeightOffset;
                fogStartDistance = right.fogStartDistance;
                fogRange = right.fogRange;
            }
            else if (right.fogDensity < 0.0001f)
            {
                fogDensity = Mathf.LerpUnclamped(left.fogDensity, right.fogDensity, t);
                fogColor = left.fogColor;
                fogHalfDensityHeight = left.fogHalfDensityHeight;
                fogHeightOffset = left.fogHeightOffset;
                fogStartDistance = left.fogStartDistance;
                fogRange = left.fogRange;
            }
            else
            {
                fogColor = Color.LerpUnclamped(left.fogColor, right.fogColor, t);
                fogDensity = Mathf.LerpUnclamped(left.fogDensity, right.fogDensity, t);
                fogHalfDensityHeight = Mathf.LerpUnclamped(left.fogHalfDensityHeight, right.fogHalfDensityHeight, t);
                fogHeightOffset = Mathf.LerpUnclamped(left.fogHeightOffset, right.fogHeightOffset, t);
                fogStartDistance = Mathf.LerpUnclamped(left.fogStartDistance, right.fogStartDistance, t);
                fogRange = Mathf.LerpUnclamped(left.fogRange, right.fogRange, t);
            }
        }
    }

    [Serializable]
    public struct Cloud2dSettings
    {
        public bool enable;

        public enum AmbientSource
        {
            SkyColor,
            EquatorColor
        }

        public enum MappingMode
        {
            Rectangular,
            Polar
        }

        //public AmbientSource ambientSource;
        public float attenuation;
        public float stepSize;
        public float alphaSaturation;
        public float lightColorMultiplier;
        public Color skyColor;
        public float skyColorMultiplier;
        public float cloudsDensity;
        public float scatterMultiplier;
        public MappingMode mappingMode;
        public float rotateSpeed;
        public float heightOffset;
        public Material cloudMaterial;
        public void LerpUnclamped(ref Cloud2dSettings left, ref Cloud2dSettings right, float t)
        {
            if (left.enable || right.enable)
                enable = true;
            else
                enable = false;

            //ambientSource = left.ambientSource;
            mappingMode = left.mappingMode;
            cloudMaterial = left.cloudMaterial;
            attenuation = Mathf.LerpUnclamped(left.attenuation, right.attenuation, t);
            stepSize = Mathf.LerpUnclamped(left.stepSize, right.stepSize, t);
            alphaSaturation = Mathf.LerpUnclamped(left.alphaSaturation, right.alphaSaturation, t);
            lightColorMultiplier = Mathf.LerpUnclamped(left.lightColorMultiplier, right.lightColorMultiplier, t);
            skyColor = Color.LerpUnclamped(left.skyColor, right.skyColor, t);
            skyColorMultiplier = Mathf.LerpUnclamped(left.skyColorMultiplier, right.skyColorMultiplier, t);
            cloudsDensity = Mathf.LerpUnclamped(left.cloudsDensity, right.cloudsDensity, t);
            scatterMultiplier = Mathf.LerpUnclamped(left.scatterMultiplier, right.scatterMultiplier, t);
            rotateSpeed = Mathf.LerpUnclamped(left.rotateSpeed, right.rotateSpeed, t);
            heightOffset = Mathf.LerpUnclamped(left.heightOffset, right.heightOffset, t);
        }
    }

    [Serializable]
    public struct BlackHoleSettings
    {
        public bool enable;
        public float radius;
        public float offsetDistance;
        public float scaleCoef;
        public float intensity;
        public float darkIntensity;

        public void LerpUnclamped(ref BlackHoleSettings left, ref BlackHoleSettings right, float t)
        {
            //ambientSource = left.ambientSource;
            if(left.enable && !right.enable)
            {
                enable = right.enable;
                radius = right.radius;
                offsetDistance = right.offsetDistance;
                scaleCoef = right.scaleCoef;
                intensity = right.intensity;
                darkIntensity = right.darkIntensity;
            }
            else if(!left.enable && right.enable)
            {
                enable = right.enable;
                radius = right.radius;
                offsetDistance = right.offsetDistance;
                scaleCoef = right.scaleCoef;
                intensity = right.intensity;
                darkIntensity = right.darkIntensity;
            }
            else
            {
                enable = right.enable;
                radius = Mathf.LerpUnclamped(left.radius, right.radius, t);
                offsetDistance = Mathf.LerpUnclamped(left.offsetDistance, right.offsetDistance, t);
                scaleCoef = Mathf.LerpUnclamped(left.scaleCoef, right.scaleCoef, t);
                intensity = Mathf.LerpUnclamped(left.intensity, right.intensity, t);
                darkIntensity = Mathf.LerpUnclamped(left.darkIntensity, right.darkIntensity, t);

            }

        }
    }

    [Serializable]
    public struct FogVolumeState
    {
        public Color FogMainColor;
        //public Vector3 fogVolumeScale;
        public Color _AmbientColor;
        //public float Absorption;
        //public float HeightAbsorption;
        //public bool EnableInscattering;
        public Color InscatteringColor;
        //public float InscatteringShape;
        //public float InscatteringIntensity;
        //public float InscatteringStartDistance;
        //public float InscatteringTransitionWideness;
        public Color LightExtinctionColor;

        public float PenetrateScale;
        public float PenetrateMaxDepth;
        //public bool _DirectionalLighting;
        //public float _DirectionalLightingDistance;
        //public float DirectLightingShadowDensity;
        //public int DirectLightingShadowSteps;
        //public bool ColorAdjust;
        //public float Offset;
        //public float Gamma;
        //public float NoiseIntensity;
        //public int Iterations;
        //public float IterationStep;
        //public float _OptimizationFactor;
        //public float FadeDistance;
        //public bool useHeightGradient;
        //public float GradMin;
        //public float GradMax;
        //public float GradMin2;
        //public float GradMax2;

        //public bool EnableNoise;
        //public float _3DNoiseScale;
        //public Vector4 Speed;
        //public Vector4 Stretch;

        //public float NoiseContrast;
        //public float NoiseDensity;
        //public int Octaves;
        //public float BaseTiling;
        //public float _BaseRelativeSpeed;

        //public float DetailTiling;
        //public float _DetailRelativeSpeed;
        //public float DetailDistance;
        //public float _NoiseDetailRange;
        //public float _DetailMaskingThreshold;
        //public float _Curl;
        //public float _CumulonimbusIntensity;
        //public float _CrestaIntensity;

        public float PreBake_Gammar;
        public Color TintForPreCal;
        public Vector2 Velocity;
        public float JitterIntensity;
        public float pre_cloud_depth_degeneration_intensity;
        public float pre_cloud_depth_range;

        public void LerpUnclamped(ref FogVolumeState left, ref FogVolumeState right, float t)
        {
            FogMainColor = Color.LerpUnclamped(left.FogMainColor, right.FogMainColor, t);
            _AmbientColor = Color.LerpUnclamped(left._AmbientColor, right._AmbientColor, t);
            //Absorption = Mathf.LerpUnclamped(left.Absorption, right.Absorption, t);
            //HeightAbsorption = Mathf.LerpUnclamped(left.HeightAbsorption, right.HeightAbsorption, t);
            //InscatteringShape = Mathf.LerpUnclamped(left.InscatteringShape, right.InscatteringShape, t);
            //InscatteringIntensity = Mathf.LerpUnclamped(left.InscatteringIntensity, right.InscatteringIntensity, t);
            //InscatteringStartDistance = Mathf.LerpUnclamped(left.InscatteringStartDistance, right.InscatteringStartDistance, t);
            //InscatteringTransitionWideness = Mathf.LerpUnclamped(left.InscatteringTransitionWideness, right.InscatteringTransitionWideness, t);
            LightExtinctionColor = Color.LerpUnclamped(left.LightExtinctionColor, right.LightExtinctionColor, t);
            InscatteringColor = Color.LerpUnclamped(left.InscatteringColor, right.InscatteringColor, t);
            PenetrateScale = Mathf.LerpUnclamped(left.PenetrateScale, right.PenetrateScale, t);
            PenetrateMaxDepth = Mathf.LerpUnclamped(left.PenetrateMaxDepth, right.PenetrateMaxDepth, t);
            //_DirectionalLightingDistance = Mathf.LerpUnclamped(left._DirectionalLightingDistance, right._DirectionalLightingDistance, t);
            //DirectLightingShadowDensity = Mathf.LerpUnclamped(left.DirectLightingShadowDensity, right.DirectLightingShadowDensity, t);
            //Offset = Mathf.LerpUnclamped(left.Offset, right.Offset, t);
            //Gamma = Mathf.LerpUnclamped(left.Gamma, right.Gamma, t);
            //NoiseIntensity = Mathf.LerpUnclamped(left.NoiseIntensity, right.NoiseIntensity, t);
            //FadeDistance = Mathf.LerpUnclamped(left.FadeDistance, right.FadeDistance, t);
            //GradMin = Mathf.LerpUnclamped(left.GradMin, right.GradMin, t);
            //GradMax = Mathf.LerpUnclamped(left.GradMax, right.GradMax, t);
            //GradMin2 = Mathf.LerpUnclamped(left.GradMin2, right.GradMin2, t);
            //GradMax2 = Mathf.LerpUnclamped(left.GradMax2, right.GradMax2, t);
            //_3DNoiseScale = Mathf.LerpUnclamped(left._3DNoiseScale, right._3DNoiseScale, t);
            //NoiseContrast = Mathf.LerpUnclamped(left.NoiseContrast, right.NoiseContrast, t);
            //NoiseDensity = Mathf.LerpUnclamped(left.NoiseDensity, right.NoiseDensity, t);
            ////BaseTiling = Mathf.LerpUnclamped(left.BaseTiling, right.BaseTiling, t);
            ////_BaseRelativeSpeed = Mathf.LerpUnclamped(left._BaseRelativeSpeed, right._BaseRelativeSpeed, t);
            ////DetailTiling = Mathf.LerpUnclamped(left.DetailTiling, right.DetailTiling, t);
            ////_DetailRelativeSpeed = Mathf.LerpUnclamped(left._DetailRelativeSpeed, right._DetailRelativeSpeed, t);
            //DetailDistance = Mathf.LerpUnclamped(left.DetailDistance, right.DetailDistance, t);
            //_NoiseDetailRange = Mathf.LerpUnclamped(left._NoiseDetailRange, right._NoiseDetailRange, t);
            //_DetailMaskingThreshold = Mathf.LerpUnclamped(left._DetailMaskingThreshold, right._DetailMaskingThreshold, t);
            ////_Curl = Mathf.LerpUnclamped(left._Curl, right._Curl, t);
            //_CumulonimbusIntensity = Mathf.LerpUnclamped(left._CumulonimbusIntensity, right._CumulonimbusIntensity, t);
            //_CrestaIntensity = Mathf.LerpUnclamped(left._CrestaIntensity, right._CrestaIntensity, t);
            TintForPreCal = Color.LerpUnclamped(left.TintForPreCal, right.TintForPreCal, t);
            JitterIntensity = Mathf.LerpUnclamped(left.JitterIntensity, right.JitterIntensity, t);
            pre_cloud_depth_degeneration_intensity = Mathf.LerpUnclamped(left.pre_cloud_depth_degeneration_intensity, right.pre_cloud_depth_degeneration_intensity, t);
            pre_cloud_depth_range = Mathf.LerpUnclamped(left.pre_cloud_depth_range, right.pre_cloud_depth_range, t);
            Velocity = Vector2.LerpUnclamped(left.Velocity, right.Velocity, t);
        }
    }


    [Serializable]
    public struct WeatherSystemSettings
    {
        public bool isRaining;
        public bool isFlashLighting;
        public float rainningAmount;
        public float diffuseDarkening;
        public float puddleAmount;
        public float puddleRipplesAmount;
        public float puddleRipplesScale;
        public float nearRainDropIntensity;
        public float farRainDropIntensity;
        public bool isSnowing;
        public float rpOutDoorStrength;
       
        public void LerpUnclamped(ref WeatherSystemSettings left, ref WeatherSystemSettings right, float t)
        {
            if (right.isRaining && !left.isRaining)
            {
                isRaining = right.isRaining;
                isFlashLighting = right.isFlashLighting;
                rainningAmount = right.rainningAmount * t;
                diffuseDarkening = right.diffuseDarkening;
                puddleAmount = right.puddleAmount;
                puddleRipplesAmount = right.puddleRipplesAmount;
                puddleRipplesScale = right.puddleRipplesScale;
                nearRainDropIntensity = right.nearRainDropIntensity;
                farRainDropIntensity = right.farRainDropIntensity;
            }
            else if (left.isRaining && !right.isRaining)
            {
                isRaining = left.isRaining;
                isFlashLighting = left.isFlashLighting;
                rainningAmount = left.rainningAmount * (1f - t);
                diffuseDarkening = left.diffuseDarkening;
                puddleAmount = left.puddleAmount;
                puddleRipplesAmount = left.puddleRipplesAmount;
                puddleRipplesScale = left.puddleRipplesScale;
                nearRainDropIntensity = left.nearRainDropIntensity;
                farRainDropIntensity = left.farRainDropIntensity;
            }
            else
            {
                isRaining = right.isRaining;
                isFlashLighting = right.isFlashLighting;
                rainningAmount = Mathf.LerpUnclamped(left.rainningAmount, right.rainningAmount, t);
                diffuseDarkening = Mathf.LerpUnclamped(left.diffuseDarkening, right.diffuseDarkening, t);
                puddleAmount = Mathf.LerpUnclamped(left.puddleAmount, right.puddleAmount, t);
                puddleRipplesAmount = Mathf.LerpUnclamped(left.puddleRipplesAmount, right.puddleRipplesAmount, t);
                puddleRipplesScale = Mathf.LerpUnclamped(left.puddleRipplesScale, right.puddleRipplesScale, t);
                nearRainDropIntensity = Mathf.LerpUnclamped(left.nearRainDropIntensity, right.nearRainDropIntensity, t);
                farRainDropIntensity = Mathf.LerpUnclamped(left.farRainDropIntensity, right.farRainDropIntensity, t);
            }

            rpOutDoorStrength = Mathf.LerpUnclamped(left.rpOutDoorStrength, right.rpOutDoorStrength, t);
           
        }
    }


    [Serializable]
    public struct CloudShadowSettings
    {
        public bool enable;
        public Texture cloudTexture;
        public Vector2 cloudTiling;
        public Vector2 cloudWindSpeed;
        [Range(0.0f, 1.0f)]
        public float cloudFadeOut;
        [Range(0.0f, 1.0f)]
        public float shadowIntensity;
        public bool hasCloudShadow;

        public void LerpUnclamped(ref CloudShadowSettings left, ref CloudShadowSettings right, float t)
        {
            if (left.enable || right.enable)
                enable = true;
            else
                enable = false;

            if (left.hasCloudShadow && !right.hasCloudShadow)
            {
                hasCloudShadow = left.hasCloudShadow;
                cloudTexture = left.cloudTexture;
                cloudTiling = left.cloudTiling;
                cloudWindSpeed = left.cloudWindSpeed;
                cloudFadeOut = left.cloudFadeOut;
                shadowIntensity = Mathf.LerpUnclamped(left.shadowIntensity, 0, t);
            }
            else if (!left.hasCloudShadow && right.hasCloudShadow)
            {
                hasCloudShadow = right.hasCloudShadow;
                cloudTexture = right.cloudTexture;
                cloudTiling = right.cloudTiling;
                cloudWindSpeed = right.cloudWindSpeed;
                cloudFadeOut = right.cloudFadeOut;
                shadowIntensity = Mathf.LerpUnclamped(0, right.shadowIntensity, t);
            }
            else if( left.hasCloudShadow && right.hasCloudShadow)
            {
                hasCloudShadow = true;
                cloudTexture = left.cloudTexture;
                cloudTiling = left.cloudTiling;
                cloudWindSpeed = left.cloudWindSpeed;
                cloudFadeOut = left.cloudFadeOut;
                shadowIntensity = left.shadowIntensity;
            }
            else
            {
                hasCloudShadow = false;
            }
        }


    }

    [Serializable]
    public struct OceanFogSettings
    {
        public bool enable;
        public Color oceanFogColor;
        public float oceanFogColorMultiplier;
        public float oceanFogDensity;
        public void LerpUnclamped(ref OceanFogSettings left, ref OceanFogSettings right, float t)
        {
            if (left.enable || right.enable)
                enable = true;
            else
                enable = false;
            oceanFogColor = Color.LerpUnclamped(left.oceanFogColor, right.oceanFogColor, t);
            oceanFogColorMultiplier = Mathf.LerpUnclamped(left.oceanFogColorMultiplier, right.oceanFogColorMultiplier, t);
            oceanFogDensity = Mathf.LerpUnclamped(left.oceanFogDensity, right.oceanFogDensity, t);

        }
    }

    [Serializable]
    public struct ShadowFociSettings
    {
        public bool enable;
        public Vector3 offset;
        public float radius;
        [Range(-0.08f, 0.09f)]
        public float depthBias;

        [Range(-0.08f, 0.09f)]
        public float maleDepthBias;

        public void LerpUnclamped(ref ShadowFociSettings left, ref ShadowFociSettings right, float t)
        {
            if (left.enable || right.enable)
                enable = true;
            else
                enable = false;
            offset = Vector3.LerpUnclamped(left.offset, right.offset, t);
            radius = Mathf.LerpUnclamped(left.radius, right.radius, t);
            depthBias = Mathf.LerpUnclamped(left.depthBias, right.depthBias, t);
            maleDepthBias = Mathf.LerpUnclamped(left.maleDepthBias, right.maleDepthBias, t);

        }
    }

    [Serializable]
    public struct VolumetricFogSettings
    {
        public bool enable;
        public float scatteringCoef;
        public float absorptionCoef;
        public float phaseAnisotropy;

        // TODO : ???
        private List<VolumetricFogDensity> m_densityList;

        public void LerpUnclamped(ref VolumetricFogSettings left, ref VolumetricFogSettings right, float t)
        {
            //ambientSource = left.ambientSource;
            if (left.enable && !right.enable)
            {
                enable = right.enable;
                scatteringCoef = right.scatteringCoef;
                absorptionCoef = right.absorptionCoef;
                phaseAnisotropy = right.phaseAnisotropy;
            }
            else if (!left.enable && right.enable)
            {
                enable = right.enable;
                scatteringCoef = right.scatteringCoef;
                absorptionCoef = right.absorptionCoef;
                phaseAnisotropy = right.phaseAnisotropy;
            }
            else
            {
                enable = right.enable;
                scatteringCoef = Mathf.LerpUnclamped(left.scatteringCoef, right.scatteringCoef, t);
                absorptionCoef = Mathf.LerpUnclamped(left.absorptionCoef, right.absorptionCoef, t);
                phaseAnisotropy = Mathf.LerpUnclamped(left.phaseAnisotropy, right.phaseAnisotropy, t);
            }

        }

        public void AddDensity(VolumetricFogDensity vfd)
        {
            if (m_densityList == null)
                m_densityList = new List<VolumetricFogDensity>();

            for (int i = 0; i < m_densityList.Count; i++)
            {
                if (m_densityList[i] == vfd)
                    return;
            }

            m_densityList.Add(vfd);
        }

        public void RemoveDensity(VolumetricFogDensity vfd)
        {
            if(m_densityList != null)
                m_densityList.Remove(vfd);
        }

        public List<VolumetricFogDensity> GetDensityList()
        {
            if(m_densityList != null)
                m_densityList.RemoveAll(x=>x == null);
            return m_densityList;
        }
    }

    public class EnvironmentProfile : ScriptableObject
    {
        public SunSettings sun = new SunSettings
        {
            enable = true,
            sunDirection = 180f,
            sunEquator = 90f,
            moonDirection = 180f,
            moonEquator = 90f,
            timeline = 9f,
            sunColor = Color.white,
            sunIntensity = 1f,
            sunInDirectionIntensity = 1f,
            charactorLightColor0 = Color.white,
            charactorLightIntensity0 = 1f,
            charactorLightColor1 = Color.white,
            charactorLightIntensity1 = 0.5f,
#if TEMPLY_COMMENT
            // ProFlare Begin
            proFlareAsset = null,
            GlobalScale = 100,
            MultiplyScaleByTransformScale = false,
            GlobalBrightness = 1,
            GlobalTintColor = Color.white,
            // ProFlare End
#endif

            bakedLighterStength = 1.0f,
            bakedEnvGIStrength = 1.0f,
            shadowStrength = 1.0f,
        };

        public AmbientSettings ambient = new AmbientSettings
        {
            enable = true,
            source = AmbientSettings.kAmbientSourceType.Skybox,
            skyColor = new Color(0.212f, 0.227f, 0.259f, 1f),
            equatorColor = new Color(0.114f, 0.125f, 0.133f, 1f),
            groundColor = new Color(0.047f, 0.043f, 0.035f, 1f),
            intensity = 1f,
            reflectionIntensity = 1f,
            CharacterAmbient = false
        };

        public AmbientSettings ambientCharacter = new AmbientSettings
        {
            source = AmbientSettings.kAmbientSourceType.Skybox,
            skyColor = new Color(0.212f, 0.227f, 0.259f, 1f),
            equatorColor = new Color(0.114f, 0.125f, 0.133f, 1f),
            groundColor = new Color(0.047f, 0.043f, 0.035f, 1f),
            intensity = 1f,
            reflectionIntensity = 1f,
            bUseThisSH = false,
            CharacterAmbient = true
        };

        public SkyBoxSettings skybox = new SkyBoxSettings
        {
            enable = true,
            exposure = 1.0f,
            rotation = 0f,
            isFog = true
            //texture = null
        };

        public SkyBoxSettings prevSkybox;


        public AtmosphericScatteringSettings atmosphericScattering = new AtmosphericScatteringSettings
        {
            enable = true,
            enableSunDisk = true,
            sunIrradiance = new Vector3(25f, 25f, 25f),
            sunDiameter = 80.0f,
            sunBrightness = 2.5f,

            enableMoon = true,
            moonAlbedo = 4f,
            moonContrast = 1f,
            moonDiameter = 100f,
            moonIrradiance = 0.0002f,
            moonLightColor = Color.white,
            moonLightSource = Vector2.zero,

            brightnessPower = 0.25f,
            maxAltitudeKm = 15f,
            maxDistanceKm = 300f,
            rayleigh = new Vector3(0.00712f, 0.01319f, 0.02735f),

            ozoneStrength = 0.05f,
            baseOzone = new Color(15f / 255f, 10f / 255f, 3f / 255f),
            emissivity = 0f,
            planetRadiusKm = 6378f,
            atmosphereThicknessKm = 64f,

            enableStar = true,
            maxStarMagnitude = 4,
            starBrightness = 25,
            starLight = 0.025f,
            enableMilkyWay = true,
            backgroundBrightness = 0f,
            backgroundOffset = 0f,
            backgroundRotation = 0f,

            blendToColours = 0f,
            zenith = Color.black,
            horizon = Color.black,

            haze = 1f,
            hazeBaseKm = 0f,
            hazeScaleKm = 0.7f,
            hazeEccentricity = 0.82f,
            mie = new Vector3(6.11f, 8.18f, 11.70f),
            autoMie = true,

            fogColor = new Color(0.047999f, 0.216f, 0.467999f, 0.238217f),
            fogDensity = 0.0f,
            fogHalfDensityHeight = 1000.0f,
            fogHeightOffset = 0f,
            fogStartDistance = 0f,
            fogRange = 10000f

        };

        public OceanFogSettings oceanFog = new OceanFogSettings
        {
            enable = true,
            oceanFogColor = new Color(0.02f, 0.57f, 0.76f),
            oceanFogColorMultiplier = 0.5f,
            oceanFogDensity = 0.3f
        };

        public Cloud2dSettings cloud2d = new Cloud2dSettings
        {
            enable = true,
            //ambientSource = Cloud2dSettings.AmbientSource.EquatorColor,
            attenuation = 0.6f,
            stepSize = 0.004f,
            alphaSaturation = 2.0f,
            lightColorMultiplier = 4f,
            skyColor = Color.black,
            skyColorMultiplier = 1.5f,
            cloudsDensity = 1.0f,
            scatterMultiplier = 1.0f,
            mappingMode = Cloud2dSettings.MappingMode.Rectangular,
            rotateSpeed = 0.0f,
            heightOffset = 0.0f
        };

        public WeatherSystemSettings weatherSystem = new WeatherSystemSettings
        {
            isRaining = false,
            isFlashLighting = false,
            rainningAmount = 0.5f,
            diffuseDarkening = 0.5f,
            puddleAmount = 5f,
            puddleRipplesAmount = 0.5f,
            puddleRipplesScale = 0.5f,
            nearRainDropIntensity = 5,
            farRainDropIntensity = 5,
            isSnowing = false,
            rpOutDoorStrength = 1.0f,
           

        };

        public CloudShadowSettings cloudShadow = new CloudShadowSettings
        {
            hasCloudShadow = false,
            cloudTiling = new Vector2(0.3f, 0.3f),
            cloudWindSpeed = new Vector2(0.03f, 0.03f),
            cloudFadeOut = 1.0f,
            shadowIntensity = 0.5f,
            cloudTexture = null
        };


        public FogVolumeState fogState = new FogVolumeState
        {
            FogMainColor = new Color(1,0.9019608f,0.9372549f),
            _AmbientColor = new Color(0.6415094f, 0.49703693f, 0.32983267f),
            InscatteringColor = new Color(0.87655747f, 0.8969895f, 0.9245283f),
            LightExtinctionColor = new Color(0.8006408f, 0.97202927f, 0.9811321f),
            PenetrateScale = 2.0f,
            PenetrateMaxDepth = 300.0f,
            //Absorption = 0.52f,
            //HeightAbsorption = 0.88f,

            //InscatteringShape = 0.1f,
            //InscatteringIntensity = 0.807f,
            //InscatteringStartDistance = 0.0f,
            //InscatteringTransitionWideness = 1.0f,
            //_DirectionalLightingDistance = 0.0f,
            //DirectLightingShadowDensity = 1.57f,
            //DirectLightingShadowSteps = 1,
            //Offset = 0.026f,
            //Gamma = 1.0f,
            //NoiseIntensity = 1.0f,
            //Iterations = 268,
            //IterationStep = 380,
            //_OptimizationFactor = 0.000000005f,
            //FadeDistance = 102490.0f,
            //GradMin = 0.88f,
            //GradMax = 0f,
            //GradMin2 = 0.22f,
            //GradMax2 = 0.5f,
            //_3DNoiseScale = 0.09f,
            //Speed = { x = 0, y = 0, z = 40, w = 0 },
            //Stretch = { x = 1, y = 1, z = 1, w = 0 },
            //NoiseContrast = 11.0f,
            //NoiseDensity = 1.3f,
            //Octaves = 3,
            //BaseTiling = 30.0f,
            //_BaseRelativeSpeed = 0.1f,
            //DetailTiling = 24.0f,
            //_DetailRelativeSpeed = 0.39f,
            //DetailDistance = 22515.9f,
            //_NoiseDetailRange = 0.103f,
            //_DetailMaskingThreshold = 18.0f,
            //_Curl = 0.0f,
            //_CumulonimbusIntensity = 1.2f,
            //_CrestaIntensity = 1.2f,

            PreBake_Gammar = 1.78f,
            TintForPreCal = Color.white,
            Velocity = new Vector2(100.0f, 100.0f),
            JitterIntensity = 0.0097f,
            pre_cloud_depth_degeneration_intensity = 4.76f,
            pre_cloud_depth_range = 0.05f,
        };

        public BlackHoleSettings blackHoleSetting = new BlackHoleSettings
        {
            enable = false,
            radius = 300,
            scaleCoef = 1.0f,
            intensity = 1.0f,
            darkIntensity = 0.0f,
            offsetDistance = 3.0f,

        };

        public VolumetricFogSettings volumetricFogSetting = new VolumetricFogSettings
        {
            enable = false,
            scatteringCoef = 0.5f,
            absorptionCoef = 0.5f,
            phaseAnisotropy = 0,
        };

        public void Lerp(EnvironmentProfile right, float t)
        {
            if (right == null)
                return;
            t = Mathf.Clamp01(t);
            sun.LerpUnclamped(ref sun, ref right.sun, t);
            ambient.LerpUnclamped(ref ambient, ref right.ambient, t);
            ambientCharacter.LerpUnclamped(ref ambientCharacter, ref right.ambientCharacter, t);
            prevSkybox.CopyDiffentFrom(ref skybox);
            skybox.LerpUnclamped(ref skybox, ref right.skybox, t);
            atmosphericScattering.LerpUnclamped(ref atmosphericScattering, ref right.atmosphericScattering, t);
            oceanFog.LerpUnclamped(ref oceanFog, ref right.oceanFog, t);
            cloud2d.LerpUnclamped(ref cloud2d, ref right.cloud2d, t);
            weatherSystem.LerpUnclamped(ref weatherSystem, ref right.weatherSystem, t);
            cloudShadow.LerpUnclamped(ref cloudShadow, ref right.cloudShadow, t);
            fogState.LerpUnclamped(ref fogState, ref right.fogState, t);
            blackHoleSetting.LerpUnclamped(ref blackHoleSetting, ref right.blackHoleSetting, t);
            volumetricFogSetting.LerpUnclamped(ref volumetricFogSetting, ref right.volumetricFogSetting, t);
        }

        public void Lerp(EnvironmentProfile left, EnvironmentProfile right, float t)
        {
            if (right == null || left == null)
                return;
            t = Mathf.Clamp01(t);
            sun.LerpUnclamped(ref left.sun, ref right.sun, t);
            ambient.LerpUnclamped(ref left.ambient, ref right.ambient, t);
            ambientCharacter.LerpUnclamped(ref left.ambientCharacter, ref right.ambientCharacter, t);

            prevSkybox.CopyDiffentFrom(ref left.skybox);
            skybox.LerpUnclamped(ref left.skybox, ref right.skybox, t);
            atmosphericScattering.LerpUnclamped(ref left.atmosphericScattering, ref right.atmosphericScattering, t);
            oceanFog.LerpUnclamped(ref left.oceanFog, ref right.oceanFog, t);
            cloud2d.LerpUnclamped(ref left.cloud2d, ref right.cloud2d, t);
            weatherSystem.LerpUnclamped(ref left.weatherSystem, ref right.weatherSystem, t);
            cloudShadow.LerpUnclamped(ref left.cloudShadow, ref right.cloudShadow, t);
            fogState.LerpUnclamped(ref left.fogState, ref right.fogState, t);
            blackHoleSetting.LerpUnclamped(ref left.blackHoleSetting, ref right.blackHoleSetting, t);
            volumetricFogSetting.LerpUnclamped(ref left.volumetricFogSetting, ref right.volumetricFogSetting, t);
        }

        public void CopyFrom(EnvironmentProfile other)
        {
            if (other == null)
                return;
            sun = other.sun;
            //ambient = other.ambient;
            //ambient.CopySHData(other.ambient);
            //ambient.SetLightProbeFromData();
            ambient.DeepClone(ref other.ambient);
            ambientCharacter.DeepClone(ref other.ambientCharacter);
            skybox = other.skybox;
            atmosphericScattering = other.atmosphericScattering;
            oceanFog = other.oceanFog;
            cloud2d = other.cloud2d;
            weatherSystem = other.weatherSystem;
            cloudShadow = other.cloudShadow;
            fogState = other.fogState;
            blackHoleSetting = other.blackHoleSetting;
            volumetricFogSetting = other.volumetricFogSetting;
        }

        //public AtmosphereSettings atmosphere = new AtmosphereSettings
        //{
        //    scatterIntensity = 1,
        //    scatterExtinction = 0
        //};
        public void CheckTextureUsing()
        {
            skybox.SkyTexture.CheckIfNeedUnloadTex();
        }
    }

}
