using UnityEngine; using UnityEngine.Rendering; [ExecuteInEditMode] [ImageEffectAllowedInSceneView] [RequireComponent(typeof(Camera))] public class CommandBufferBlur : MonoBehaviour { Shader _shader; Material _material = null; Camera _camera = null; CommandBuffer _commandBuffer = null; Vector2 _screenResolution = Vector2.zero; RenderTextureFormat _textureFormat = RenderTextureFormat.ARGB32; public void Cleanup() { if (!Initialized) return; _camera.RemoveCommandBuffer(CameraEvent.BeforeForwardAlpha, _commandBuffer); _commandBuffer = null; Object.DestroyImmediate(_material); } public void OnEnable() { Cleanup(); Initialize(); } public void OnDisable() { Cleanup(); } public bool Initialized { get { return _commandBuffer != null; } } void Initialize() { if (Initialized) return; if (!_shader) { _shader = Shader.Find("Hidden/SeparableGlassBlur"); if (!_shader) throw new MissingReferenceException("Unable to find required shader \"Hidden/SeparableGlassBlur\""); } if (!_material) { _material = new Material(_shader); _material.hideFlags = HideFlags.HideAndDontSave; } _camera = GetComponent(); if (_camera.allowHDR && SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.DefaultHDR)) _textureFormat = RenderTextureFormat.DefaultHDR; _commandBuffer = new CommandBuffer(); _commandBuffer.name = "Blur screen"; int numIterations = 4; Vector2[] sizes = { new Vector2(Screen.width, Screen.height), new Vector2(Screen.width / 2, Screen.height / 2), new Vector2(Screen.width / 4, Screen.height / 4), new Vector2(Screen.width / 8, Screen.height / 8), }; for (int i = 0; i < numIterations; ++i) { int screenCopyID = Shader.PropertyToID("_ScreenCopyTexture"); _commandBuffer.GetTemporaryRT(screenCopyID, -1, -1, 0, FilterMode.Bilinear, _textureFormat); _commandBuffer.Blit(BuiltinRenderTextureType.CurrentActive, screenCopyID); int blurredID = Shader.PropertyToID("_Grab" + i + "_Temp1"); int blurredID2 = Shader.PropertyToID("_Grab" + i + "_Temp2"); _commandBuffer.GetTemporaryRT(blurredID, (int)sizes[i].x, (int)sizes[i].y, 0, FilterMode.Bilinear, _textureFormat); _commandBuffer.GetTemporaryRT(blurredID2, (int)sizes[i].x, (int)sizes[i].y, 0, FilterMode.Bilinear, _textureFormat); _commandBuffer.Blit(screenCopyID, blurredID); _commandBuffer.ReleaseTemporaryRT(screenCopyID); _commandBuffer.SetGlobalVector("offsets", new Vector4(2.0f / sizes[i].x, 0, 0, 0)); _commandBuffer.Blit(blurredID, blurredID2, _material); _commandBuffer.SetGlobalVector("offsets", new Vector4(0, 2.0f / sizes[i].y, 0, 0)); _commandBuffer.Blit(blurredID2, blurredID, _material); _commandBuffer.SetGlobalTexture("_GrabBlurTexture_" + i, blurredID); } _camera.AddCommandBuffer(CameraEvent.BeforeForwardAlpha, _commandBuffer); _screenResolution = new Vector2(Screen.width, Screen.height); } void OnPreRender() { if (_screenResolution != new Vector2(Screen.width, Screen.height)) Cleanup(); Initialize(); } }