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