1#version 130
2
3// needs version 130 for textureLod
4
5// license:BSD-3-Clause
6// copyright-holders:Ryan Holtz,ImJezze
7//-----------------------------------------------------------------------------
8// Bloom Effect
9//-----------------------------------------------------------------------------
10
11#if defined(VERTEX)
12
13#if __VERSION__ >= 130
14#define COMPAT_VARYING out
15#define COMPAT_ATTRIBUTE in
16#define COMPAT_TEXTURE texture
17#else
18#define COMPAT_VARYING varying
19#define COMPAT_ATTRIBUTE attribute
20#define COMPAT_TEXTURE texture2D
21#endif
22
23#ifdef GL_ES
24#define COMPAT_PRECISION mediump
25#else
26#define COMPAT_PRECISION
27#endif
28
29COMPAT_ATTRIBUTE vec4 VertexCoord;
30COMPAT_ATTRIBUTE vec4 COLOR;
31COMPAT_ATTRIBUTE vec4 TexCoord;
32COMPAT_VARYING vec4 COL0;
33COMPAT_VARYING vec4 TEX0;
34
35vec4 _oPosition1;
36uniform mat4 MVPMatrix;
37uniform COMPAT_PRECISION int FrameDirection;
38uniform COMPAT_PRECISION int FrameCount;
39uniform COMPAT_PRECISION vec2 OutputSize;
40uniform COMPAT_PRECISION vec2 TextureSize;
41uniform COMPAT_PRECISION vec2 InputSize;
42
43// compatibility #defines
44#define vTexCoord TEX0.xy
45#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
46#define OutSize vec4(OutputSize, 1.0 / OutputSize)
47
48void main()
49{
50    gl_Position = MVPMatrix * VertexCoord;
51    TEX0.xy = TexCoord.xy;
52}
53
54#elif defined(FRAGMENT)
55
56#ifdef GL_ES
57#ifdef GL_FRAGMENT_PRECISION_HIGH
58precision highp float;
59#else
60precision mediump float;
61#endif
62#define COMPAT_PRECISION mediump
63#else
64#define COMPAT_PRECISION
65#endif
66
67#if __VERSION__ >= 130
68#define COMPAT_VARYING in
69#define COMPAT_TEXTURE texture
70out COMPAT_PRECISION vec4 FragColor;
71#else
72#define COMPAT_VARYING varying
73#define FragColor gl_FragColor
74#define COMPAT_TEXTURE texture2D
75#endif
76
77uniform COMPAT_PRECISION int FrameDirection;
78uniform COMPAT_PRECISION int FrameCount;
79uniform COMPAT_PRECISION vec2 OutputSize;
80uniform COMPAT_PRECISION vec2 TextureSize;
81uniform COMPAT_PRECISION vec2 InputSize;
82uniform sampler2D Texture;
83COMPAT_VARYING vec4 TEX0;
84
85// compatibility #defines
86#define Source Texture
87#define vTexCoord TEX0.xy
88
89#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
90#define OutSize vec4(OutputSize, 1.0 / OutputSize)
91
92// effect toggles and multi
93uniform COMPAT_PRECISION float bloomtoggle, ntscsignal, scanlinetoggle, chromatoggle,
94   distortiontoggle, screenscale_x, screenscale_y, screenoffset_x, screenoffset_y, swapxy;
95// bloom params
96uniform COMPAT_PRECISION float bloomblendmode, bloomscale, bloomoverdrive_r, bloomoverdrive_g, bloomoverdrive_b,
97   level0weight, level1weight, level2weight, level3weight, level4weight, level5weight, level6weight, level7weight, level8weight;
98//	uniform COMPAT_PRECISION float vectorscreen; // unused
99// post params
100uniform COMPAT_PRECISION float mask_width, mask_height, mask_offset_x, mask_offset_y, preparebloom, shadowtilemode,
101   power_r, power_g, power_b, floor_r, floor_g, floor_b, chromamode, conversiongain_x, conversiongain_y, conversiongain_z,
102   humbaralpha, backcolor_r, backcolor_g, backcolor_b, shadowalpha, shadowcount_x, shadowcount_y, shadowuv_x, shadowuv_y;
103// ntsc params // doesn't work here, so commenting all of them.
104// uniform COMPAT_PRECISION float avalue, bvalue, ccvalue, ovalue, pvalue, scantime, notchhalfwidth, yfreqresponse, ifreqresponse, qfreqresponse, signaloffset;
105// color params
106uniform COMPAT_PRECISION float col_red, col_grn, col_blu, col_offset_x, col_offset_y, col_offset_z, col_scale_x,
107   col_scale_y, col_scale_z, col_saturation;
108// deconverge params
109uniform COMPAT_PRECISION float converge_x_r, converge_x_g, converge_x_b, converge_y_r, converge_y_g, converge_y_b,
110   radial_conv_x_r, radial_conv_x_g, radial_conv_x_b, radial_conv_y_r, radial_conv_y_g, radial_conv_y_b;
111// scanline params
112uniform COMPAT_PRECISION float scanlinealpha, scanlinescale, scanlineheight, scanlinevariation, scanlineoffset,
113   scanlinebrightscale, scanlinebrightoffset;
114// defocus params
115uniform COMPAT_PRECISION float defocus_x, defocus_y;
116// phosphor params
117uniform COMPAT_PRECISION float deltatime, phosphor_r, phosphor_g, phosphor_b, phosphortoggle;
118// chroma params
119uniform COMPAT_PRECISION float ygain_r, ygain_g, ygain_b, chromaa_x, chromaa_y, chromab_x, chromab_y, chromac_x, chromac_y;
120// distortion params
121uniform COMPAT_PRECISION float distortion_amount, cubic_distortion_amount, distort_corner_amount, round_corner_amount,
122   smooth_border_amount, vignette_amount, reflection_amount, reflection_col_r, reflection_col_g, reflection_col_b;
123// vector params //doesn't work here, so commenting all of them.
124// uniform COMPAT_PRECISION float timeratio, timescale, lengthratio, lengthscale, beamsmooth;
125// I'm not going to bother supporting implementations without runtime parameters.
126
127const float vectorscreen = 0.0;
128bool VectorScreen = bool(vectorscreen);
129
130bool BloomToggle = bool(bloomtoggle);
131
132float Level0Weight = level0weight;
133float Level1Weight = level1weight;
134float Level2Weight = level2weight;
135float Level3Weight = level3weight;
136float Level4Weight = level4weight;
137float Level5Weight = level5weight;
138float Level6Weight = level6weight;
139float Level7Weight = level7weight;
140float Level8Weight = level8weight;
141
142int BloomBlendMode = int(bloomblendmode); // 0 brighten, 1 darken
143float BloomScale = bloomscale;
144vec3 BloomOverdrive = vec3(bloomoverdrive_r, bloomoverdrive_g, bloomoverdrive_b);
145
146//-----------------------------------------------------------------------------
147// Constants
148//-----------------------------------------------------------------------------
149
150const float E = 2.7182817f;
151const float Gelfond = 23.140692f; // e^pi (Gelfond constant)
152const float GelfondSchneider = 2.6651442f; // 2^sqrt(2) (Gelfond-Schneider constant)
153
154//-----------------------------------------------------------------------------
155// Functions
156//-----------------------------------------------------------------------------
157
158// www.stackoverflow.com/questions/5149544/can-i-generate-a-random-number-inside-a-pixel-shader/
159float random(vec2 seed)
160{
161	// irrationals for pseudo randomness
162	vec2 i = vec2(Gelfond, GelfondSchneider);
163
164	return fract(cos(dot(seed, i)) * 123456.0);
165}
166
167//-----------------------------------------------------------------------------
168// Bloom Vertex Shader
169//-----------------------------------------------------------------------------
170
171#define DiffuseSampler Source
172#define BloomCoord vTexCoord
173
174#define BloomSamplerA Source
175#define BloomSamplerB Source
176#define BloomSamplerC Source
177#define BloomSamplerD Source
178#define BloomSamplerE Source
179#define BloomSamplerF Source
180#define BloomSamplerG Source
181#define BloomSamplerH Source
182
183// vector screen uses twice -1 as many bloom levels
184#define BloomSamplerI Source
185#define BloomSamplerJ Source
186#define BloomSamplerK Source
187#define BloomSamplerL Source
188#define BloomSamplerM Source
189#define BloomSamplerN Source
190#define BloomSamplerO Source
191
192vec3 GetNoiseFactor(vec3 n, float random)
193{
194	// smaller n become more noisy
195	vec3 NoiseFactor;
196	NoiseFactor.x = 1.0 + random * max(0.0, 0.25 * pow(E, -8. * n.x));
197	NoiseFactor.y = 1.0 + random * max(0.0, 0.25 * pow(E, -8. * n.y));
198	NoiseFactor.z = 1.0 + random * max(0.0, 0.25 * pow(E, -8. * n.z));
199	return NoiseFactor;
200}
201
202void main()
203{
204   if(!BloomToggle)
205   {
206      FragColor = COMPAT_TEXTURE(Source, vTexCoord);
207      return;
208   }
209   else
210   {
211      vec3 texel = COMPAT_TEXTURE(DiffuseSampler, vTexCoord).rgb;
212      // use mipmapping for cheap bloom
213      vec3 texelA = textureLod(BloomSamplerA, BloomCoord.xy, 1.0).rgb;
214      vec3 texelB = textureLod(BloomSamplerB, BloomCoord.xy, 2.0).rgb;
215      vec3 texelC = textureLod(BloomSamplerC, BloomCoord.xy, 3.0).rgb;
216      vec3 texelD = textureLod(BloomSamplerD, BloomCoord.xy, 4.0).rgb;
217      vec3 texelE = textureLod(BloomSamplerE, BloomCoord.xy, 5.0).rgb;
218      vec3 texelF = textureLod(BloomSamplerF, BloomCoord.xy, 6.0).rgb;
219      vec3 texelG = textureLod(BloomSamplerG, BloomCoord.xy, 7.0).rgb;
220      vec3 texelH = textureLod(BloomSamplerH, BloomCoord.xy, 8.0).rgb;
221
222      vec3 texelI = vec3(0.0, 0.0, 0.0);
223      vec3 texelJ = vec3(0.0, 0.0, 0.0);
224      vec3 texelK = vec3(0.0, 0.0, 0.0);
225      vec3 texelL = vec3(0.0, 0.0, 0.0);
226      vec3 texelM = vec3(0.0, 0.0, 0.0);
227      vec3 texelN = vec3(0.0, 0.0, 0.0);
228      vec3 texelO = vec3(0.0, 0.0, 0.0);
229
230
231      // vector screen uses twice -1 as many bloom levels
232      if (VectorScreen)
233      {
234         texelI = COMPAT_TEXTURE(BloomSamplerI, BloomCoord.xy).rgb;
235         texelJ = COMPAT_TEXTURE(BloomSamplerJ, BloomCoord.xy).rgb;
236         texelK = COMPAT_TEXTURE(BloomSamplerK, BloomCoord.xy).rgb;
237         texelL = COMPAT_TEXTURE(BloomSamplerL, BloomCoord.xy).rgb;
238         texelM = COMPAT_TEXTURE(BloomSamplerM, BloomCoord.xy).rgb;
239         texelN = COMPAT_TEXTURE(BloomSamplerN, BloomCoord.xy).rgb;
240         texelO = COMPAT_TEXTURE(BloomSamplerO, BloomCoord.xy).rgb;
241      }
242
243      vec3 blend;
244
245      // brighten
246      if (BloomBlendMode < 0.5)
247      {
248         vec3 bloom = vec3(0.0, 0.0, 0.0);
249
250         texel *= Level0Weight;
251
252         if (VectorScreen)
253         {
254            bloom += texelA * Level1Weight;
255            bloom += texelB * Level2Weight;
256            bloom += texelC * Level3Weight;
257            bloom += texelD * Level4Weight;
258            bloom += texelE * Level5Weight;
259            bloom += texelF * Level6Weight;
260            bloom += texelG * Level7Weight;
261            bloom += texelH * Level8Weight;
262         }
263         // vector screen uses twice -1 as many bloom levels
264         else
265         {
266            bloom += texelA * (Level1Weight);
267            bloom += texelB * (Level1Weight + Level2Weight) * 0.5;
268            bloom += texelC * (Level2Weight);
269            bloom += texelD * (Level2Weight + Level3Weight) * 0.5;
270            bloom += texelE * (Level3Weight);
271            bloom += texelF * (Level3Weight + Level4Weight) * 0.5;
272            bloom += texelG * (Level4Weight);
273            bloom += texelH * (Level4Weight + Level5Weight) * 0.5;
274            bloom += texelI * (Level5Weight);
275            bloom += texelJ * (Level5Weight + Level6Weight) * 0.5;
276            bloom += texelK * (Level6Weight);
277            bloom += texelL * (Level6Weight + Level7Weight) * 0.5;
278            bloom += texelM * (Level7Weight);
279            bloom += texelN * (Level7Weight + Level8Weight) * 0.5;
280            bloom += texelO * (Level8Weight);
281         }
282
283         bloom *= BloomScale;
284
285         vec3 bloomOverdrive;
286         bloomOverdrive.r = max(0.0, texel.r + bloom.r - 1.0) * BloomOverdrive.r;
287         bloomOverdrive.g = max(0.0, texel.g + bloom.g - 1.0) * BloomOverdrive.g;
288         bloomOverdrive.b = max(0.0, texel.b + bloom.b - 1.0) * BloomOverdrive.b;
289
290         bloom.r += bloomOverdrive.g * 0.5;
291         bloom.r += bloomOverdrive.b * 0.5;
292         bloom.g += bloomOverdrive.r * 0.5;
293         bloom.g += bloomOverdrive.b * 0.5;
294         bloom.b += bloomOverdrive.r * 0.5;
295         bloom.b += bloomOverdrive.g * 0.5;
296
297         vec2 NoiseCoord = vTexCoord;
298         vec3 NoiseFactor = GetNoiseFactor(bloom, random(NoiseCoord));
299
300         blend = texel + bloom * NoiseFactor;
301      }
302
303      // darken
304      else
305      {
306         texelA = min(texel, texelA);
307         texelB = min(texel, texelB);
308         texelC = min(texel, texelC);
309         texelD = min(texel, texelD);
310         texelE = min(texel, texelE);
311         texelF = min(texel, texelF);
312         texelG = min(texel, texelG);
313         texelH = min(texel, texelH);
314
315         blend = texel * Level0Weight;
316         blend = mix(blend, texelA, Level1Weight * BloomScale);
317         blend = mix(blend, texelB, Level2Weight * BloomScale);
318         blend = mix(blend, texelC, Level3Weight * BloomScale);
319         blend = mix(blend, texelD, Level4Weight * BloomScale);
320         blend = mix(blend, texelE, Level5Weight * BloomScale);
321         blend = mix(blend, texelF, Level6Weight * BloomScale);
322         blend = mix(blend, texelG, Level7Weight * BloomScale);
323         blend = mix(blend, texelH, Level8Weight * BloomScale);
324      }
325
326       FragColor = vec4(blend, 1.0);
327   }
328}
329#endif
330