using UnityEngine; using FogVolumeUtilities; [ExecuteInEditMode] public class FogVolumeScreen : MonoBehaviour { [Header("Scene blur")] [Range(1, 8)] public int Downsample = 8; [SerializeField] [Range(.001f, 15)] float _Falloff = 1; public int screenX { get { return SceneCamera.pixelWidth; } } float FOV_compensation = 0; public int screenY { get { return SceneCamera.pixelHeight; } } Shader _BlurShader = null; Camera UniformFogCamera; GameObject UniformFogCameraGO; [HideInInspector] public Camera SceneCamera; //[SerializeField] RenderTexture RT_FogVolumeConvolution; // [SerializeField] RenderTextureFormat RT_Format; [HideInInspector] public int FogVolumeLayer = -1; [SerializeField] [HideInInspector] string _FogVolumeLayerName = "FogVolumeUniform"; public string FogVolumeLayerName { get { return _FogVolumeLayerName; } set { if (_FogVolumeLayerName != value) SetFogVolumeLayer(value); } } void SetFogVolumeLayer(string NewFogVolumeLayerName) { _FogVolumeLayerName = NewFogVolumeLayerName; FogVolumeLayer = LayerMask.NameToLayer(_FogVolumeLayerName); } void OnValidate() { SetFogVolumeLayer(_FogVolumeLayerName); } Material _BlurMaterial = null; Material BlurMaterial { get { if (_BlurMaterial == null) { _BlurMaterial = new Material(_BlurShader); _BlurMaterial.hideFlags = HideFlags.HideAndDontSave; } return _BlurMaterial; } } [Range(0, 10)] public int iterations = 3; // [Range(0, 1)] // public float _Dither = .8f; [Range(0.0f, 1.0f)] public float blurSpread = 0.6f; // [Range(0, 1)] // public float ImageDistortion = 0; //BLOOM stuff public enum BlurType { Standard = 0, Sgx = 1, } [Header("Bloom")] [Range(1, 5)] public int _BloomDowsample = 8; [Range(0.0f, 1.5f)] public float threshold = 0.35f; [Range(0.0f, 10)] public float intensity = 2.5f; [Range(0, 1)] public float _Saturation = 1; [Range(0, 5f)] public float blurSize = 1; [Range(1, 10)] public int blurIterations = 4; BlurType blurType = BlurType.Standard; Shader fastBloomShader = null; Material _fastBloomMaterial = null; Material fastBloomMaterial { get { if (_fastBloomMaterial == null) { _fastBloomMaterial = new Material(fastBloomShader); _fastBloomMaterial.hideFlags = HideFlags.HideAndDontSave; } return _fastBloomMaterial; } } void CreateUniformFogCamera() { UniformFogCameraGO = GameObject.Find("Uniform Fog Volume Camera"); if (UniformFogCameraGO == null) { UniformFogCameraGO = new GameObject(); UniformFogCameraGO.name = "Uniform Fog Volume Camera"; if (UniformFogCamera == null) UniformFogCamera = UniformFogCameraGO.AddComponent(); UniformFogCamera.backgroundColor = new Color(0, 0, 0, 0); UniformFogCamera.clearFlags = CameraClearFlags.SolidColor; UniformFogCamera.renderingPath = RenderingPath.Forward; UniformFogCamera.enabled = false; UniformFogCamera.farClipPlane = SceneCamera.farClipPlane; #if UNITY_5_6_OR_NEWER UniformFogCamera.GetComponent().allowMSAA = false; #endif } else { UniformFogCamera = UniformFogCameraGO.GetComponent(); } //UniformFogCameraGO.hideFlags = HideFlags.None; UniformFogCameraGO.hideFlags = HideFlags.HideInHierarchy; initFOV = SceneCamera.fieldOfView; } float initFOV; void OnEnable() { SceneCamera = gameObject.GetComponent(); _BlurShader = Shader.Find("Hidden/FogVolumeDensityFilter"); if (_BlurShader == null) print("Hidden/FogVolumeDensityFilter #SHADER ERROR#"); fastBloomShader = Shader.Find("Hidden/FogVolumeBloom"); if (fastBloomShader == null) print("Hidden/FogVolumeBloom #SHADER ERROR#"); CreateUniformFogCamera(); } protected void OnDisable() { if (_BlurMaterial) { DestroyImmediate(_BlurMaterial); } if (_fastBloomMaterial) { DestroyImmediate(_fastBloomMaterial); } //3.2.1 lets destroy it if (UniformFogCameraGO) DestroyImmediate(UniformFogCameraGO); } public void FourTapCone(RenderTexture source, RenderTexture dest, int iteration) { float off = 0.5f + iteration * blurSpread; Graphics.BlitMultiTap(source, dest, BlurMaterial, new Vector2(-off, -off), new Vector2(-off, off), new Vector2(off, off), new Vector2(off, -off) ); } // Downsamples the texture to a quarter resolution. private void DownSample4x(RenderTexture source, RenderTexture dest) { float off = 1.0f; Graphics.BlitMultiTap(source, dest, BlurMaterial, new Vector2(-off, -off), new Vector2(-off, off), new Vector2(off, off), new Vector2(off, -off) ); } public RenderTextureFormat GetRTFormat() { #if UNITY_5_6_OR_NEWER RT_Format=(SceneCamera.allowHDR == true) ? RenderTextureFormat.DefaultHDR : RenderTextureFormat.Default; return RT_Format; #else RT_Format = (SceneCamera.hdr == true) ? RenderTextureFormat.DefaultHDR : RenderTextureFormat.ARGBHalf; return RT_Format; #endif //return RT_Format; } public void ReleaseRT(RenderTexture rt) { if (rt != null) { RenderTexture.ReleaseTemporary(rt); rt = null; } } public RenderTextureReadWrite GetRTReadWrite() { //return RenderTextureReadWrite.Default; #if UNITY_5_6_OR_NEWER return (SceneCamera.allowHDR) ? RenderTextureReadWrite.Default : RenderTextureReadWrite.Linear; #else return (SceneCamera.hdr) ? RenderTextureReadWrite.Default : RenderTextureReadWrite.Linear; #endif } protected void GetRT(ref RenderTexture rt, int2 size, string name) { // Release existing one ReleaseRT(rt); rt = RenderTexture.GetTemporary(size.x, size.y, 0, GetRTFormat(), GetRTReadWrite()); rt.filterMode = FilterMode.Bilinear; rt.name = name; rt.wrapMode = TextureWrapMode.Repeat; } public void ConvolveFogVolume() { if (UniformFogCameraGO == null) CreateUniformFogCamera(); int2 resolution = new int2(screenX, screenY); UniformFogCamera.projectionMatrix = SceneCamera.projectionMatrix; UniformFogCamera.transform.position = SceneCamera.transform.position; UniformFogCamera.transform.rotation = SceneCamera.transform.rotation; GetRT(ref RT_FogVolumeConvolution, resolution, "RT_FogVolumeConvolution"); UniformFogCamera.targetTexture = RT_FogVolumeConvolution; UniformFogCamera.Render(); Shader.SetGlobalTexture("RT_FogVolumeConvolution", RT_FogVolumeConvolution); } public bool SceneBloom = false; #region instance private static FogVolumeScreen _instance; public static FogVolumeScreen instance { get { if (_instance == null) { _instance = FindObjectOfType(); } return _instance; } } #endregion RenderTexture _source; void OnRenderImage(RenderTexture source, RenderTexture destination) { ConvolveFogVolume(); GetRT(ref _source, new int2(Screen.width, Screen.height), "_source"); Graphics.Blit(source, _source); fastBloomMaterial.SetTexture("_source", _source); BlurMaterial.SetTexture("_source", _source); //Graphics.Blit(_source, destination, BlurMaterial); // RT_Format = source.format; #region Density convolution UniformFogCamera.cullingMask = 1 << instance.FogVolumeLayer; //UniformFogCamera.cullingMask |= 1 << LayerMask.NameToLayer("FogVolumeUniform");//add Fog volume uniforms FOV_compensation = initFOV / SceneCamera.fieldOfView; Shader.SetGlobalFloat("FOV_compensation", FOV_compensation); fastBloomMaterial.SetFloat("_Falloff", _Falloff); // BlurMaterial.SetFloat("_Dither", _Dither); // BlurMaterial.SetFloat("_Distortion", ImageDistortion * -.08f); RenderTexture RT_DensityBlur = RenderTexture.GetTemporary(screenX / Downsample, screenY / Downsample, 0, RT_Format); DownSample4x(source, RT_DensityBlur); for (int i = 0; i < iterations; i++) { RenderTexture RT_DensityBlur2 = RenderTexture.GetTemporary(screenX / Downsample, screenY / Downsample, 0, RT_Format); FourTapCone(RT_DensityBlur, RT_DensityBlur2, i); RenderTexture.ReleaseTemporary(RT_DensityBlur); RT_DensityBlur = RT_DensityBlur2; } // Graphics.Blit(RT_DensityBlur, destination); #endregion #region Bloom if (intensity > 0) { Rendering.EnsureKeyword(fastBloomMaterial, "BLOOM", true); float widthMod = 2.0f / (float)_BloomDowsample; fastBloomMaterial.SetFloat("_Saturation", _Saturation); fastBloomMaterial.SetVector("_Parameter", new Vector4(blurSize * widthMod, 0.0f, threshold, intensity)); var rtW = source.width / _BloomDowsample; var rtH = source.height / _BloomDowsample; // downsample RenderTexture rt = RenderTexture.GetTemporary(rtW, rtH, 0, RT_Format); rt.filterMode = FilterMode.Bilinear; if (SceneBloom) Graphics.Blit(source, rt, fastBloomMaterial, 1); else Graphics.Blit(RT_DensityBlur, rt, fastBloomMaterial, 1); var passOffs = blurType == BlurType.Standard ? 0 : 2; for (int i = 1; i < blurIterations; i++) { fastBloomMaterial.SetVector("_Parameter", new Vector4(blurSize * widthMod + (i * 1.0f), 0.0f, threshold, intensity)); // vertical blur RenderTexture rt2 = RenderTexture.GetTemporary(rtW, rtH, 0, RT_Format); rt2.filterMode = FilterMode.Bilinear; Graphics.Blit(rt, rt2, fastBloomMaterial, 2 + passOffs); RenderTexture.ReleaseTemporary(rt); rt = rt2; // horizontal blur rt2 = RenderTexture.GetTemporary(rtW, rtH, 0, RT_Format); rt2.filterMode = FilterMode.Bilinear; Graphics.Blit(rt, rt2, fastBloomMaterial, 3 + passOffs); RenderTexture.ReleaseTemporary(rt); rt = rt2; } fastBloomMaterial.SetTexture("_Bloom", rt); RenderTexture.ReleaseTemporary(rt); } else Rendering.EnsureKeyword(fastBloomMaterial, "BLOOM", false); #endregion Graphics.Blit(RT_DensityBlur, destination, fastBloomMaterial, 0); RenderTexture.ReleaseTemporary(RT_DensityBlur); } }