1
2 Shader "Hidden/FastBloom" {
3 Properties {
4 _MainTex ("Base (RGB)", 2D) = "white" {}
5 _Bloom ("Bloom (RGB)", 2D) = "black" {}
6 }
7
8 CGINCLUDE
9
10 #include "UnityCG.cginc"
11
12 sampler2D _MainTex;
13 sampler2D _Bloom;
14
15 uniform half4 _MainTex_TexelSize;
16
17 uniform half4 _Parameter;
18 uniform half4 _OffsetsA;
19 uniform half4 _OffsetsB;
20
21 #define ONE_MINUS_THRESHHOLD_TIMES_INTENSITY _Parameter.w
22 #define THRESHHOLD _Parameter.z
23
24 struct v2f_simple
25 {
26 float4 pos : SV_POSITION;
27 half2 uv : TEXCOORD0;
28
29 #if UNITY_UV_STARTS_AT_TOP
30 half2 uv2 : TEXCOORD1;
31 #endif
32 };
33
34 v2f_simple vertBloom ( appdata_img v )
35 {
36 v2f_simple o;
37
38 o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
39 o.uv = v.texcoord;
40
41 #if UNITY_UV_STARTS_AT_TOP
42 o.uv2 = v.texcoord;
43 if (_MainTex_TexelSize.y < 0.0)
44 o.uv.y = 1.0 - o.uv.y;
45 #endif
46
47 return o;
48 }
49
50 struct v2f_tap
51 {
52 float4 pos : SV_POSITION;
53 half2 uv20 : TEXCOORD0;
54 half2 uv21 : TEXCOORD1;
55 half2 uv22 : TEXCOORD2;
56 half2 uv23 : TEXCOORD3;
57 };
58
59 v2f_tap vert4Tap ( appdata_img v )
60 {
61 v2f_tap o;
62
63 o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
64 o.uv20 = v.texcoord + _MainTex_TexelSize.xy;
65 o.uv21 = v.texcoord + _MainTex_TexelSize.xy * half2(-0.5h,-0.5h);
66 o.uv22 = v.texcoord + _MainTex_TexelSize.xy * half2(0.5h,-0.5h);
67 o.uv23 = v.texcoord + _MainTex_TexelSize.xy * half2(-0.5h,0.5h);
68
69 return o;
70 }
71
72 fixed4 fragBloom ( v2f_simple i ) : SV_Target
73 {
74 #if UNITY_UV_STARTS_AT_TOP
75
76 fixed4 color = tex2D(_MainTex, i.uv2);
77 return color + tex2D(_Bloom, i.uv);
78
79 #else
80
81 fixed4 color = tex2D(_MainTex, i.uv);
82 return color + tex2D(_Bloom, i.uv);
83
84 #endif
85 }
86
87 fixed4 fragDownsample ( v2f_tap i ) : SV_Target
88 {
89 fixed4 color = tex2D (_MainTex, i.uv20);
90 color += tex2D (_MainTex, i.uv21);
91 color += tex2D (_MainTex, i.uv22);
92 color += tex2D (_MainTex, i.uv23);
93 return max(color/4 - THRESHHOLD, 0) * ONE_MINUS_THRESHHOLD_TIMES_INTENSITY;
94 }
95
96 // weight curves
97
98 static const half curve[7] = { 0.0205, 0.0855, 0.232, 0.324, 0.232, 0.0855, 0.0205 }; // gauss'ish blur weights
99
100 static const half4 curve4[7] = { half4(0.0205,0.0205,0.0205,0), half4(0.0855,0.0855,0.0855,0), half4(0.232,0.232,0.232,0),
101 half4(0.324,0.324,0.324,1), half4(0.232,0.232,0.232,0), half4(0.0855,0.0855,0.0855,0), half4(0.0205,0.0205,0.0205,0) };
102
103 struct v2f_withBlurCoords8
104 {
105 float4 pos : SV_POSITION;
106 half4 uv : TEXCOORD0;
107 half2 offs : TEXCOORD1;
108 };
109
110 struct v2f_withBlurCoordsSGX
111 {
112 float4 pos : SV_POSITION;
113 half2 uv : TEXCOORD0;
114 half4 offs[3] : TEXCOORD1;
115 };
116
117 v2f_withBlurCoords8 vertBlurHorizontal (appdata_img v)
118 {
119 v2f_withBlurCoords8 o;
120 o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
121
122 o.uv = half4(v.texcoord.xy,1,1);
123 o.offs = _MainTex_TexelSize.xy * half2(1.0, 0.0) * _Parameter.x;
124
125 return o;
126 }
127
128 v2f_withBlurCoords8 vertBlurVertical (appdata_img v)
129 {
130 v2f_withBlurCoords8 o;
131 o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
132
133 o.uv = half4(v.texcoord.xy,1,1);
134 o.offs = _MainTex_TexelSize.xy * half2(0.0, 1.0) * _Parameter.x;
135
136 return o;
137 }
138
139 half4 fragBlur8 ( v2f_withBlurCoords8 i ) : SV_Target
140 {
141 half2 uv = i.uv.xy;
142 half2 netFilterWidth = i.offs;
143 half2 coords = uv - netFilterWidth * 3.0;
144
145 half4 color = 0;
146 for( int l = 0; l < 7; l++ )
147 {
148 half4 tap = tex2D(_MainTex, coords);
149 color += tap * curve4[l];
150 coords += netFilterWidth;
151 }
152 return color;
153 }
154
155
156 v2f_withBlurCoordsSGX vertBlurHorizontalSGX (appdata_img v)
157 {
158 v2f_withBlurCoordsSGX o;
159 o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
160
161 o.uv = v.texcoord.xy;
162 half2 netFilterWidth = _MainTex_TexelSize.xy * half2(1.0, 0.0) * _Parameter.x;
163 half4 coords = -netFilterWidth.xyxy * 3.0;
164
165 o.offs[0] = v.texcoord.xyxy + coords * half4(1.0h,1.0h,-1.0h,-1.0h);
166 coords += netFilterWidth.xyxy;
167 o.offs[1] = v.texcoord.xyxy + coords * half4(1.0h,1.0h,-1.0h,-1.0h);
168 coords += netFilterWidth.xyxy;
169 o.offs[2] = v.texcoord.xyxy + coords * half4(1.0h,1.0h,-1.0h,-1.0h);
170
171 return o;
172 }
173
174 v2f_withBlurCoordsSGX vertBlurVerticalSGX (appdata_img v)
175 {
176 v2f_withBlurCoordsSGX o;
177 o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
178
179 o.uv = half4(v.texcoord.xy,1,1);
180 half2 netFilterWidth = _MainTex_TexelSize.xy * half2(0.0, 1.0) * _Parameter.x;
181 half4 coords = -netFilterWidth.xyxy * 3.0;
182
183 o.offs[0] = v.texcoord.xyxy + coords * half4(1.0h,1.0h,-1.0h,-1.0h);
184 coords += netFilterWidth.xyxy;
185 o.offs[1] = v.texcoord.xyxy + coords * half4(1.0h,1.0h,-1.0h,-1.0h);
186 coords += netFilterWidth.xyxy;
187 o.offs[2] = v.texcoord.xyxy + coords * half4(1.0h,1.0h,-1.0h,-1.0h);
188
189 return o;
190 }
191
192 half4 fragBlurSGX ( v2f_withBlurCoordsSGX i ) : SV_Target
193 {
194 half2 uv = i.uv.xy;
195
196 half4 color = tex2D(_MainTex, i.uv) * curve4[3];
197
198 for( int l = 0; l < 3; l++ )
199 {
200 half4 tapA = tex2D(_MainTex, i.offs[l].xy);
201 half4 tapB = tex2D(_MainTex, i.offs[l].zw);
202 color += (tapA + tapB) * curve4[l];
203 }
204
205 return color;
206
207 }
208
209 ENDCG
210
211 SubShader {
212 ZTest Off Cull Off ZWrite Off Blend Off
213
214 // 0
215 Pass {
216
217 CGPROGRAM
218 #pragma vertex vertBloom
219 #pragma fragment fragBloom
220
221 ENDCG
222
223 }
224
225 // 1
226 Pass {
227
228 CGPROGRAM
229
230 #pragma vertex vert4Tap
231 #pragma fragment fragDownsample
232
233 ENDCG
234
235 }
236
237 // 2
238 Pass {
239 ZTest Always
240 Cull Off
241
242 CGPROGRAM
243
244 #pragma vertex vertBlurVertical
245 #pragma fragment fragBlur8
246
247 ENDCG
248 }
249
250 // 3
251 Pass {
252 ZTest Always
253 Cull Off
254
255 CGPROGRAM
256
257 #pragma vertex vertBlurHorizontal
258 #pragma fragment fragBlur8
259
260 ENDCG
261 }
262
263 // alternate blur
264 // 4
265 Pass {
266 ZTest Always
267 Cull Off
268
269 CGPROGRAM
270
271 #pragma vertex vertBlurVerticalSGX
272 #pragma fragment fragBlurSGX
273
274 ENDCG
275 }
276
277 // 5
278 Pass {
279 ZTest Always
280 Cull Off
281
282 CGPROGRAM
283
284 #pragma vertex vertBlurHorizontalSGX
285 #pragma fragment fragBlurSGX
286
287 ENDCG
288 }
289 }
290
291 FallBack Off
292 }