- Home /
Layer-based Bloom Image Effect renders over objects
I tried to make a layer-based bloom effect. The bloom effect is from FastMobileBloom, and then I edited some of the script and shader for it to work on selected layers. Here is the result:
The only problem now is that the effect is rendering over objects. How can I prevent this?
Here is the setup:
2 cameras, the sourceCamera and the bloomCamera that is generated by code.
sourceCamera - cullingMask is Everything except for the Bloom layer, the FastMobileBloomEffect script is attached.
bloomCamera - cullingMask is Bloom layer only, clearFlags to Nothing, has a targetTexture.
Notes:
I am on Android platform.
Tried MK Glow Free, works in the Editor, but black screen on build (the UI is rendering though).
FastMobileBloomEffect.cs
using UnityEngine;
[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
public class FastMobileBloomEffect : MonoBehaviour
{
[Range(0.0f, 1.5f)] public float threshold = 0.25f;
[Range(0.00f, 4.0f)] public float intensity = 1.0f;
[Range(0.25f, 5.5f)] public float blurSize = 1.0f;
[Range(1, 4)] public int blurIterations = 2;
public LayerMask bloomMask = -1;
Camera sourceCamera
{
get
{
if (_sourceCamera == null)
_sourceCamera = GetComponent<Camera>();
return _sourceCamera;
}
}
Camera _sourceCamera;
Camera bloomCamera
{
get
{
if (_bloomCamera == null)
{
_bloomCamera = new GameObject("Bloom Camera", typeof(Camera), typeof(FlareLayer)).GetComponent<Camera>();
_bloomCamera.enabled = false;
_bloomCamera.gameObject.hideFlags = HideFlags.HideAndDontSave;
_bloomCamera.transform.SetParent(this.transform);
_bloomCamera.transform.localPosition = Vector3.zero;
_bloomCamera.transform.localRotation = Quaternion.identity;
_bloomCamera.transform.localScale = Vector3.one;
}
_bloomCamera.CopyFrom(sourceCamera);
_bloomCamera.cullingMask = bloomMask;
_bloomCamera.clearFlags = CameraClearFlags.Nothing;
_bloomCamera.targetTexture = target;
return _bloomCamera;
}
}
Camera _bloomCamera;
RenderTexture target
{
get
{
if (_target == null || _target.width != sourceCamera.pixelWidth || _target.height != sourceCamera.pixelHeight)
_target = new RenderTexture(sourceCamera.pixelWidth, sourceCamera.pixelHeight, 24, RenderTextureFormat.ARGB32);
return _target;
}
}
RenderTexture _target;
Material fastBloomMat
{
get
{
if (_fastBloomMat == null)
{
_fastBloomMat = new Material(Resources.Load<Shader>("FastMobileBloom"));
_fastBloomMat.hideFlags = HideFlags.HideAndDontSave;
}
return _fastBloomMat;
}
}
Material _fastBloomMat;
void OnPreRender()
{
sourceCamera.Render();
RenderTexture.active = bloomCamera.targetTexture;
GL.Clear(true, true, Color.clear);
RenderTexture.active = null;
bloomCamera.Render();
}
static void Clear(ref RenderTexture rt)
{
RenderTexture active = RenderTexture.active;
RenderTexture.active = rt;
GL.Clear(true, true, Color.clear);
RenderTexture.active = active;
}
void OnRenderImage(RenderTexture src, RenderTexture dst)
{
Graphics.Blit(src, dst);
int width = target.width / 4;
int height = target.height / 4;
RenderTexture rt = RenderTexture.GetTemporary(width, height, 0, target.format);
rt.DiscardContents();
Clear(ref rt);
fastBloomMat.SetFloat("_Spread", blurSize);
fastBloomMat.SetVector("_ThresholdParams", new Vector2(1.0f, -threshold));
Graphics.Blit(target, rt, fastBloomMat, 0);
//downscale
for(int i = 0; i < blurIterations - 1; i++)
{
RenderTexture rt2 = RenderTexture.GetTemporary(rt.width / 2, rt.height / 2, 0, target.format);
rt2.DiscardContents();
Clear(ref rt2);
fastBloomMat.SetFloat("_Spread", blurSize);
Graphics.Blit(rt, rt2, fastBloomMat, 1);
RenderTexture.ReleaseTemporary(rt);
rt = rt2;
}
//upscale
for(int i = 0; i < blurIterations - 1; i++)
{
RenderTexture rt2 = RenderTexture.GetTemporary(rt.width * 2, rt.height * 2, 0, target.format);
rt2.DiscardContents();
Clear(ref rt2);
fastBloomMat.SetFloat("_Spread", blurSize);
Graphics.Blit(rt, rt2, fastBloomMat, 2);
RenderTexture.ReleaseTemporary(rt);
rt = rt2;
}
fastBloomMat.SetFloat("_BloomIntensity", intensity);
fastBloomMat.SetTexture("_BloomTex", rt);
Graphics.Blit(target, dst, fastBloomMat, 3);
RenderTexture.ReleaseTemporary(rt);
}
}
FastMobileBloom.shader
Shader "Custom/FastMobileBloom"
{
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
_BloomTex ("Bloom (RGB)", 2D) = "black" {}
}
CGINCLUDE
#include "UnityCG.cginc"
uniform sampler2D _MainTex;
uniform half4 _MainTex_TexelSize;
uniform half4 _MainTex_ST;
uniform half2 _ThresholdParams;
uniform half _Spread;
uniform sampler2D _BloomTex;
uniform half _BloomIntensity;
struct v2fCombineBloom
{
float4 pos : SV_POSITION;
half2 uv : TEXCOORD0;
#if UNITY_UV_STARTS_AT_TOP
half2 uv2 : TEXCOORD1;
#endif
};
struct v2fBlurDown
{
float4 pos : SV_POSITION;
half2 uv0 : TEXCOORD0;
half4 uv12 : TEXCOORD1;
half4 uv34 : TEXCOORD2;
};
struct v2fBlurUp
{
float4 pos : SV_POSITION;
half4 uv12 : TEXCOORD0;
half4 uv34 : TEXCOORD1;
half4 uv56 : TEXCOORD2;
half4 uv78 : TEXCOORD3;
};
v2fBlurDown vertBlurDown(appdata_img v)
{
v2fBlurDown o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv0 = UnityStereoScreenSpaceUVAdjust(v.texcoord.xy, _MainTex_ST);
o.uv12.xy = UnityStereoScreenSpaceUVAdjust(v.texcoord.xy + half2( 1.0h, 1.0h) * _MainTex_TexelSize.xy * _Spread, _MainTex_ST);
o.uv12.zw = UnityStereoScreenSpaceUVAdjust(v.texcoord.xy + half2(-1.0h, 1.0h) * _MainTex_TexelSize.xy * _Spread, _MainTex_ST);
o.uv34.xy = UnityStereoScreenSpaceUVAdjust(v.texcoord.xy + half2(-1.0h, -1.0h) * _MainTex_TexelSize.xy * _Spread, _MainTex_ST);
o.uv34.zw = UnityStereoScreenSpaceUVAdjust(v.texcoord.xy + half2( 1.0h, -1.0h) * _MainTex_TexelSize.xy * _Spread, _MainTex_ST);
return o;
}
v2fBlurUp vertBlurUp(appdata_img v)
{
v2fBlurUp o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv12.xy = UnityStereoScreenSpaceUVAdjust(v.texcoord.xy + half2( 1.0h, 1.0h) * _MainTex_TexelSize.xy * _Spread, _MainTex_ST);
o.uv12.zw = UnityStereoScreenSpaceUVAdjust(v.texcoord.xy + half2(-1.0h, 1.0h) * _MainTex_TexelSize.xy * _Spread, _MainTex_ST);
o.uv34.xy = UnityStereoScreenSpaceUVAdjust(v.texcoord.xy + half2(-1.0h, -1.0h) * _MainTex_TexelSize.xy * _Spread, _MainTex_ST);
o.uv34.zw = UnityStereoScreenSpaceUVAdjust(v.texcoord.xy + half2( 1.0h, -1.0h) * _MainTex_TexelSize.xy * _Spread, _MainTex_ST);
o.uv56.xy = UnityStereoScreenSpaceUVAdjust(v.texcoord.xy + half2( 0.0h, 2.0h) * _MainTex_TexelSize.xy * _Spread, _MainTex_ST);
o.uv56.zw = UnityStereoScreenSpaceUVAdjust(v.texcoord.xy + half2( 0.0h, -2.0h) * _MainTex_TexelSize.xy * _Spread, _MainTex_ST);
o.uv78.xy = UnityStereoScreenSpaceUVAdjust(v.texcoord.xy + half2( 2.0h, 0.0h) * _MainTex_TexelSize.xy * _Spread, _MainTex_ST);
o.uv78.zw = UnityStereoScreenSpaceUVAdjust(v.texcoord.xy + half2(-2.0h, 0.0h) * _MainTex_TexelSize.xy * _Spread, _MainTex_ST);
return o;
}
v2fCombineBloom vertCombineBloom(appdata_img v)
{
v2fCombineBloom o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = UnityStereoScreenSpaceUVAdjust(v.texcoord, _MainTex_ST);
#if UNITY_UV_STARTS_AT_TOP
o.uv2 = o.uv;
if (_MainTex_TexelSize.y < 0.0)
o.uv.y = 1.0 - o.uv.y;
#endif
return o;
}
fixed4 fragBlurDownFirstPass(v2fBlurDown i) : SV_Target
{
fixed4 col0 = tex2D(_MainTex, i.uv0);
fixed4 col1 = tex2D(_MainTex, i.uv12.xy);
fixed4 col2 = tex2D(_MainTex, i.uv12.zw);
fixed4 col3 = tex2D(_MainTex, i.uv34.xy);
fixed4 col4 = tex2D(_MainTex, i.uv34.zw);
fixed4 col = col0 + col1*0.25 + col2*0.25 + col3*0.25 + col4*0.25;
col = col * 0.5;
col = col + _ThresholdParams.y;
col = max(col, 0.0);
return col;
}
fixed4 fragBlurDown(v2fBlurDown i) : SV_Target
{
fixed4 col0 = tex2D(_MainTex, i.uv0);
fixed4 col1 = tex2D(_MainTex, i.uv12.xy);
fixed4 col2 = tex2D(_MainTex, i.uv12.zw);
fixed4 col3 = tex2D(_MainTex, i.uv34.xy);
fixed4 col4 = tex2D(_MainTex, i.uv34.zw);
fixed4 col = col0 + col1*0.25 + col2*0.25 + col3*0.25 + col4*0.25;
col = col * 0.5;
return col;
}
#define oneSix 0.1666666
#define oneThree 0.3333333
fixed4 fragBlurUp(v2fBlurUp i) : SV_Target
{
fixed4 col1 = tex2D(_MainTex, i.uv12.xy);
fixed4 col2 = tex2D(_MainTex, i.uv12.zw);
fixed4 col3 = tex2D(_MainTex, i.uv34.xy);
fixed4 col4 = tex2D(_MainTex, i.uv34.zw);
fixed4 col5 = tex2D(_MainTex, i.uv56.xy);
fixed4 col6 = tex2D(_MainTex, i.uv56.zw);
fixed4 col7 = tex2D(_MainTex, i.uv78.xy);
fixed4 col8 = tex2D(_MainTex, i.uv78.zw);
fixed4 col = col1*oneThree + col2*oneThree + col3*oneThree + col4*oneThree + col5*oneSix + col6*oneSix + col7*oneSix + col8*oneSix;
//col = col * 0.5;
return col;
}
fixed4 fragCombineBloom(v2fCombineBloom i) : SV_Target
{
#if UNITY_UV_STARTS_AT_TOP
fixed4 col = tex2D(_MainTex, i.uv2);
return col + tex2D(_BloomTex, i.uv) * _BloomIntensity;
#else
fixed4 col = tex2D(_MainTex, i.uv);
return col + tex2D(_BloomTex, i.uv) * _BloomIntensity;
#endif
}
ENDCG
SubShader
{
//edit
Lighting Off
Cull Off ZWrite Off ZTest Always
Blend One OneMinusSrcAlpha
//
//initial downscale and threshold
Pass
{
CGPROGRAM
#pragma vertex vertBlurDown
#pragma fragment fragBlurDownFirstPass
ENDCG
}
//down pass
Pass
{
CGPROGRAM
#pragma vertex vertBlurDown
#pragma fragment fragBlurDown
ENDCG
}
//up pass
Pass
{
CGPROGRAM
#pragma vertex vertBlurUp
#pragma fragment fragBlurUp
ENDCG
}
//final bloom
Pass
{
CGPROGRAM
#pragma vertex vertCombineBloom
#pragma fragment fragCombineBloom
ENDCG
}
}
}
Your answer
Follow this Question
Related Questions
Selective glow through a multi camera setup with a bloom effect 0 Answers
Bloom image effect causing second camera to flicker? 0 Answers
In FastBloom(Bloom Optimized) shader, what's the difference between Standard and Sgx blur type? 0 Answers
Issue with multiple cameras and bloom+HDR 1 Answer
Glow-like effects and WebCamTextures 0 Answers