| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224 | using System.Collections;using System.Collections.Generic;#if UNITY_EDITORusing UnityEditor;using UnityEditor.SceneManagement;#endifusing UnityEngine;namespace FXV{    [ExecuteInEditMode]    public class VolumeFog : MonoBehaviour    {        static bool XR_ENABLED = false;                public static void SetEnabledXR(bool enabled)        {            XR_ENABLED = enabled;        }        public enum FogType        {            ViewAligned = 0,            SphericalPos = 1,            SphericalDist = 2,            InvertedSpherical = 8,            InvertedSphericalXHeight = 11,            BoxPos = 3,            BoxDist = 4,            BoxExperimental = 5,            Height = 6,            HeightXBox = 7,            HeightXView = 9,            BoxXView = 10,        };        public enum FogClipping        {            None = 0,            ClipToSkybox = 1,            ClipToBounds = 2        }        public enum FogBlendMode        {            AlphaBlend,            Add        }        public enum FogMeshType        {            Default = 0,            Custom        }        public enum FogFallof        {            Linear = 0,            Smoothed,            Exp,            Exp2        }        public enum FogFunction        {            Default = 0,            Alternative        }        public enum FogRenderMode        {            Simplified = 0,            Default        }        [SerializeField]        FogType fogType = FogType.ViewAligned;        [SerializeField]        float fogMin = 0.0f;        [SerializeField]        float fogMax = 1.0f;        [SerializeField]        float _fogDepth = 1.0f;        public float FogMin        {            get            {                return fogMin;            }            set            {                fogMin = value;                _fogDepth = fogMax - fogMin;                isPropsDirty = true;            }        }        public float FogMax        {            get            {                return fogMax;            }            set            {                fogMax = value;                _fogDepth = fogMax - fogMin;                isPropsDirty = true;            }        }        public float FogDepth        {            get            {                return fogMax - fogMin;            }            set            {                _fogDepth = value;                fogMin = fogMax - value;                isPropsDirty = true;            }        }        [SerializeField]        float secFogMin = 0.0f;        [SerializeField]        float secFogMax = 1.0f;        [SerializeField]        Vector3 worldSize = Vector3.one;        [SerializeField]        FogFallof fogFalloffType = FogFallof.Linear;        [SerializeField, Range(0.5f, 15.0f)]        float fogFalloffCurve = 1.0f;        //[SerializeField]        //int renderQueue = 3100;        [SerializeField, FXV.Internal.fxvSortingLayerAttribute]        string sortingLayer = "Default";        [SerializeField]        int sortingOrder = 0;        [SerializeField]        uint renderingLayerMask = 0xffffffff;        [SerializeField]        Color fogColor = Color.white;        [SerializeField]        FogBlendMode blendType = FogBlendMode.AlphaBlend;        [SerializeField]        FogMeshType fogMeshType = FogMeshType.Default;        [SerializeField]        Mesh customMesh = null;        [SerializeField]        FogClipping fogClipping = FogClipping.None;        [SerializeField]        FogRenderMode renderMode = FogRenderMode.Default;        [SerializeField]        bool affectedByLights = false;        [SerializeField, Range(0.1f, 2.0f)]        float lightScatteringFactor = 1.0f;        [SerializeField, Range(0.0f, 1.0f)]        float lightReflectivity = 1.0f;        [SerializeField, Range(0.0f, 1.0f)]        float lightTransmission = 0.5f;        VolumeFogGroup fogGroup = null;        Renderer myRenderer = null;        MeshFilter myFilter = null;        MaterialPropertyBlock props = null;        bool isPropsDirty = true;        Mesh plane = null;        Mesh renderMesh = null;        bool renderMeshIsProcedural = false;        Bounds rendererLocalBounds;        Transform myTransform;        Vector3 myPosition;        Vector3 boundsOffset = Vector3.zero;        float globalScaleFactor = 1.0f;        private void Start()        {            SetupComponents();            if (myTransform == null)            {                myTransform = transform;                myPosition = transform.position;            }            PrepareFogObject();            myRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;            Material mat = GetCachedMaterial(this);            if (myRenderer.sharedMaterial != mat)            {                myRenderer.sharedMaterial = mat;            }            rendererLocalBounds = myRenderer.localBounds;            Camera.onPostRender += CameraFinishedRendering;        }        void SetupComponents()        {            if (myFilter == null)            {                myFilter = GetComponent<MeshFilter>();                if (myFilter == null)                {                    myFilter = gameObject.AddComponent<MeshFilter>();                }                myFilter.hideFlags = HideFlags.HideInInspector;            }            if (myRenderer == null)            {                myRenderer = GetComponent<Renderer>();                if (myRenderer == null)                {                    myRenderer = gameObject.AddComponent<MeshRenderer>();                }                myRenderer.hideFlags = HideFlags.HideInInspector;            }        }        internal void DestroyAsset(Object assetObject)        {#if UNITY_EDITOR            if (!Application.isPlaying)            {                DestroyImmediate(assetObject);            }            else#endif            {                Destroy(assetObject);            }        }        internal void PrepareFogObject()        {            if (IsUsingDepthWorkflow())            {                FogDepth = _fogDepth;            }            else            {                FogDepth = fogMax - fogMin;            }            if (fogGroup != null)            {                VolumeFogGroup parentGroup = GetComponentInParent<VolumeFogGroup>();                if (parentGroup == null)                {                    TryUnegisterFromGroup();                }                else if (parentGroup != fogGroup)                {                    TryUnegisterFromGroup();                    TryRegisterInGroup();                }            }            SetupComponents();            Material mat = GetCachedMaterial(this);            if (myRenderer.sharedMaterial != mat)            {                myRenderer.sharedMaterial = mat;            }            if (myTransform == null)            {                myTransform = transform;            }            myPosition = myTransform.position;            UpdateScale();            if (props == null)            {                CreateMaterialProps();            }            else            {                UpdateMaterialProps();            }#if UNITY_EDITOR            UnityEditor.EditorApplication.delayCall += _DelayedValidate;#else            _DelayedValidate();#endif        }        private void OnValidate()        {            PrepareFogObject();            UpdateScale();        }        internal void _DelayedValidate()        {            UpdateRenderMesh();        }        public bool IsCustomMesh()        {            return fogMeshType == FogMeshType.Custom;        }        public bool IsUsingDepthWorkflow()        {            return (fogType == FogType.InvertedSpherical) || fogType == FogType.InvertedSphericalXHeight;        }        public bool IsSphereShape()        {            return (fogType == FogType.SphericalPos || fogType == FogType.SphericalDist);        }        public bool IsBoxShape()        {            return !IsSphereShape();        }        public bool IsUsingSecondaryParams()        {            return fogType == FogType.HeightXBox || fogType == FogType.HeightXView || fogType == FogType.BoxXView || fogType == FogType.InvertedSphericalXHeight;        }        internal void UpdateRenderMesh()        {            if (this == null)            {                return;            }            if (myFilter == null)            {                myFilter = GetComponent<MeshFilter>();            }            if (renderMesh != null && renderMeshIsProcedural)            {                DestroyAsset(renderMesh);                renderMeshIsProcedural = false;            }            if (IsCustomMesh())            {                myFilter.sharedMesh = customMesh;                renderMesh = customMesh;                worldSize = myRenderer.localBounds.size;                boundsOffset = myRenderer.localBounds.center;                UpdateMaterialProps();            }            else            {                if (IsSphereShape())                {                    renderMesh = Resources.GetBuiltinResource<Mesh>("New-Sphere.fbx");                    myFilter.sharedMesh = renderMesh;                }                else if (IsBoxShape())                {                    renderMesh = Resources.GetBuiltinResource<Mesh>("Cube.fbx");                    myFilter.sharedMesh = renderMesh;                }                else                {                    InitializeBoxRenderMesh();                    myFilter.sharedMesh = renderMesh;                }                boundsOffset = Vector3.zero;            }            rendererLocalBounds = myRenderer.localBounds;        }        internal void UpdateGlobalScaleFactor()        {            Vector3 parentScale = (transform.parent != null) ? transform.parent.lossyScale : Vector3.one;            float maxScale = Mathf.Max(Mathf.Max(parentScale.x, parentScale.y), parentScale.z);            float minScale = Mathf.Min(Mathf.Min(parentScale.x, parentScale.y), parentScale.z);            globalScaleFactor = (minScale + (maxScale - minScale) * 0.5f);        }        internal void UpdateScale()        {            UpdateGlobalScaleFactor();            if (IsCustomMesh())            {                transform.localScale = Vector3.one;                // lock scale for custom mesh            }            else            {                if (IsSphereShape())                {                    transform.localScale = Vector3.one * Mathf.Max(fogMin, fogMax) * 2.0f;                }                else if (IsBoxShape())                {                    transform.localScale = worldSize;                }                else                {                    transform.localScale = Vector3.one;                }            }        }        internal void UpdateTransformScaleChanges()        {            if (IsCustomMesh())            {                transform.localScale = Vector3.one;                // lock scale for custom mesh            }            else            {                if (IsSphereShape())                {                    float currentScale = Mathf.Max(fogMin, fogMax) * 2.0f;                    bool changed = false;                    float r = fogMin / fogMax;                    if (transform.localScale.x != currentScale)                    {                         fogMax = transform.localScale.x * 0.5f;                        transform.localScale = Vector3.one * transform.localScale.x;                        changed = true;                    }                    if (transform.localScale.y != currentScale)                    {                        fogMax = transform.localScale.y * 0.5f;                        transform.localScale = Vector3.one * transform.localScale.y;                        changed = true;                    }                    if (transform.localScale.z != currentScale)                    {                        fogMax = transform.localScale.z * 0.5f;                        transform.localScale = Vector3.one * transform.localScale.z;                        changed = true;                    }                    if (changed)                    {                        fogMin = r * fogMax;                        UpdateGlobalScaleFactor();                        UpdateMaterialProps();                    }                }                else if (IsBoxShape())                {                    if (worldSize != transform.localScale)                    {                        worldSize = transform.localScale;                        UpdateGlobalScaleFactor();                        UpdateMaterialProps();                    }                }                else                {                    transform.localScale = Vector3.one;                }            }        }        internal void CreateMaterialProps()        {            props = new MaterialPropertyBlock();            UpdateMaterialProps();        }        internal void UpdateMaterialProps()        {            props.SetColor("_Color", GetFogColor());            props.SetVector("_WorldSize", worldSize * globalScaleFactor);            if (IsCustomMesh())            {                props.SetVector("_LocalSize", worldSize); //worldSize stores local bounds size for custom mesh                props.SetVector("_LocalOffset", boundsOffset);            }            props.SetFloat("_FogMin", fogMin * globalScaleFactor);            props.SetFloat("_FogMax", fogMax * globalScaleFactor);            props.SetFloat("_FogFalloff", GetFogFalloffParam());            if (IsUsingSecondaryParams())            {                props.SetFloat("_SecFogMin", secFogMin * globalScaleFactor);                props.SetFloat("_SecFogMax", secFogMax * globalScaleFactor);            }            if (IsAffectedByLights())            {                props.SetFloat("_LightScatteringFactor", GetLightScatteringFactor());                props.SetFloat("_LightReflectivity", GetLightReflectivity());                props.SetFloat("_LightTransmission", GetLightTransmission());            }            isPropsDirty = true;        }        internal void TryRegisterInGroup()        {            if (fogGroup == null)            {                fogGroup = GetComponentInParent<VolumeFogGroup>();                if (fogGroup)                {                    fogGroup.RegisterFogObject(this);                }            }        }        internal void TryUnegisterFromGroup()        {            if (fogGroup)            {                fogGroup.UnregisterFogObject(this);                fogGroup = null;            }        }        private void OnEnable()        {            SetupComponents();            TryRegisterInGroup();            myRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;            Camera.onPostRender -= CameraFinishedRendering;            Camera.onPostRender += CameraFinishedRendering;            if (props == null)            {                CreateMaterialProps();            }            else            {                UpdateMaterialProps();            }        }        private void OnDisable()        {            TryUnegisterFromGroup();            Camera.onPostRender -= CameraFinishedRendering;        }        void OnDestroy()        {            if (plane)            {                DestroyAsset(plane);                plane = null;            }            if (renderMesh != null && renderMeshIsProcedural)            {                DestroyAsset(renderMesh);                renderMeshIsProcedural = false;            }            if (fogGroup)            {                fogGroup.UnregisterFogObject(this);                fogGroup = null;            }            props = null;            myRenderer = null;            Camera.onPostRender -= CameraFinishedRendering;        }        public void OnDidApplyAnimationProperties()        {            if (props != null)            {                UpdateMaterialProps();            }        }        private void OnTransformParentChanged()        {            if (props == null)            {                return;            }            UpdateScale();            UpdateMaterialProps();        }        private void Update()        {        }        internal bool RenderCameraPlane(Camera camera)        {            if (IsSphereShape())            {                //TODO: optimize this                float nearOffset = camera.nearClipPlane / Mathf.Cos(camera.fieldOfView * 0.5f * Mathf.Deg2Rad);                float radius = Mathf.Max(fogMin, fogMax) * globalScaleFactor + nearOffset;                Vector3 distVec = transform.position - camera.transform.position;                if (distVec.sqrMagnitude < radius * radius)                {                    return true;                }            }            else            {                Bounds b = myRenderer.bounds;                b.extents += Vector3.one * (camera.nearClipPlane / Mathf.Cos(camera.fieldOfView * 0.5f * Mathf.Deg2Rad));                return b.Contains(camera.transform.position);            }            return false;        }        private void LateUpdate()        {            UpdateParams();        }        private void OnWillRenderObject()        {            UpdateParams();            if (!Application.isPlaying)            {                UpdateTransformScaleChanges();            }            Camera camera = VolumeFogManager.instance.GetCurrentRenderingCamera();            if (camera)            {                if ((camera.depthTextureMode & DepthTextureMode.Depth) == 0)                {                    camera.depthTextureMode |= DepthTextureMode.Depth;                }                if (RenderCameraPlane(camera))                {                    if (props == null)                    {                        CreateMaterialProps();                    }                    if (plane == null)                    {                        InitializeCameraMesh();                    }                    UpdateMesh(camera);                    myFilter.sharedMesh = plane;                }                else                {                    myFilter.sharedMesh = renderMesh;                }            }        }        private void CameraFinishedRendering(Camera cam)        {        }        void InitializeBoxRenderMesh()        {            Vector3 extents = worldSize * 0.5f;            renderMesh = new Mesh();            renderMesh.name = "ProceduralBox_" + worldSize.x + "_" + worldSize.y + "_" + worldSize.z;            Vector3[] c = new Vector3[8];            c[0] = new Vector3(-extents.x, -extents.y, extents.z);            c[1] = new Vector3(extents.x, -extents.y, extents.z);            c[2] = new Vector3(extents.x, -extents.y, -extents.z);            c[3] = new Vector3(-extents.x, -extents.y, -extents.z);            c[4] = new Vector3(-extents.x, extents.y, extents.z);            c[5] = new Vector3(extents.x, extents.y, extents.z);            c[6] = new Vector3(extents.x, extents.y, -extents.z);            c[7] = new Vector3(-extents.x, extents.y, -extents.z);            Vector3[] vertices = new Vector3[24]            {                c[0], c[1], c[2], c[3], // Bottom	            c[7], c[4], c[0], c[3], // Left	            c[4], c[5], c[1], c[0], // Front	            c[6], c[7], c[3], c[2], // Back	            c[5], c[6], c[2], c[1], // Right	            c[7], c[6], c[5], c[4]  // Top            };            renderMesh.vertices = vertices;            int[] tris = new int[]            {                3, 1, 0,        3, 2, 1,        // Bottom		            7, 5, 4,        7, 6, 5,        // Left	            11, 9, 8,       11, 10, 9,      // Front	            15, 13, 12,     15, 14, 13,     // Back	            19, 17, 16,     19, 18, 17,	    // Right	            23, 21, 20,     23, 22, 21,     // Top            };            renderMesh.triangles = tris;            Vector3 up = Vector3.up;            Vector3 down = Vector3.down;            Vector3 forward = Vector3.forward;            Vector3 back = Vector3.back;            Vector3 left = Vector3.left;            Vector3 right = Vector3.right;            Vector3[] normals = new Vector3[]            {                down, down, down, down,             // Bottom	            left, left, left, left,             // Left	            forward, forward, forward, forward,	// Front	            back, back, back, back,             // Back	            right, right, right, right,         // Right	            up, up, up, up                      // Top            };            renderMesh.normals = normals;            Vector2 uv00 = new Vector2(0f, 0f);            Vector2 uv10 = new Vector2(1f, 0f);            Vector2 uv01 = new Vector2(0f, 1f);            Vector2 uv11 = new Vector2(1f, 1f);            Vector2[] uv = new Vector2[]            {                uv11, uv01, uv00, uv10, // Bottom	            uv11, uv01, uv00, uv10, // Left	            uv11, uv01, uv00, uv10, // Front	            uv11, uv01, uv00, uv10, // Back	        	            uv11, uv01, uv00, uv10, // Right 	            uv11, uv01, uv00, uv10  // Top            };            renderMesh.uv = uv;            renderMesh.RecalculateBounds();            renderMesh.Optimize();            renderMesh.MarkDynamic();            renderMeshIsProcedural = true;        }        void UpdateBoxRenderMesh()        {            Vector3 extents = worldSize * 0.5f;            Vector3[] c = new Vector3[8];            c[0] = new Vector3(-extents.x, -extents.y, extents.z);            c[1] = new Vector3(extents.x, -extents.y, extents.z);            c[2] = new Vector3(extents.x, -extents.y, -extents.z);            c[3] = new Vector3(-extents.x, -extents.y, -extents.z);            c[4] = new Vector3(-extents.x, extents.y, extents.z);            c[5] = new Vector3(extents.x, extents.y, extents.z);            c[6] = new Vector3(extents.x, extents.y, -extents.z);            c[7] = new Vector3(-extents.x, extents.y, -extents.z);            Vector3[] vertices = new Vector3[24]            {                c[0], c[1], c[2], c[3], // Bottom	            c[7], c[4], c[0], c[3], // Left	            c[4], c[5], c[1], c[0], // Front	            c[6], c[7], c[3], c[2], // Back	            c[5], c[6], c[2], c[1], // Right	            c[7], c[6], c[5], c[4]  // Top            };            renderMesh.vertices = vertices;        }        void InitializeCameraMesh()        {            plane = new Mesh();            Vector3[] vertices = new Vector3[4]            {                new Vector3(-1.0f, -1.0f, 0),                new Vector3(1.0f, -1.0f, 0),                new Vector3(-1.0f, 1.0f, 0),                new Vector3(1.0f, 1.0f, 0)            };            plane.vertices = vertices;            int[] tris = new int[6]            {                // lower left triangle                0, 2, 1,                // upper right triangle                2, 3, 1            };            plane.triangles = tris;            Vector3[] normals = new Vector3[4]            {                -Vector3.forward,                -Vector3.forward,                -Vector3.forward,                -Vector3.forward            };            plane.normals = normals;            Vector2[] uv = new Vector2[4]            {                        new Vector2(0, 0),                        new Vector2(1, 0),                        new Vector2(0, 1),                        new Vector2(1, 1)            };            plane.uv = uv;            plane.bounds = rendererLocalBounds;            plane.MarkDynamic();        }        void UpdateMesh(Camera camera)        {            float zOffset = 0.001f;            Vector3[] vertices = null;            float stereoSeparationX = (camera.stereoEnabled || XR_ENABLED) ? 3.0f : 0.2f;            float stereoSeparationY = (camera.stereoEnabled || XR_ENABLED) ? 1.0f : 0.2f;            vertices = new Vector3[4]            {                camera.ViewportToWorldPoint( new Vector3(-stereoSeparationX, -stereoSeparationY, camera.nearClipPlane + zOffset) ),                camera.ViewportToWorldPoint( new Vector3(1.0f + stereoSeparationX, -stereoSeparationY, camera.nearClipPlane + zOffset) ),                camera.ViewportToWorldPoint( new Vector3(-stereoSeparationX, 1.0f + stereoSeparationY, camera.nearClipPlane + zOffset) ),                camera.ViewportToWorldPoint( new Vector3(1.0f+stereoSeparationX, 1.0f + stereoSeparationY, camera.nearClipPlane + zOffset) )            };            vertices[0] = transform.InverseTransformPoint(vertices[0]);            vertices[1] = transform.InverseTransformPoint(vertices[1]);            vertices[2] = transform.InverseTransformPoint(vertices[2]);            vertices[3] = transform.InverseTransformPoint(vertices[3]);            plane.vertices = vertices;            plane.bounds = rendererLocalBounds;        }        public void SetFogColor(Color color)        {            if (fogGroup != null && fogGroup.controlsColor)            {                Debug.LogWarning("Setting color for fog object that is controlled by group - this will not take effect");            }            fogColor = color;            props.SetColor("_Color", GetFogColor());            isPropsDirty = true;        }        public FogType GetFogType()        {            return fogType;        }        public float GetFogFalloffParam()        {            return fogGroup != null && fogGroup.controlsFalloffParam ? Mathf.Clamp(fogFalloffCurve * fogGroup.falloffParamMultiplier, 0.5f, 15.0f) : fogFalloffCurve;        }        public Vector3 GetFogBoxSize()        {            return worldSize;        }        public void SetFogBoxSize(Vector3 size)        {            worldSize = size;        }        public Color GetFogColor()        {            return fogGroup != null && fogGroup.controlsColor ? fogGroup.fogColor : fogColor;        }        public VolumeFogGroup GetParentFogGroup()        {            return fogGroup;        }        public void SetAffectedByLights(bool affected)        {            if (fogGroup != null && fogGroup.controlsLighting)            {                Debug.LogWarning("Setting affected by lights for fog object that is controlled by group - this will not take effect");            }            affectedByLights = affected;            Material mat = GetCachedMaterial(this);            if (myRenderer.sharedMaterial != mat)            {                myRenderer.sharedMaterial = mat;            }            UpdateMaterialProps();        }        public bool IsAffectedByLights()        {            return fogGroup != null && fogGroup.controlsLighting ? fogGroup.affectedByLights : affectedByLights;        }        public float GetLightScatteringFactor()        {            return fogGroup != null && fogGroup.controlsLighting ? fogGroup.lightScatteringFactor : lightScatteringFactor;        }        public float GetLightReflectivity()        {            return fogGroup != null && fogGroup.controlsLighting ? fogGroup.lightReflectivity : lightReflectivity;        }        public float GetLightTransmission()        {            return fogGroup != null && fogGroup.controlsLighting ? fogGroup.lightTransmission : lightTransmission;        }        void UpdateParams()        {            if (isPropsDirty)            {                myRenderer.SetPropertyBlock(props);                myRenderer.sortingLayerName = sortingLayer;                myRenderer.sortingOrder = sortingOrder;                myRenderer.renderingLayerMask = renderingLayerMask;                isPropsDirty = false;            }        }        internal string GetMaterialName()        {            string ret = "VF";            ret += IsAffectedByLights() ? "Lit" : "Unlit";            ret += blendType.ToString();            ret += fogType.ToString();            ret += fogFalloffType.ToString();            ret += renderMode.ToString();            ret += fogMeshType.ToString();            ret += fogClipping.ToString();            if (Internal.fxvFogAssetConfig.ActiveRenderPipeline == Internal.fxvFogAssetConfig.Pipeline.URP)            {                ret += "URP";            }            return ret;        }        internal static Dictionary<string, Material> cachedMaterials = new Dictionary<string, Material> ();        internal static Material GetCachedMaterial(VolumeFog fogObject)        {            string materialKey = fogObject.GetMaterialName();            Material mat = null;            if (cachedMaterials.TryGetValue(materialKey, out mat))            {                if (mat == null)                {                    mat = CreateMaterial(fogObject);                    if (mat)                    {                        cachedMaterials[materialKey] = mat;                    }                }                return mat;            }            string cachePath = "MaterialsCache/" + materialKey;            mat = Resources.Load(cachePath) as Material;            if (mat == null)            {                mat = CreateMaterial(fogObject);                if (mat)                {#if UNITY_EDITOR                    UnityEditor.EditorApplication.delayCall += () =>                    {                        fogObject._DelayedSaveToCache(materialKey, mat);                    };#endif                    cachedMaterials[materialKey] = mat;                }            }            else            {                SetupMaterialKeywords(mat, fogObject);                cachedMaterials[materialKey] = mat;            }            return mat;        }#if UNITY_EDITOR        internal void _DelayedSaveToCache(string materialKey, Material mat)        {            if (mat == null)            {                Debug.Log("Trying to save null material for key " +  materialKey);                return;            }            string saveFolder = Internal.fxvFogAssetConfig.AssetPath + "/Resources/MaterialsCache/";            if (!System.IO.Directory.Exists(saveFolder))            {                System.IO.Directory.CreateDirectory(saveFolder);            }            UnityEditor.AssetDatabase.CreateAsset(mat, saveFolder + materialKey + ".mat");            UnityEditor.AssetDatabase.SaveAssets();            UnityEditor.AssetDatabase.Refresh();        }#endif        internal static void SetupMaterialKeywords(Material mat, VolumeFog fogObject)        {            mat.SetFloat("_FogType", (float)fogObject.fogType);            var types = System.Enum.GetNames(typeof(VolumeFog.FogType));            foreach (string name in types)            {                mat.DisableKeyword("FXV_FOGTYPE_" + name.ToUpper());            }            mat.EnableKeyword("FXV_FOGTYPE_" + fogObject.fogType.ToString().ToUpper());            mat.SetFloat("_FogFalloffType", (float)fogObject.fogFalloffType);            if (fogObject.fogFalloffType == VolumeFog.FogFallof.Linear)            {                mat.EnableKeyword("FXV_LINEAR_FALLOFF");            }            else if (fogObject.fogFalloffType == VolumeFog.FogFallof.Smoothed)            {                mat.EnableKeyword("FXV_SMOOTHED_FALLOFF");            }            else if (fogObject.fogFalloffType == VolumeFog.FogFallof.Exp)            {                mat.EnableKeyword("FXV_EXP_FALLOFF");            }            else if (fogObject.fogFalloffType == VolumeFog.FogFallof.Exp2)            {                mat.EnableKeyword("FXV_EXP2_FALLOFF");            }            mat.SetFloat("_BlendMode", (float)fogObject.blendType);            if (fogObject.blendType == VolumeFog.FogBlendMode.AlphaBlend)            {                mat.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);                mat.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);                mat.SetInt("_ZWrite", 0);            }            else if (fogObject.blendType == VolumeFog.FogBlendMode.Add)            {                mat.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);                mat.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One);                mat.SetInt("_ZWrite", 0);            }            mat.SetFloat("_InAirEnabled", (float)fogObject.renderMode);            if (fogObject.renderMode == FogRenderMode.Default)            {                mat.EnableKeyword("FXV_IN_AIR_FOG");            }            mat.SetFloat("_FogMeshType", (float)fogObject.fogMeshType);            if (fogObject.fogMeshType == FogMeshType.Custom)            {                mat.EnableKeyword("FXV_FOG_CUSTOM_MESH");            }            mat.SetFloat("_FogClipping", (float)fogObject.fogClipping);            if (fogObject.fogClipping == FogClipping.ClipToSkybox)            {                mat.EnableKeyword("FXV_FOG_CLIP_SKYBOX");            }            else if (fogObject.fogClipping == FogClipping.ClipToBounds)            {                mat.EnableKeyword("FXV_FOG_CLIP_BOUNDS");            }            mat.enableInstancing = true;        }        internal static Material CreateMaterial(VolumeFog fogObject)        {            Material mat = null;            string shaderVersion = "";            if (Internal.fxvFogAssetConfig.ActiveRenderPipeline == Internal.fxvFogAssetConfig.Pipeline.URP)            {                shaderVersion += "URP";            }            if (fogObject.IsAffectedByLights())            {                Shader shader = Shader.Find("FXV/FXVVolumeFogLit" + shaderVersion);                if (!shader) //this might happen when render pipeline specific package is not imported                {                    return null;                }                mat = new Material(shader);            }            else            {                mat = new Material(Shader.Find("FXV/FXVVolumeFog"));            }            SetupMaterialKeywords(mat, fogObject);            return mat;        }#if UNITY_EDITOR        public static void SetFogType(VolumeFog fogObject, FogType type)        {            fogObject.fogType = type;            fogObject.PrepareFogObject();        }        public static void UpdateFogType(VolumeFog fogObject)        {            fogObject.UpdateRenderMesh();            fogObject.UpdateScale();        }        public static Material SetupFogMaterial(VolumeFog fogObject)        {            Material mat = GetCachedMaterial(fogObject);            Renderer r = fogObject.GetComponent<Renderer>();            if (r.sharedMaterial != mat)            {                r.sharedMaterial = mat;            }            return mat;        }        private void OnDrawGizmosSelected()        {            Gizmos.color = Color.red;            if (IsBoxShape())            {                 Gizmos.DrawWireCube(transform.position + boundsOffset, worldSize);            }            else            {                Gizmos.DrawWireSphere(transform.position + boundsOffset, fogMax);            }        }#endif    }}
 |