@script ExecuteInEditMode @script RequireComponent (Camera) @script AddComponentMenu ("Image Effects/Bloom and Flares") enum LensflareStyle { Ghosting = 0, Hollywood = 1, Combined = 2, } enum TweakMode { Simple = 0, Advanced = 1, } class BloomAndFlares extends PostEffectsBase { public var tweakMode : TweakMode = 1; public var bloomThisTag : String; public var sepBlurSpread : float = 1.5; public var useSrcAlphaAsMask : float = 0.5; public var bloomIntensity : float = 1.0; public var bloomThreshhold : float = 0.4; public var bloomBlurIterations : int = 3; public var lensflares : boolean = true; public var hollywoodFlareBlurIterations : int = 4; public var lensflareMode : LensflareStyle = 0; public var hollyStretchWidth : float = 2.5; public var lensflareIntensity : float = 0.75; public var lensflareThreshhold : float = 0.5; public var flareColorA : Color = Color(0.4,0.4,0.8,0.75); public var flareColorB : Color = Color(0.4,0.8,0.8,0.75); public var flareColorC : Color = Color(0.8,0.4,0.8,0.75); public var flareColorD : Color = Color(0.8,0.4,0.0,0.75); public var blurWidth : float = 1.0; // needed shaders & materials ... public var addAlphaHackShader : Shader; private var _alphaAddMaterial : Material; public var lensFlareShader : Shader; private var _lensFlareMaterial : Material; public var vignetteShader : Shader; private var _vignetteMaterial : Material; public var separableBlurShader : Shader; private var _separableBlurMaterial : Material; public var addBrightStuffOneOneShader: Shader; private var _addBrightStuffBlendOneOneMaterial : Material; public var hollywoodFlareBlurShader: Shader; private var _hollywoodFlareBlurMaterial : Material; public var hollywoodFlareStretchShader: Shader; private var _hollywoodFlareStretchMaterial : Material; public var brightPassFilterShader : Shader; private var _brightPassFilterMaterial : Material; function Start () { CreateMaterials (); CheckSupport(false); } // @TODO group shaders into material passes function CreateMaterials () { _lensFlareMaterial = CheckShaderAndCreateMaterial(lensFlareShader,_lensFlareMaterial); _vignetteMaterial = CheckShaderAndCreateMaterial(vignetteShader,_vignetteMaterial); _separableBlurMaterial = CheckShaderAndCreateMaterial(separableBlurShader,_separableBlurMaterial); _addBrightStuffBlendOneOneMaterial = CheckShaderAndCreateMaterial(addBrightStuffOneOneShader,_addBrightStuffBlendOneOneMaterial); _hollywoodFlareBlurMaterial = CheckShaderAndCreateMaterial(hollywoodFlareBlurShader,_hollywoodFlareBlurMaterial); _hollywoodFlareStretchMaterial = CheckShaderAndCreateMaterial(hollywoodFlareStretchShader,_hollywoodFlareStretchMaterial); _brightPassFilterMaterial = CheckShaderAndCreateMaterial(brightPassFilterShader,_brightPassFilterMaterial); _alphaAddMaterial = CheckShaderAndCreateMaterial(addAlphaHackShader,_alphaAddMaterial); } function OnRenderImage (source : RenderTexture, destination : RenderTexture) { CreateMaterials (); // some objects should ignore the alpha threshhold limit, // so draw .a = 1 into the color buffer for those ... // // the drawing is scheduled here if(bloomThisTag && bloomThisTag != "Untagged") { var gos : GameObject[] = GameObject.FindGameObjectsWithTag(bloomThisTag); for (var go : GameObject in gos) { if(go.GetComponent(MeshFilter)) { var mesh : Mesh = (go.GetComponent(MeshFilter) as MeshFilter).sharedMesh; _alphaAddMaterial.SetPass(0); Graphics.DrawMeshNow(mesh,go.transform.localToWorldMatrix); } } } var halfRezColor : RenderTexture = RenderTexture.GetTemporary(source.width / 2.0, source.height / 2.0, 0); var quarterRezColor : RenderTexture = RenderTexture.GetTemporary(source.width / 4.0, source.height / 4.0, 0); var secondQuarterRezColor : RenderTexture = RenderTexture.GetTemporary(source.width / 4.0, source.height / 4.0, 0); var thirdQuarterRezColor : RenderTexture = RenderTexture.GetTemporary(source.width / 4.0, source.height / 4.0, 0); // at this point, we have massaged the alpha channel enough to start downsampling process for bloom Graphics.Blit (source, halfRezColor); Graphics.Blit (halfRezColor, quarterRezColor); RenderTexture.ReleaseTemporary (halfRezColor); // cut colors (threshholding) _brightPassFilterMaterial.SetVector ("threshhold", Vector4 (bloomThreshhold, 1.0/(1.0-bloomThreshhold), 0.0, 0.0)); _brightPassFilterMaterial.SetFloat ("useSrcAlphaAsMask", useSrcAlphaAsMask); Graphics.Blit (quarterRezColor, secondQuarterRezColor, _brightPassFilterMaterial); // blurring if (bloomBlurIterations < 1) bloomBlurIterations = 1; Graphics.Blit(secondQuarterRezColor, quarterRezColor); for (var iter : int = 0; iter < bloomBlurIterations; iter++ ) { _separableBlurMaterial.SetVector ("offsets", Vector4 (0.0, (sepBlurSpread * 1.0) / quarterRezColor.height, 0.0, 0.0)); Graphics.Blit (quarterRezColor, thirdQuarterRezColor, _separableBlurMaterial); _separableBlurMaterial.SetVector ("offsets", Vector4 ((sepBlurSpread * 1.0) / quarterRezColor.width, 0.0, 0.0, 0.0)); Graphics.Blit (thirdQuarterRezColor, quarterRezColor, _separableBlurMaterial); } Graphics.Blit (source, destination); if (lensflares) { // lens flare fun: cut some additional values // (yes, they will be cut on top of the already cut bloom values, // so just optimize away if not really needed) _brightPassFilterMaterial.SetVector ("threshhold", Vector4 (lensflareThreshhold, 1.0/(1.0-lensflareThreshhold), 0.0, 0.0)); _brightPassFilterMaterial.SetFloat ("useSrcAlphaAsMask", 0.0); Graphics.Blit (secondQuarterRezColor, thirdQuarterRezColor, _brightPassFilterMaterial); if(lensflareMode == 0) // ghosting { // smooth out a little _separableBlurMaterial.SetVector ("offsets", Vector4 (0.0, (sepBlurSpread*1.0)/quarterRezColor.height, 0.0, 0.0)); Graphics.Blit (thirdQuarterRezColor, secondQuarterRezColor, _separableBlurMaterial); _separableBlurMaterial.SetVector ("offsets", Vector4 ((sepBlurSpread*1.0)/quarterRezColor.width, 0.0, 0.0, 0.0)); Graphics.Blit (secondQuarterRezColor, thirdQuarterRezColor, _separableBlurMaterial); // vignette for lens flares so that we don't notice any hard edges _vignetteMaterial.SetFloat ("vignetteIntensity", 0.975); Graphics.Blit (thirdQuarterRezColor, secondQuarterRezColor, _vignetteMaterial); // generating flares (_lensFlareMaterial has One One Blend) _lensFlareMaterial.SetVector ("colorA", Vector4(flareColorA.r,flareColorA.g,flareColorA.b,flareColorA.a) * lensflareIntensity); _lensFlareMaterial.SetVector ("colorB", Vector4(flareColorB.r,flareColorB.g,flareColorB.b,flareColorB.a) * lensflareIntensity); _lensFlareMaterial.SetVector ("colorC", Vector4(flareColorC.r,flareColorC.g,flareColorC.b,flareColorC.a) * lensflareIntensity); _lensFlareMaterial.SetVector ("colorD", Vector4(flareColorD.r,flareColorD.g,flareColorD.b,flareColorD.a) * lensflareIntensity); Graphics.Blit (secondQuarterRezColor, quarterRezColor, _lensFlareMaterial); } else { _hollywoodFlareBlurMaterial.SetVector ("offsets", Vector4(0.0, (sepBlurSpread * 1.0) / quarterRezColor.height, 0.0, 0.0)); _hollywoodFlareBlurMaterial.SetTexture("_NonBlurredTex", quarterRezColor); _hollywoodFlareBlurMaterial.SetVector ("tintColor", Vector4(flareColorA.r,flareColorA.g,flareColorA.b,flareColorA.a) * flareColorA.a * lensflareIntensity); Graphics.Blit (thirdQuarterRezColor, secondQuarterRezColor, _hollywoodFlareBlurMaterial); _hollywoodFlareStretchMaterial.SetVector ("offsets", Vector4 ((sepBlurSpread * 1.0) / quarterRezColor.width, 0.0, 0.0, 0.0)); _hollywoodFlareStretchMaterial.SetFloat("stretchWidth", hollyStretchWidth); Graphics.Blit (secondQuarterRezColor, thirdQuarterRezColor, _hollywoodFlareStretchMaterial); if(lensflareMode == 1) // hollywood flares { for (var itera : int = 0; itera < hollywoodFlareBlurIterations; itera++ ) { _separableBlurMaterial.SetVector ("offsets", Vector4 ((sepBlurSpread * 1.0) / quarterRezColor.width, 0.0, 0.0, 0.0)); Graphics.Blit (thirdQuarterRezColor, secondQuarterRezColor, _separableBlurMaterial); _separableBlurMaterial.SetVector ("offsets", Vector4 ((sepBlurSpread * 1.0) / quarterRezColor.width, 0.0, 0.0, 0.0)); Graphics.Blit (secondQuarterRezColor, thirdQuarterRezColor, _separableBlurMaterial); } _addBrightStuffBlendOneOneMaterial.SetFloat ("intensity", 1.0); Graphics.Blit (thirdQuarterRezColor, quarterRezColor, _addBrightStuffBlendOneOneMaterial); } else // 'both' (@NOTE: is weird, maybe just remove) { for (var ix : int = 0; ix < hollywoodFlareBlurIterations; ix++ ) { _separableBlurMaterial.SetVector ("offsets", Vector4 ((sepBlurSpread * 1.0) / quarterRezColor.width, 0.0, 0.0, 0.0)); Graphics.Blit (thirdQuarterRezColor, secondQuarterRezColor, _separableBlurMaterial); _separableBlurMaterial.SetVector ("offsets", Vector4 ((sepBlurSpread * 1.0) / quarterRezColor.width, 0.0, 0.0, 0.0)); Graphics.Blit (secondQuarterRezColor, thirdQuarterRezColor, _separableBlurMaterial); } // vignette for lens flares _vignetteMaterial.SetFloat ("vignetteIntensity", 1.0); Graphics.Blit (thirdQuarterRezColor, secondQuarterRezColor, _vignetteMaterial); // creating the flares // _lensFlareMaterial has One One Blend _lensFlareMaterial.SetVector ("colorA", Vector4(flareColorA.r,flareColorA.g,flareColorA.b,flareColorA.a) * flareColorA.a * lensflareIntensity); _lensFlareMaterial.SetVector ("colorB", Vector4(flareColorB.r,flareColorB.g,flareColorB.b,flareColorB.a) * flareColorB.a * lensflareIntensity); _lensFlareMaterial.SetVector ("colorC", Vector4(flareColorC.r,flareColorC.g,flareColorC.b,flareColorC.a) * flareColorC.a * lensflareIntensity); _lensFlareMaterial.SetVector ("colorD", Vector4(flareColorD.r,flareColorD.g,flareColorD.b,flareColorD.a) * flareColorD.a * lensflareIntensity); Graphics.Blit (secondQuarterRezColor, thirdQuarterRezColor, _lensFlareMaterial); _addBrightStuffBlendOneOneMaterial.SetFloat ("intensity", 1.0); Graphics.Blit (thirdQuarterRezColor, quarterRezColor, _addBrightStuffBlendOneOneMaterial); } } } _addBrightStuffBlendOneOneMaterial.SetFloat("intensity", bloomIntensity); Graphics.Blit (quarterRezColor, destination, _addBrightStuffBlendOneOneMaterial); RenderTexture.ReleaseTemporary (quarterRezColor); RenderTexture.ReleaseTemporary (secondQuarterRezColor); RenderTexture.ReleaseTemporary (thirdQuarterRezColor); } }