From 6eb915c129fc90c6f4c82ae097dd6ffad5239efc Mon Sep 17 00:00:00 2001 From: chai Date: Mon, 25 Jan 2021 14:28:30 +0800 Subject: +scripts --- Client/Assets/Scripts/PostEffect/Bloom.cs | 335 ++++++++++++++++++++++++++++++ 1 file changed, 335 insertions(+) create mode 100644 Client/Assets/Scripts/PostEffect/Bloom.cs (limited to 'Client/Assets/Scripts/PostEffect/Bloom.cs') diff --git a/Client/Assets/Scripts/PostEffect/Bloom.cs b/Client/Assets/Scripts/PostEffect/Bloom.cs new file mode 100644 index 00000000..d7c17c40 --- /dev/null +++ b/Client/Assets/Scripts/PostEffect/Bloom.cs @@ -0,0 +1,335 @@ +using UnityEngine; +using System.Collections; + +[ExecuteInEditMode] +[RequireComponent(typeof(Camera))] +public class Bloom : PostEffectsBase +{ + public enum LensFlareStyle { + Ghosting = 0, + Anamorphic = 1, + Combined = 2, + } + + public enum TweakMode { + Basic = 0, + Complex = 1, + } + + public enum HDRBloomMode { + Auto = 0, + On = 1, + Off = 2, + } + + public enum BloomScreenBlendMode { + Screen = 0, + Add = 1, + } + + public enum BloomQuality { + Cheap = 0, + High = 1, + } + + public TweakMode tweakMode = TweakMode.Basic; + public BloomScreenBlendMode screenBlendMode = BloomScreenBlendMode.Add; + + public HDRBloomMode hdr = HDRBloomMode.Auto; + private bool doHdr = false; + public float sepBlurSpread = 2.5f; + + public BloomQuality quality = BloomQuality.High; + + public float bloomIntensity = 0.5f; + public float bloomThreshhold = 0.5f; + public Color bloomThreshholdColor = Color.white; + public int bloomBlurIterations = 2; + + public int hollywoodFlareBlurIterations = 2; + public float flareRotation = 0.0f; + public LensFlareStyle lensflareMode = LensFlareStyle.Anamorphic; + public float hollyStretchWidth = 2.5f; + public float lensflareIntensity = 0.0f; + public float lensflareThreshhold = 0.3f; + public float lensFlareSaturation = 0.75f; + public Color flareColorA = new Color (0.4f, 0.4f, 0.8f, 0.75f); + public Color flareColorB = new Color(0.4f, 0.8f, 0.8f, 0.75f); + public Color flareColorC = new Color(0.8f, 0.4f, 0.8f, 0.75f); + public Color flareColorD = new Color(0.8f, 0.4f, 0.0f, 0.75f); + public float blurWidth = 1.0f; + public Texture2D lensFlareVignetteMask; + + public Shader lensFlareShader; + private Material lensFlareMaterial; + + public Shader screenBlendShader; + private Material screenBlend; + + public Shader blurAndFlaresShader; + private Material blurAndFlaresMaterial; + + public Shader brightPassFilterShader; + private Material brightPassFilterMaterial; + + new bool CheckResources () + { + CheckSupport (false); + + screenBlend = CheckShaderAndCreateMaterial (screenBlendShader, screenBlend); + lensFlareMaterial = CheckShaderAndCreateMaterial(lensFlareShader,lensFlareMaterial); + blurAndFlaresMaterial = CheckShaderAndCreateMaterial (blurAndFlaresShader, blurAndFlaresMaterial); + brightPassFilterMaterial = CheckShaderAndCreateMaterial(brightPassFilterShader, brightPassFilterMaterial); + + if(!isSupported) + ReportAutoDisable (); + return isSupported; + } + + void OnRenderImage (RenderTexture source,RenderTexture destination) { + if(CheckResources()==false) { + Graphics.Blit (source, destination); + return; + } + + // screen blend is not supported when HDR is enabled (will cap values) + + doHdr = false; + if(hdr == HDRBloomMode.Auto) + doHdr = source.format == RenderTextureFormat.ARGBHalf && GetComponent().hdr; + else { + doHdr = hdr == HDRBloomMode.On; + } + + doHdr = doHdr && supportHDRTextures; + + BloomScreenBlendMode realBlendMode = screenBlendMode; + if(doHdr) + realBlendMode = BloomScreenBlendMode.Add; + + var rtFormat = (doHdr) ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.Default; + var rtW2 = source.width/2; + var rtH2 = source.height/2; + var rtW4 = source.width/4; + var rtH4 = source.height/4; + + float widthOverHeight = (1.0f * source.width) / (1.0f * source.height); + float oneOverBaseSize = 1.0f / 512.0f; + + // downsample + RenderTexture quarterRezColor = RenderTexture.GetTemporary (rtW4, rtH4, 0, rtFormat); + RenderTexture halfRezColorDown = RenderTexture.GetTemporary (rtW2, rtH2, 0, rtFormat); + if(quality > BloomQuality.Cheap) { + Graphics.Blit (source, halfRezColorDown, screenBlend, 2); + RenderTexture rtDown4 = RenderTexture.GetTemporary (rtW4, rtH4, 0, rtFormat); + Graphics.Blit (halfRezColorDown, rtDown4, screenBlend, 2); + Graphics.Blit (rtDown4, quarterRezColor, screenBlend, 6); + RenderTexture.ReleaseTemporary(rtDown4); + } + else { + Graphics.Blit (source, halfRezColorDown); + Graphics.Blit (halfRezColorDown, quarterRezColor, screenBlend, 6); + } + RenderTexture.ReleaseTemporary (halfRezColorDown); + + // cut colors (threshholding) + RenderTexture secondQuarterRezColor = RenderTexture.GetTemporary (rtW4, rtH4, 0, rtFormat); + BrightFilter (bloomThreshhold * bloomThreshholdColor, quarterRezColor, secondQuarterRezColor); + + // blurring + + if (bloomBlurIterations < 1) bloomBlurIterations = 1; + else if (bloomBlurIterations > 10) bloomBlurIterations = 10; + + for (int iter = 0; iter < bloomBlurIterations; iter++ ) { + float spreadForPass = (1.0f + (iter * 0.25f)) * sepBlurSpread; + + // vertical blur + RenderTexture blur4 = RenderTexture.GetTemporary (rtW4, rtH4, 0, rtFormat); + blurAndFlaresMaterial.SetVector ("_Offsets", new Vector4 (0.0f, spreadForPass * oneOverBaseSize, 0.0f, 0.0f)); + Graphics.Blit (secondQuarterRezColor, blur4, blurAndFlaresMaterial, 4); + RenderTexture.ReleaseTemporary(secondQuarterRezColor); + secondQuarterRezColor = blur4; + + // horizontal blur + blur4 = RenderTexture.GetTemporary (rtW4, rtH4, 0, rtFormat); + blurAndFlaresMaterial.SetVector("_Offsets", new Vector4((spreadForPass / widthOverHeight) * oneOverBaseSize, 0.0f, 0.0f, 0.0f)); + Graphics.Blit (secondQuarterRezColor, blur4, blurAndFlaresMaterial, 4); + RenderTexture.ReleaseTemporary (secondQuarterRezColor); + secondQuarterRezColor = blur4; + + if (quality > BloomQuality.Cheap) { + if (iter == 0) + { + Graphics.SetRenderTarget(quarterRezColor); + GL.Clear(false, true, Color.black); // Clear to avoid RT restore + Graphics.Blit (secondQuarterRezColor, quarterRezColor); + } + else + { + quarterRezColor.MarkRestoreExpected(); // using max blending, RT restore expected + Graphics.Blit (secondQuarterRezColor, quarterRezColor, screenBlend, 10); + } + } + } + + if(quality > BloomQuality.Cheap) + { + Graphics.SetRenderTarget(secondQuarterRezColor); + GL.Clear(false, true, Color.black); // Clear to avoid RT restore + Graphics.Blit (quarterRezColor, secondQuarterRezColor, screenBlend, 6); + } + + // lens flares: ghosting, anamorphic or both (ghosted anamorphic flares) + + if (lensflareIntensity > Mathf.Epsilon) { + + RenderTexture rtFlares4 = RenderTexture.GetTemporary (rtW4, rtH4, 0, rtFormat); + + if (lensflareMode == 0) { + // ghosting only + + BrightFilter (lensflareThreshhold, secondQuarterRezColor, rtFlares4); + + if(quality > BloomQuality.Cheap) { + // smooth a little + blurAndFlaresMaterial.SetVector("_Offsets", new Vector4(0.0f, (1.5f) / (1.0f * quarterRezColor.height), 0.0f, 0.0f)); + Graphics.SetRenderTarget(quarterRezColor); + GL.Clear(false, true, Color.black); // Clear to avoid RT restore + Graphics.Blit (rtFlares4, quarterRezColor, blurAndFlaresMaterial, 4); + + blurAndFlaresMaterial.SetVector("_Offsets", new Vector4((1.5f) / (1.0f * quarterRezColor.width), 0.0f, 0.0f, 0.0f)); + Graphics.SetRenderTarget(rtFlares4); + GL.Clear(false, true, Color.black); // Clear to avoid RT restore + Graphics.Blit (quarterRezColor, rtFlares4, blurAndFlaresMaterial, 4); + } + + // no ugly edges! + Vignette (0.975f, rtFlares4, rtFlares4); + BlendFlares (rtFlares4, secondQuarterRezColor); + } + else { + + //Vignette (0.975f, rtFlares4, rtFlares4); + //DrawBorder(rtFlares4, screenBlend, 8); + + float flareXRot = 1.0f * Mathf.Cos(flareRotation); + float flareyRot = 1.0f * Mathf.Sin(flareRotation); + + float stretchWidth = (hollyStretchWidth * 1.0f / widthOverHeight) * oneOverBaseSize; + //float stretchWidthY = hollyStretchWidth * oneOverBaseSize; + + blurAndFlaresMaterial.SetVector("_Offsets", new Vector4(flareXRot, flareyRot, 0.0f, 0.0f)); + blurAndFlaresMaterial.SetVector("_Threshhold", new Vector4(lensflareThreshhold, 1.0f, 0.0f, 0.0f)); + blurAndFlaresMaterial.SetVector("_TintColor", new Vector4(flareColorA.r, flareColorA.g, flareColorA.b, flareColorA.a) * flareColorA.a * lensflareIntensity); + blurAndFlaresMaterial.SetFloat ("_Saturation", lensFlareSaturation); + + // "pre and cut" + quarterRezColor.DiscardContents(); + Graphics.Blit (rtFlares4, quarterRezColor, blurAndFlaresMaterial, 2); + // "post" + rtFlares4.DiscardContents(); + Graphics.Blit (quarterRezColor, rtFlares4, blurAndFlaresMaterial, 3); + + blurAndFlaresMaterial.SetVector("_Offsets", new Vector4(flareXRot * stretchWidth, flareyRot * stretchWidth, 0.0f, 0.0f)); + // stretch 1st + blurAndFlaresMaterial.SetFloat ("_StretchWidth", hollyStretchWidth); + quarterRezColor.DiscardContents(); + Graphics.Blit (rtFlares4, quarterRezColor, blurAndFlaresMaterial, 1); + // stretch 2nd + blurAndFlaresMaterial.SetFloat ("_StretchWidth", hollyStretchWidth * 2.0f); + rtFlares4.DiscardContents(); + Graphics.Blit (quarterRezColor, rtFlares4, blurAndFlaresMaterial, 1); + // stretch 3rd + blurAndFlaresMaterial.SetFloat ("_StretchWidth", hollyStretchWidth * 4.0f); + quarterRezColor.DiscardContents(); + Graphics.Blit (rtFlares4, quarterRezColor, blurAndFlaresMaterial, 1); + + // additional blur passes + for (int iter = 0; iter < hollywoodFlareBlurIterations; iter++) + { + stretchWidth = (hollyStretchWidth * 2.0f / widthOverHeight) * oneOverBaseSize; + + blurAndFlaresMaterial.SetVector("_Offsets", new Vector4(stretchWidth * flareXRot, stretchWidth * flareyRot, 0.0f, 0.0f)); + rtFlares4.DiscardContents(); + Graphics.Blit (quarterRezColor, rtFlares4, blurAndFlaresMaterial, 4); + + blurAndFlaresMaterial.SetVector("_Offsets", new Vector4(stretchWidth * flareXRot, stretchWidth * flareyRot, 0.0f, 0.0f)); + quarterRezColor.DiscardContents(); + Graphics.Blit (rtFlares4, quarterRezColor, blurAndFlaresMaterial, 4); + } + + if (lensflareMode == LensFlareStyle.Anamorphic) + // anamorphic lens flares + AddTo (1.0f, quarterRezColor, secondQuarterRezColor); + else { + + // "combined" lens flares + + Vignette (1.0f, quarterRezColor, rtFlares4); + BlendFlares (rtFlares4, quarterRezColor); + AddTo (1.0f, quarterRezColor, secondQuarterRezColor); + } + } + RenderTexture.ReleaseTemporary (rtFlares4); + } + + int blendPass = (int)realBlendMode; + //if(Mathf.Abs(chromaticBloom) < Mathf.Epsilon) + // blendPass += 4; + + screenBlend.SetFloat ("_Intensity", bloomIntensity); + screenBlend.SetTexture ("_ColorBuffer", source); + + if(quality > BloomQuality.Cheap) { + RenderTexture halfRezColorUp = RenderTexture.GetTemporary (rtW2, rtH2, 0, rtFormat); + Graphics.Blit (secondQuarterRezColor, halfRezColorUp); + Graphics.Blit (halfRezColorUp, destination, screenBlend, blendPass); + RenderTexture.ReleaseTemporary (halfRezColorUp); + } + else + Graphics.Blit (secondQuarterRezColor, destination, screenBlend, blendPass); + + RenderTexture.ReleaseTemporary (quarterRezColor); + RenderTexture.ReleaseTemporary (secondQuarterRezColor); + } + + private void AddTo (float intensity_, RenderTexture from, RenderTexture to) { + screenBlend.SetFloat ("_Intensity", intensity_); + to.MarkRestoreExpected(); // additive blending, RT restore expected + Graphics.Blit (from, to, screenBlend, 9); + } + + private void BlendFlares (RenderTexture from,RenderTexture to) { + lensFlareMaterial.SetVector("colorA", new Vector4(flareColorA.r, flareColorA.g, flareColorA.b, flareColorA.a) * lensflareIntensity); + lensFlareMaterial.SetVector("colorB", new Vector4(flareColorB.r, flareColorB.g, flareColorB.b, flareColorB.a) * lensflareIntensity); + lensFlareMaterial.SetVector("colorC", new Vector4(flareColorC.r, flareColorC.g, flareColorC.b, flareColorC.a) * lensflareIntensity); + lensFlareMaterial.SetVector ("colorD", new Vector4 (flareColorD.r, flareColorD.g, flareColorD.b, flareColorD.a) * lensflareIntensity); + to.MarkRestoreExpected(); // additive blending, RT restore expected + Graphics.Blit (from, to, lensFlareMaterial); + } + + private void BrightFilter (float thresh,RenderTexture from,RenderTexture to) { + brightPassFilterMaterial.SetVector("_Threshhold", new Vector4(thresh, thresh, thresh, thresh)); + Graphics.Blit (from, to, brightPassFilterMaterial, 0); + } + + private void BrightFilter (Color threshColor,RenderTexture from,RenderTexture to) { + brightPassFilterMaterial.SetVector ("_Threshhold", threshColor); + Graphics.Blit (from, to, brightPassFilterMaterial, 1); + } + + private void Vignette (float amount,RenderTexture from,RenderTexture to) { + if(lensFlareVignetteMask) { + screenBlend.SetTexture ("_ColorBuffer", lensFlareVignetteMask); + to.MarkRestoreExpected(); // using blending, RT restore expected + Graphics.Blit (from == to ? null : from, to, screenBlend, from == to ? 7 : 3); + } + else if (from != to) + { + Graphics.SetRenderTarget (to); + GL.Clear(false, true, Color.black); // clear destination to avoid RT restore + Graphics.Blit (from, to); + } + } +} -- cgit v1.1-26-g67d0