//Based on Unity's GlobalFog. namespace UnityEngine.AzureSky { [ExecuteInEditMode] [ImageEffectAllowedInSceneView] [RequireComponent(typeof(Camera))] [AddComponentMenu("Azure[Sky] Dynamic Skybox/Azure Fog Scattering Renderer")] public sealed class AzureFogScatteringRenderer : MonoBehaviour { #pragma warning disable 0108 // Remove warning caused by obsolete members that do not actually exist /// The reference to the camera that the fog scattering should be rendered. public Camera camera { get => m_camera; set => m_camera = value; } private Camera m_camera = null; #pragma warning restore 0108 /// The material that will render the fog scattering RenderTexture into the screen. public Material fogRendererMaterial { get => m_fogRendererMaterial; set => m_fogRendererMaterial = value; } [SerializeField] private Material m_fogRendererMaterial = null; /// The material that will compute the fog scattering effect and render it into a RenderTexture. public Material fogComputationMaterial { get => m_fogComputationMaterial; set => m_fogComputationMaterial = value; } [SerializeField] private Material m_fogComputationMaterial = null; /// The render texture that stores the fog scattering data. (RGB: Scattering Data), (Alpha: Fog Data). public RenderTexture fogScatteringRT { get => m_fogScatteringRT; set => m_fogScatteringRT = value; } [SerializeField] private RenderTexture m_fogScatteringRT = null; /// The start width resolution of the fog scattering render texture. public int fogRenderTextureWidth => m_fogRenderTextureWidth; [SerializeField] private int m_fogRenderTextureWidth = 1920; /// The start height resolution of the fog scattering render texture. public int fogRenderTextureHeight => m_fogRenderTextureHeight; [SerializeField] private int m_fogRenderTextureHeight = 1080; /// Stores the camera frunstum corners position. private Vector3[] m_frustumCorners = new Vector3[4]; /// The view port rect. private Rect m_viewRect = new Rect(0, 0, 1, 1); /// The camera frustum corners matrix. private Matrix4x4 m_frustumCornersArray = Matrix4x4.identity; private void Start() { m_camera = GetComponent(); SetFogScatteringResolution(m_fogRenderTextureWidth, m_fogRenderTextureHeight); } private void OnEnable() { m_camera = GetComponent(); } [ImageEffectOpaque] void OnRenderImage(RenderTexture source, RenderTexture destination) { m_camera.depthTextureMode |= DepthTextureMode.Depth; if (m_fogComputationMaterial == null || m_fogRendererMaterial == null) { Graphics.Blit(source, destination); return; } m_camera.CalculateFrustumCorners(m_viewRect, m_camera.farClipPlane, m_camera.stereoActiveEye, m_frustumCorners); m_frustumCornersArray = Matrix4x4.identity; m_frustumCornersArray.SetRow(0, m_camera.transform.TransformVector(m_frustumCorners[0])); // bottom left m_frustumCornersArray.SetRow(2, m_camera.transform.TransformVector(m_frustumCorners[1])); // top left m_frustumCornersArray.SetRow(3, m_camera.transform.TransformVector(m_frustumCorners[2])); // top right m_frustumCornersArray.SetRow(1, m_camera.transform.TransformVector(m_frustumCorners[3])); // bottom right m_fogComputationMaterial.SetMatrix(AzureShaderUniforms.FrustumCornersMatrix, m_frustumCornersArray); m_fogRendererMaterial.SetMatrix(AzureShaderUniforms.FrustumCornersMatrix, m_frustumCornersArray); // Compute the fog scattering effect and render it into a RenderTexture Graphics.Blit(null, m_fogScatteringRT, m_fogComputationMaterial, 0); // Render the fog scattering RenderTexture into the screen. m_fogRendererMaterial.SetTexture(AzureShaderUniforms.FogScatteringDataTexture, m_fogScatteringRT); Graphics.Blit(source, destination, m_fogRendererMaterial, 0); } /// Sets the resolution of the render texture that stores fog scattering data. public void SetFogScatteringResolution(int width, int height) { m_fogRenderTextureWidth = width; m_fogRenderTextureHeight = height; m_fogScatteringRT = new RenderTexture(width, height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default) { name = "Fog Scattering RT", wrapMode = TextureWrapMode.Clamp, filterMode = FilterMode.Bilinear }; m_fogScatteringRT.Create(); } } }