├── Ls_Advect.1.glsl ├── Ls_Advect.1.glsl.p ├── Ls_Advect.2.glsl ├── Ls_Advect.xml ├── Ls_Airglow.01.glsl ├── Ls_Airglow.01.glsl.p ├── Ls_Airglow.02.glsl ├── Ls_Airglow.03.glsl ├── Ls_Airglow.04.glsl ├── Ls_Airglow.05.glsl ├── Ls_Airglow.06.glsl ├── Ls_Airglow.07.glsl ├── Ls_Airglow.08.glsl ├── Ls_Airglow.09.glsl ├── Ls_Airglow.10.glsl ├── Ls_Airglow.11.glsl ├── Ls_Airglow.12.glsl ├── Ls_Airglow.13.glsl ├── Ls_Airglow.14.glsl ├── Ls_Airglow.15.glsl ├── Ls_Airglow.16.glsl ├── Ls_Airglow.17.glsl ├── Ls_Airglow.xml ├── Ls_Airglow_builder.py ├── Ls_Ash.1.glsl ├── Ls_Ash.1.glsl.p ├── Ls_Ash.2.glsl ├── Ls_Ash.3.glsl ├── Ls_Ash.xml ├── Ls_Bevel.1.glsl ├── Ls_Bevel.1.glsl.p ├── Ls_Bevel.2.glsl ├── Ls_Bevel.3.glsl ├── Ls_Bevel.4.glsl ├── Ls_Bevel.5.glsl ├── Ls_Bevel.6.glsl ├── Ls_Bevel.xml ├── Ls_Chips.glsl ├── Ls_Chips.glsl.p ├── Ls_Chips.hip ├── Ls_Chips.mx ├── Ls_Chips.textureGrid.exr ├── Ls_Chips.xml ├── Ls_Colourmatrix.glsl ├── Ls_Colourmatrix.glsl.p ├── Ls_Colourmatrix.xml ├── Ls_Colourspace.glsl ├── Ls_Colourspace.glsl.p ├── Ls_Colourspace.xml ├── Ls_Contacts.glsl ├── Ls_Contacts.glsl.p ├── Ls_Contacts.xml ├── Ls_Dilate.1.glsl ├── Ls_Dilate.1.glsl.p ├── Ls_Dilate.2.glsl ├── Ls_Dilate.xml ├── Ls_Dollface.1.glsl ├── Ls_Dollface.1.glsl.p ├── Ls_Dollface.2.glsl ├── Ls_Dollface.xml ├── Ls_FXAA.glsl ├── Ls_FXAA.glsl.p ├── Ls_FXAA.xml ├── Ls_Filmstrip.glsl ├── Ls_Filmstrip.glsl.p ├── Ls_Filmstrip.xml ├── Ls_Fireflies.glsl ├── Ls_Fireflies.glsl.p ├── Ls_Fireflies.xml ├── Ls_Fireflies_sortingnetwork.pl ├── Ls_Flock.1.glsl ├── Ls_Flock.1.glsl.p ├── Ls_Flock.2.glsl ├── Ls_Flock.xml ├── Ls_Fluid.1.glsl ├── Ls_Fluid.1.glsl.p ├── Ls_Fluid.10.glsl ├── Ls_Fluid.2.glsl ├── Ls_Fluid.3.glsl ├── Ls_Fluid.4.glsl ├── Ls_Fluid.5.glsl ├── Ls_Fluid.6.glsl ├── Ls_Fluid.7.glsl ├── Ls_Fluid.8.glsl ├── Ls_Fluid.9.glsl ├── Ls_Fluid.xml ├── Ls_Glint.1.glsl ├── Ls_Glint.1.glsl.p ├── Ls_Glint.2.glsl ├── Ls_Glint.3.glsl ├── Ls_Glint.xml ├── Ls_GlueP.glsl ├── Ls_GlueP.glsl.p ├── Ls_GlueP.xml ├── Ls_Lumps.1.glsl ├── Ls_Lumps.1.glsl.p ├── Ls_Lumps.10.glsl ├── Ls_Lumps.2.glsl ├── Ls_Lumps.3.glsl ├── Ls_Lumps.4.glsl ├── Ls_Lumps.5.glsl ├── Ls_Lumps.6.glsl ├── Ls_Lumps.7.glsl ├── Ls_Lumps.8.glsl ├── Ls_Lumps.9.glsl ├── Ls_Lumps.xml ├── Ls_NaNfix.glsl ├── Ls_NaNfix.glsl.p ├── Ls_NaNfix.xml ├── Ls_Nail.glsl ├── Ls_Nail.glsl.p ├── Ls_Nail.xml ├── Ls_Pentatone.glsl ├── Ls_Pentatone.xml ├── Ls_Poly.01.glsl ├── Ls_Poly.01.glsl.p ├── Ls_Poly.02.glsl ├── Ls_Poly.03.glsl ├── Ls_Poly.04.glsl ├── Ls_Poly.05.glsl ├── Ls_Poly.06.glsl ├── Ls_Poly.07.glsl ├── Ls_Poly.08.glsl ├── Ls_Poly.09.glsl ├── Ls_Poly.10.glsl ├── Ls_Poly.11.glsl ├── Ls_Poly.12.glsl ├── Ls_Poly.13.glsl ├── Ls_Poly.14.glsl ├── Ls_Poly.15.glsl ├── Ls_Poly.16.glsl ├── Ls_Poly.17.glsl ├── Ls_Poly.18.glsl ├── Ls_Poly.19.glsl ├── Ls_Poly.20.glsl ├── Ls_Poly.21.glsl ├── Ls_Poly.22.glsl ├── Ls_Poly.23.glsl ├── Ls_Poly.24.glsl ├── Ls_Poly.25.glsl ├── Ls_Poly.26.glsl ├── Ls_Poly.27.glsl ├── Ls_Poly.28.glsl ├── Ls_Poly.29.glsl ├── Ls_Poly.xml ├── Ls_Poly_builder.py ├── Ls_Posmatte.glsl ├── Ls_Posmatte.glsl.p ├── Ls_Posmatte.xml ├── Ls_Relax.glsl ├── Ls_Relax.glsl.p ├── Ls_Relax.xml ├── Ls_RndmGrade.glsl ├── Ls_RndmGrade.glsl.p ├── Ls_RndmGrade.xml ├── Ls_Shadowplate.1.glsl ├── Ls_Shadowplate.1.glsl.p ├── Ls_Shadowplate.2.glsl ├── Ls_Shadowplate.3.glsl ├── Ls_Shadowplate.4.glsl ├── Ls_Shadowplate.xml ├── Ls_Splineblur.1.glsl ├── Ls_Splineblur.1.glsl.p ├── Ls_Splineblur.2.glsl ├── Ls_Splineblur.xml ├── Ls_Stickon.1.glsl ├── Ls_Stickon.1.glsl.p ├── Ls_Stickon.2.glsl ├── Ls_Stickon.xml ├── Ls_Sweat.1.glsl ├── Ls_Sweat.1.glsl.p ├── Ls_Sweat.2.glsl ├── Ls_Sweat.3.glsl ├── Ls_Sweat.4.glsl ├── Ls_Sweat.xml ├── Ls_Tinyplanet.glsl ├── Ls_Tinyplanet.glsl.p ├── Ls_Tinyplanet.xml ├── Ls_UVewa.glsl ├── Ls_UVewa.glsl.p ├── Ls_UVewa.xml ├── Ls_Vignette.glsl ├── Ls_Vignette.glsl.p ├── Ls_Vignette.xml ├── Ls_Vops.glsl ├── Ls_Vops.glsl.p ├── Ls_Vops.xml ├── Ls_Wireless.glsl ├── Ls_Wireless.glsl.p └── Ls_Wireless.xml /Ls_Advect.1.glsl: -------------------------------------------------------------------------------- 1 | // Pass 1: make the vectors 2 | // lewis@lewissaunders.com 3 | // TODO: 4 | // o Pre-blur input in case of kinks? 5 | 6 | uniform sampler2D map; 7 | uniform float adsk_result_w, adsk_result_h, ksize; 8 | uniform bool radial, directvectors; 9 | 10 | void main() { 11 | vec2 xy = gl_FragCoord.xy; 12 | 13 | // Factor to convert pixels to [0,1] texture coords 14 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 15 | 16 | vec2 d = vec2(0.0); 17 | 18 | if(directvectors) { 19 | // Map input is already vectors, yay! 20 | d = texture2D(map, xy * px).xy; 21 | if(radial) { 22 | // Rotate 90 degrees 23 | d = vec2(-d.y, d.x); 24 | } 25 | gl_FragColor = vec4(d.x, d.y, 0.0, 1.0); 26 | return; 27 | } 28 | 29 | // Convolve by x and y Sobel matrices to get gradient vector 30 | d.x = 1.0 * texture2D(map, (xy + ksize * vec2(-1.0, -1.0)) * px).g; 31 | d.x += 2.0 * texture2D(map, (xy + ksize * vec2(-1.0, 0.0)) * px).g; 32 | d.x += 1.0 * texture2D(map, (xy + ksize * vec2(-1.0, +1.0)) * px).g; 33 | d.x += -1.0 * texture2D(map, (xy + ksize * vec2(+1.0, -1.0)) * px).g; 34 | d.x += -2.0 * texture2D(map, (xy + ksize * vec2(+1.0, 0.0)) * px).g; 35 | d.x += -1.0 * texture2D(map, (xy + ksize * vec2(+1.0, +1.0)) * px).g; 36 | d.y += 1.0 * texture2D(map, (xy + ksize * vec2(-1.0, -1.0)) * px).g; 37 | d.y += 2.0 * texture2D(map, (xy + ksize * vec2( 0.0, -1.0)) * px).g; 38 | d.y += 1.0 * texture2D(map, (xy + ksize * vec2(+1.0, -1.0)) * px).g; 39 | d.y += -1.0 * texture2D(map, (xy + ksize * vec2(-1.0, +1.0)) * px).g; 40 | d.y += -2.0 * texture2D(map, (xy + ksize * vec2( 0.0, +1.0)) * px).g; 41 | d.y += -1.0 * texture2D(map, (xy + ksize * vec2(+1.0, +1.0)) * px).g; 42 | 43 | if(!radial) { 44 | // Rotate 90 degrees 45 | d = vec2(-d.y, d.x); 46 | } 47 | 48 | // Bit of a bodge factor right here 49 | d *= 32.0 / ksize; 50 | 51 | // Output vectors for second pass 52 | gl_FragColor = vec4(d.x, d.y, 0.0, 1.0); 53 | } 54 | -------------------------------------------------------------------------------- /Ls_Advect.1.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Advect.1.glsl.p -------------------------------------------------------------------------------- /Ls_Advect.2.glsl: -------------------------------------------------------------------------------- 1 | // Pass 2: do the displace 2 | // TODO: 3 | // o Diffuse samples out along/around path direction? 4 | // lewis@lewissaunders.com 5 | 6 | uniform sampler2D front, map, adsk_results_pass1; 7 | uniform float adsk_result_w, adsk_result_h, blength, spacing, maxlength, sidestep; 8 | uniform vec2 offset; 9 | uniform int samples, oversamples; 10 | uniform vec2 bl, tr; 11 | uniform bool radial, vectors, normalize, adsk_degrade, fadeout, fadein; 12 | 13 | void main() { 14 | vec2 xy = gl_FragCoord.xy; 15 | 16 | // Factor to convert pixels to [0,1] texture coords 17 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 18 | 19 | // Get vectors from previous pass 20 | vec2 d = texture2D(adsk_results_pass1, xy * px).xy; 21 | 22 | if(vectors) { 23 | // Return the vectors, not the blur 24 | if(normalize) { 25 | // Bodge factor for a resonable result from PixelSpread 26 | d /= 4.0; 27 | d += 0.5; 28 | gl_FragColor = vec4(d.x, d.y, 1.0, 1.0); 29 | } else { 30 | gl_FragColor = vec4(d.x, d.y, 0.0, 1.0); 31 | } 32 | return; 33 | } 34 | 35 | // Crop 36 | vec2 xyn = xy * px; 37 | if((xyn.x < bl.x) || (xyn.x > tr.x)) { 38 | gl_FragColor = texture2D(front, xyn); 39 | gl_FragColor.a = 0.0; 40 | return; 41 | } 42 | if((xyn.y < bl.y) || (xyn.y > tr.y)) { 43 | gl_FragColor = texture2D(front, xyn); 44 | gl_FragColor.a = 0.0; 45 | return; 46 | } 47 | 48 | float sam = float(samples); 49 | if(adsk_degrade) { 50 | sam /= 4.0; 51 | } 52 | 53 | vec4 acc = vec4(0.0); 54 | for(int j = 0; j < oversamples; j++) { 55 | for(int k = 0; k < oversamples; k++) { 56 | // Starting point for this sample 57 | xy = gl_FragCoord.xy + spacing * vec2(float(j) / (float(oversamples) + 1.0), float(k) / (float(oversamples) + 1.0)); 58 | float dist = 0.0; 59 | // Walk along path by sampling vector image, moving, sampling, moving... 60 | for(float i = 0.0; i < sam; i++) { 61 | d = texture2D(adsk_results_pass1, xy * px).xy; 62 | if(length(d) == 0.0) { 63 | // No gradient at this point in the map, early out 64 | break; 65 | } 66 | xy += d * (blength/sam) + blength * sidestep/1000.0 * vec2(-d.y, d.x) + (blength/32.0) * offset; 67 | dist += length(d * (blength/sam)); 68 | } 69 | // Sample front image where our walk ended up 70 | acc.rgb += texture2D(front, xy * px).rgb; 71 | 72 | // Diffusion? 73 | /*for(float ix = 0.0; ix < diffusion; ix++) { 74 | for(float iy = 0.0; iy < diffusion; iy++) { 75 | acc.rgb += texture2D(front, (xy + vec2(ix, iy) * dist * px)).rgb * length(vec2(ix, iy)-vec2(diffusion/2.0, diffusion/2.0)) / (diffusion * diffusion * 32.0); 76 | } 77 | }*/ 78 | 79 | // Length we've travelled to the matte output 80 | acc.a += dist * (blength/32.0); 81 | } 82 | } 83 | acc /= float(oversamples * oversamples); 84 | 85 | if(fadeout) { 86 | acc.rgb *= 1.0 - smoothstep(0.0, 1.0, abs(acc.a/(maxlength*blength+0.0001))); 87 | } 88 | if(fadein) { 89 | acc.rgb *= smoothstep(0.0, 1.0, abs(acc.a/(maxlength*blength))); 90 | } 91 | 92 | gl_FragColor = acc; 93 | } 94 | -------------------------------------------------------------------------------- /Ls_Airglow.01.glsl: -------------------------------------------------------------------------------- 1 | // Airglow 2 | // This has a lot of passes. I used a little Python script to generate 3 | // most of them, because they're just a lot of Gaussian blurring 4 | // See Ls_Airglow_builder.py 5 | // 6 | // TODO: 7 | // o Clamp when in video de-tonemapping mode 8 | // o Negate image before/after for "black promist" effect 9 | // 10 | // Pass 1: multiply front RGB and glow source A together 11 | // lewis@lewissaunders.com 12 | 13 | uniform sampler2D front, source; 14 | uniform float adsk_result_w, adsk_result_h; 15 | uniform int colourspace; 16 | vec3 adsk_log2scene(vec3 log); 17 | vec3 adsk_scene2log(vec3 lin); 18 | 19 | // Convert from linear to video a simple, invertible way, but with smooth highlight rolloff 20 | vec3 tonemap(vec3 x) { 21 | x = max(x, 0.0); 22 | x = adsk_scene2log(x); 23 | x -= 95.0 / 1023.0; 24 | x *= 3.14159265; 25 | x = cos(x); 26 | x = 1.0 - x; 27 | x /= 2.0; 28 | x = max(x, 0.0); 29 | return x; 30 | } 31 | 32 | // Convert from video to linear, the inverse of above - unrolls highlights to above 1.0 33 | vec3 untonemap(vec3 x) { 34 | x = max(x, 0.0); 35 | x *= 2.0; 36 | x = 1.0 - x; 37 | x = acos(x); 38 | x /= 3.14159265; 39 | x += 95.0 / 1023.0; 40 | x = max(x, 0.0); 41 | x = adsk_log2scene(x); 42 | x = max(x, 0.0); 43 | return x; 44 | } 45 | 46 | void main() { 47 | vec2 res = vec2(adsk_result_w, adsk_result_h); 48 | vec2 xy = gl_FragCoord.xy / res; 49 | float m = texture2D(source, xy).b; 50 | vec3 f = texture2D(front, xy).rgb; 51 | 52 | // Convert to linear 53 | if(colourspace == 0) { 54 | // Log 55 | f = adsk_log2scene(f); 56 | } else if(colourspace == 1) { 57 | // Video - inverse tonemapping to get some highlights back 58 | f = untonemap(f); 59 | } else if(colourspace == 2) { 60 | // Video (gamma only) 61 | f = max(f, 0.0); 62 | f.r = pow(f.r, 2.4); 63 | f.g = pow(f.g, 2.4); 64 | f.b = pow(f.b, 2.4); 65 | } else if(colourspace == 3) { 66 | // Linear 67 | f = f; 68 | } 69 | 70 | f *= m; 71 | 72 | gl_FragColor = vec4(f, m); 73 | } 74 | -------------------------------------------------------------------------------- /Ls_Airglow.01.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Airglow.01.glsl.p -------------------------------------------------------------------------------- /Ls_Airglow.02.glsl: -------------------------------------------------------------------------------- 1 | // Airglow pass 2: accelerated Gaussian blur, size / 1.000000, direction vec2(1.0, 0.0) 2 | // lewis@lewissaunders.com 3 | 4 | #extension GL_ARB_shader_texture_lod : enable 5 | 6 | uniform sampler2D strength, adsk_results_pass1; 7 | uniform float size, quality; 8 | uniform float adsk_result_w, adsk_result_h; 9 | 10 | // Return a 1D Gaussian blur from texture tex, sampling from mipmap level lod 11 | // xy: centre of blur in pixels 12 | // res: pixel size of mipmap level selected by lod param 13 | // sizes: sigma of blurs, in pixels 14 | // dir: direction of blur, usually vec2(1.0, 0.0) for horizontal followed by 15 | // another pass for vertical 16 | vec4 gaussianblur(sampler2D tex, float lod, vec2 xy, vec2 res, float sizered, float sizegreen, float sizeblue, float sizealpha, vec2 dir) { 17 | vec4 sigmas = vec4(sizered, sizegreen, sizeblue, sizealpha); 18 | 19 | // Set up state for incremental coefficient calculation, see GPU Gems 20 | // We use vec4s to store four copies of the state, for different size 21 | // red/green/blue/alpha blurs. We don't actually use that here because 22 | // doing both small and large blurs in one pass ruins the mipmap acceleration 23 | // trick - it means we always have to size the mipmap for the smallest blurs 24 | // which makes the large ones really slow 25 | vec4 gx = vec4(0.0); 26 | vec4 gy = vec4(0.0); 27 | vec4 gz = vec4(0.0); 28 | gx = 1.0 / (sqrt(2.0 * 3.141592653589793238) * sigmas); 29 | gy = exp(-0.5 / (sigmas * sigmas)); 30 | gz = gy * gy; 31 | vec4 a = vec4(0.0); 32 | vec4 centre = vec4(0.0); 33 | vec4 sample1 = vec4(0.0); 34 | vec4 sample2 = vec4(0.0); 35 | 36 | // First take the centre sample 37 | sample1 = texture2DLod(tex, xy / res, lod); 38 | a += gx * sample1; 39 | vec4 energy = gx; 40 | gx *= gy; 41 | gy *= gz; 42 | 43 | // Now the other samples 44 | float support = max(max(max(sigmas.r, sigmas.g), sigmas.b), sigmas.a) * 3.0; 45 | for(float i = 1.0; i <= support; i++) { 46 | sample1 = texture2DLod(tex, (xy - i * dir) / res, lod); 47 | sample2 = texture2DLod(tex, (xy + i * dir) / res, lod); 48 | a += gx * sample1; 49 | a += gx * sample2; 50 | energy += 2.0 * gx; 51 | gx *= gy; 52 | gy *= gz; 53 | } 54 | 55 | return a / energy; 56 | } 57 | 58 | void main() { 59 | vec2 res = vec2(adsk_result_w, adsk_result_h); 60 | float strength = texture2D(strength, gl_FragCoord.xy / res).b; 61 | 62 | // We do the blur in two stages: a box filter downres followed by a proper 63 | // Gaussian blur on that low res image. We get the downres for free 64 | // from the mipmaps of the texture, fetching from that mip level inside a normal 65 | // Gaussian convolution loop. 66 | // We balance the amount of downres against the amount of true convolution with 67 | // the quality parameter, which is the approximate size of the second stage blur 68 | // in pixels; it's not exact because the downres is limited to powers of two 69 | float s = max(size * strength / 1.000000, 0.0001); 70 | float downfactor = min(quality / s, 1.0); 71 | float downlod = floor(log2(1.0/downfactor)); 72 | downfactor = 1.0 / pow(2.0, downlod); 73 | float downs = downfactor * s; 74 | vec2 downres = downfactor * res; 75 | vec2 downxy = downfactor * gl_FragCoord.xy; 76 | 77 | gl_FragColor = gaussianblur(adsk_results_pass1, downlod, downxy, downres, downs, downs, downs, downs, vec2(1.0, 0.0)); 78 | } 79 | -------------------------------------------------------------------------------- /Ls_Airglow.03.glsl: -------------------------------------------------------------------------------- 1 | // Airglow pass 3: accelerated Gaussian blur, size / 1.000000, direction vec2(0.0, 1.0) 2 | // lewis@lewissaunders.com 3 | 4 | #extension GL_ARB_shader_texture_lod : enable 5 | 6 | uniform sampler2D strength, adsk_results_pass2; 7 | uniform float size, quality; 8 | uniform float adsk_result_w, adsk_result_h; 9 | 10 | // Return a 1D Gaussian blur from texture tex, sampling from mipmap level lod 11 | // xy: centre of blur in pixels 12 | // res: pixel size of mipmap level selected by lod param 13 | // sizes: sigma of blurs, in pixels 14 | // dir: direction of blur, usually vec2(1.0, 0.0) for horizontal followed by 15 | // another pass for vertical 16 | vec4 gaussianblur(sampler2D tex, float lod, vec2 xy, vec2 res, float sizered, float sizegreen, float sizeblue, float sizealpha, vec2 dir) { 17 | vec4 sigmas = vec4(sizered, sizegreen, sizeblue, sizealpha); 18 | 19 | // Set up state for incremental coefficient calculation, see GPU Gems 20 | // We use vec4s to store four copies of the state, for different size 21 | // red/green/blue/alpha blurs. We don't actually use that here because 22 | // doing both small and large blurs in one pass ruins the mipmap acceleration 23 | // trick - it means we always have to size the mipmap for the smallest blurs 24 | // which makes the large ones really slow 25 | vec4 gx = vec4(0.0); 26 | vec4 gy = vec4(0.0); 27 | vec4 gz = vec4(0.0); 28 | gx = 1.0 / (sqrt(2.0 * 3.141592653589793238) * sigmas); 29 | gy = exp(-0.5 / (sigmas * sigmas)); 30 | gz = gy * gy; 31 | vec4 a = vec4(0.0); 32 | vec4 centre = vec4(0.0); 33 | vec4 sample1 = vec4(0.0); 34 | vec4 sample2 = vec4(0.0); 35 | 36 | // First take the centre sample 37 | sample1 = texture2DLod(tex, xy / res, lod); 38 | a += gx * sample1; 39 | vec4 energy = gx; 40 | gx *= gy; 41 | gy *= gz; 42 | 43 | // Now the other samples 44 | float support = max(max(max(sigmas.r, sigmas.g), sigmas.b), sigmas.a) * 3.0; 45 | for(float i = 1.0; i <= support; i++) { 46 | sample1 = texture2DLod(tex, (xy - i * dir) / res, lod); 47 | sample2 = texture2DLod(tex, (xy + i * dir) / res, lod); 48 | a += gx * sample1; 49 | a += gx * sample2; 50 | energy += 2.0 * gx; 51 | gx *= gy; 52 | gy *= gz; 53 | } 54 | 55 | return a / energy; 56 | } 57 | 58 | void main() { 59 | vec2 res = vec2(adsk_result_w, adsk_result_h); 60 | float strength = texture2D(strength, gl_FragCoord.xy / res).b; 61 | 62 | // We do the blur in two stages: a box filter downres followed by a proper 63 | // Gaussian blur on that low res image. We get the downres for free 64 | // from the mipmaps of the texture, fetching from that mip level inside a normal 65 | // Gaussian convolution loop. 66 | // We balance the amount of downres against the amount of true convolution with 67 | // the quality parameter, which is the approximate size of the second stage blur 68 | // in pixels; it's not exact because the downres is limited to powers of two 69 | float s = max(size * strength / 1.000000, 0.0001); 70 | float downfactor = min(quality / s, 1.0); 71 | float downlod = floor(log2(1.0/downfactor)); 72 | downfactor = 1.0 / pow(2.0, downlod); 73 | float downs = downfactor * s; 74 | vec2 downres = downfactor * res; 75 | vec2 downxy = downfactor * gl_FragCoord.xy; 76 | 77 | gl_FragColor = gaussianblur(adsk_results_pass2, downlod, downxy, downres, downs, downs, downs, downs, vec2(0.0, 1.0)); 78 | } 79 | -------------------------------------------------------------------------------- /Ls_Airglow.04.glsl: -------------------------------------------------------------------------------- 1 | // Airglow pass 4: accelerated Gaussian blur, size / 2.000000, direction vec2(1.0, 0.0) 2 | // lewis@lewissaunders.com 3 | 4 | #extension GL_ARB_shader_texture_lod : enable 5 | 6 | uniform sampler2D strength, adsk_results_pass1; 7 | uniform float size, quality; 8 | uniform float adsk_result_w, adsk_result_h; 9 | 10 | // Return a 1D Gaussian blur from texture tex, sampling from mipmap level lod 11 | // xy: centre of blur in pixels 12 | // res: pixel size of mipmap level selected by lod param 13 | // sizes: sigma of blurs, in pixels 14 | // dir: direction of blur, usually vec2(1.0, 0.0) for horizontal followed by 15 | // another pass for vertical 16 | vec4 gaussianblur(sampler2D tex, float lod, vec2 xy, vec2 res, float sizered, float sizegreen, float sizeblue, float sizealpha, vec2 dir) { 17 | vec4 sigmas = vec4(sizered, sizegreen, sizeblue, sizealpha); 18 | 19 | // Set up state for incremental coefficient calculation, see GPU Gems 20 | // We use vec4s to store four copies of the state, for different size 21 | // red/green/blue/alpha blurs. We don't actually use that here because 22 | // doing both small and large blurs in one pass ruins the mipmap acceleration 23 | // trick - it means we always have to size the mipmap for the smallest blurs 24 | // which makes the large ones really slow 25 | vec4 gx = vec4(0.0); 26 | vec4 gy = vec4(0.0); 27 | vec4 gz = vec4(0.0); 28 | gx = 1.0 / (sqrt(2.0 * 3.141592653589793238) * sigmas); 29 | gy = exp(-0.5 / (sigmas * sigmas)); 30 | gz = gy * gy; 31 | vec4 a = vec4(0.0); 32 | vec4 centre = vec4(0.0); 33 | vec4 sample1 = vec4(0.0); 34 | vec4 sample2 = vec4(0.0); 35 | 36 | // First take the centre sample 37 | sample1 = texture2DLod(tex, xy / res, lod); 38 | a += gx * sample1; 39 | vec4 energy = gx; 40 | gx *= gy; 41 | gy *= gz; 42 | 43 | // Now the other samples 44 | float support = max(max(max(sigmas.r, sigmas.g), sigmas.b), sigmas.a) * 3.0; 45 | for(float i = 1.0; i <= support; i++) { 46 | sample1 = texture2DLod(tex, (xy - i * dir) / res, lod); 47 | sample2 = texture2DLod(tex, (xy + i * dir) / res, lod); 48 | a += gx * sample1; 49 | a += gx * sample2; 50 | energy += 2.0 * gx; 51 | gx *= gy; 52 | gy *= gz; 53 | } 54 | 55 | return a / energy; 56 | } 57 | 58 | void main() { 59 | vec2 res = vec2(adsk_result_w, adsk_result_h); 60 | float strength = texture2D(strength, gl_FragCoord.xy / res).b; 61 | 62 | // We do the blur in two stages: a box filter downres followed by a proper 63 | // Gaussian blur on that low res image. We get the downres for free 64 | // from the mipmaps of the texture, fetching from that mip level inside a normal 65 | // Gaussian convolution loop. 66 | // We balance the amount of downres against the amount of true convolution with 67 | // the quality parameter, which is the approximate size of the second stage blur 68 | // in pixels; it's not exact because the downres is limited to powers of two 69 | float s = max(size * strength / 2.000000, 0.0001); 70 | float downfactor = min(quality / s, 1.0); 71 | float downlod = floor(log2(1.0/downfactor)); 72 | downfactor = 1.0 / pow(2.0, downlod); 73 | float downs = downfactor * s; 74 | vec2 downres = downfactor * res; 75 | vec2 downxy = downfactor * gl_FragCoord.xy; 76 | 77 | gl_FragColor = gaussianblur(adsk_results_pass1, downlod, downxy, downres, downs, downs, downs, downs, vec2(1.0, 0.0)); 78 | } 79 | -------------------------------------------------------------------------------- /Ls_Airglow.05.glsl: -------------------------------------------------------------------------------- 1 | // Airglow pass 5: accelerated Gaussian blur, size / 2.000000, direction vec2(0.0, 1.0) 2 | // lewis@lewissaunders.com 3 | 4 | #extension GL_ARB_shader_texture_lod : enable 5 | 6 | uniform sampler2D strength, adsk_results_pass4; 7 | uniform float size, quality; 8 | uniform float adsk_result_w, adsk_result_h; 9 | 10 | // Return a 1D Gaussian blur from texture tex, sampling from mipmap level lod 11 | // xy: centre of blur in pixels 12 | // res: pixel size of mipmap level selected by lod param 13 | // sizes: sigma of blurs, in pixels 14 | // dir: direction of blur, usually vec2(1.0, 0.0) for horizontal followed by 15 | // another pass for vertical 16 | vec4 gaussianblur(sampler2D tex, float lod, vec2 xy, vec2 res, float sizered, float sizegreen, float sizeblue, float sizealpha, vec2 dir) { 17 | vec4 sigmas = vec4(sizered, sizegreen, sizeblue, sizealpha); 18 | 19 | // Set up state for incremental coefficient calculation, see GPU Gems 20 | // We use vec4s to store four copies of the state, for different size 21 | // red/green/blue/alpha blurs. We don't actually use that here because 22 | // doing both small and large blurs in one pass ruins the mipmap acceleration 23 | // trick - it means we always have to size the mipmap for the smallest blurs 24 | // which makes the large ones really slow 25 | vec4 gx = vec4(0.0); 26 | vec4 gy = vec4(0.0); 27 | vec4 gz = vec4(0.0); 28 | gx = 1.0 / (sqrt(2.0 * 3.141592653589793238) * sigmas); 29 | gy = exp(-0.5 / (sigmas * sigmas)); 30 | gz = gy * gy; 31 | vec4 a = vec4(0.0); 32 | vec4 centre = vec4(0.0); 33 | vec4 sample1 = vec4(0.0); 34 | vec4 sample2 = vec4(0.0); 35 | 36 | // First take the centre sample 37 | sample1 = texture2DLod(tex, xy / res, lod); 38 | a += gx * sample1; 39 | vec4 energy = gx; 40 | gx *= gy; 41 | gy *= gz; 42 | 43 | // Now the other samples 44 | float support = max(max(max(sigmas.r, sigmas.g), sigmas.b), sigmas.a) * 3.0; 45 | for(float i = 1.0; i <= support; i++) { 46 | sample1 = texture2DLod(tex, (xy - i * dir) / res, lod); 47 | sample2 = texture2DLod(tex, (xy + i * dir) / res, lod); 48 | a += gx * sample1; 49 | a += gx * sample2; 50 | energy += 2.0 * gx; 51 | gx *= gy; 52 | gy *= gz; 53 | } 54 | 55 | return a / energy; 56 | } 57 | 58 | void main() { 59 | vec2 res = vec2(adsk_result_w, adsk_result_h); 60 | float strength = texture2D(strength, gl_FragCoord.xy / res).b; 61 | 62 | // We do the blur in two stages: a box filter downres followed by a proper 63 | // Gaussian blur on that low res image. We get the downres for free 64 | // from the mipmaps of the texture, fetching from that mip level inside a normal 65 | // Gaussian convolution loop. 66 | // We balance the amount of downres against the amount of true convolution with 67 | // the quality parameter, which is the approximate size of the second stage blur 68 | // in pixels; it's not exact because the downres is limited to powers of two 69 | float s = max(size * strength / 2.000000, 0.0001); 70 | float downfactor = min(quality / s, 1.0); 71 | float downlod = floor(log2(1.0/downfactor)); 72 | downfactor = 1.0 / pow(2.0, downlod); 73 | float downs = downfactor * s; 74 | vec2 downres = downfactor * res; 75 | vec2 downxy = downfactor * gl_FragCoord.xy; 76 | 77 | gl_FragColor = gaussianblur(adsk_results_pass4, downlod, downxy, downres, downs, downs, downs, downs, vec2(0.0, 1.0)); 78 | } 79 | -------------------------------------------------------------------------------- /Ls_Airglow.06.glsl: -------------------------------------------------------------------------------- 1 | // Airglow pass 6: accelerated Gaussian blur, size / 4.000000, direction vec2(1.0, 0.0) 2 | // lewis@lewissaunders.com 3 | 4 | #extension GL_ARB_shader_texture_lod : enable 5 | 6 | uniform sampler2D strength, adsk_results_pass1; 7 | uniform float size, quality; 8 | uniform float adsk_result_w, adsk_result_h; 9 | 10 | // Return a 1D Gaussian blur from texture tex, sampling from mipmap level lod 11 | // xy: centre of blur in pixels 12 | // res: pixel size of mipmap level selected by lod param 13 | // sizes: sigma of blurs, in pixels 14 | // dir: direction of blur, usually vec2(1.0, 0.0) for horizontal followed by 15 | // another pass for vertical 16 | vec4 gaussianblur(sampler2D tex, float lod, vec2 xy, vec2 res, float sizered, float sizegreen, float sizeblue, float sizealpha, vec2 dir) { 17 | vec4 sigmas = vec4(sizered, sizegreen, sizeblue, sizealpha); 18 | 19 | // Set up state for incremental coefficient calculation, see GPU Gems 20 | // We use vec4s to store four copies of the state, for different size 21 | // red/green/blue/alpha blurs. We don't actually use that here because 22 | // doing both small and large blurs in one pass ruins the mipmap acceleration 23 | // trick - it means we always have to size the mipmap for the smallest blurs 24 | // which makes the large ones really slow 25 | vec4 gx = vec4(0.0); 26 | vec4 gy = vec4(0.0); 27 | vec4 gz = vec4(0.0); 28 | gx = 1.0 / (sqrt(2.0 * 3.141592653589793238) * sigmas); 29 | gy = exp(-0.5 / (sigmas * sigmas)); 30 | gz = gy * gy; 31 | vec4 a = vec4(0.0); 32 | vec4 centre = vec4(0.0); 33 | vec4 sample1 = vec4(0.0); 34 | vec4 sample2 = vec4(0.0); 35 | 36 | // First take the centre sample 37 | sample1 = texture2DLod(tex, xy / res, lod); 38 | a += gx * sample1; 39 | vec4 energy = gx; 40 | gx *= gy; 41 | gy *= gz; 42 | 43 | // Now the other samples 44 | float support = max(max(max(sigmas.r, sigmas.g), sigmas.b), sigmas.a) * 3.0; 45 | for(float i = 1.0; i <= support; i++) { 46 | sample1 = texture2DLod(tex, (xy - i * dir) / res, lod); 47 | sample2 = texture2DLod(tex, (xy + i * dir) / res, lod); 48 | a += gx * sample1; 49 | a += gx * sample2; 50 | energy += 2.0 * gx; 51 | gx *= gy; 52 | gy *= gz; 53 | } 54 | 55 | return a / energy; 56 | } 57 | 58 | void main() { 59 | vec2 res = vec2(adsk_result_w, adsk_result_h); 60 | float strength = texture2D(strength, gl_FragCoord.xy / res).b; 61 | 62 | // We do the blur in two stages: a box filter downres followed by a proper 63 | // Gaussian blur on that low res image. We get the downres for free 64 | // from the mipmaps of the texture, fetching from that mip level inside a normal 65 | // Gaussian convolution loop. 66 | // We balance the amount of downres against the amount of true convolution with 67 | // the quality parameter, which is the approximate size of the second stage blur 68 | // in pixels; it's not exact because the downres is limited to powers of two 69 | float s = max(size * strength / 4.000000, 0.0001); 70 | float downfactor = min(quality / s, 1.0); 71 | float downlod = floor(log2(1.0/downfactor)); 72 | downfactor = 1.0 / pow(2.0, downlod); 73 | float downs = downfactor * s; 74 | vec2 downres = downfactor * res; 75 | vec2 downxy = downfactor * gl_FragCoord.xy; 76 | 77 | gl_FragColor = gaussianblur(adsk_results_pass1, downlod, downxy, downres, downs, downs, downs, downs, vec2(1.0, 0.0)); 78 | } 79 | -------------------------------------------------------------------------------- /Ls_Airglow.07.glsl: -------------------------------------------------------------------------------- 1 | // Airglow pass 7: accelerated Gaussian blur, size / 4.000000, direction vec2(0.0, 1.0) 2 | // lewis@lewissaunders.com 3 | 4 | #extension GL_ARB_shader_texture_lod : enable 5 | 6 | uniform sampler2D strength, adsk_results_pass6; 7 | uniform float size, quality; 8 | uniform float adsk_result_w, adsk_result_h; 9 | 10 | // Return a 1D Gaussian blur from texture tex, sampling from mipmap level lod 11 | // xy: centre of blur in pixels 12 | // res: pixel size of mipmap level selected by lod param 13 | // sizes: sigma of blurs, in pixels 14 | // dir: direction of blur, usually vec2(1.0, 0.0) for horizontal followed by 15 | // another pass for vertical 16 | vec4 gaussianblur(sampler2D tex, float lod, vec2 xy, vec2 res, float sizered, float sizegreen, float sizeblue, float sizealpha, vec2 dir) { 17 | vec4 sigmas = vec4(sizered, sizegreen, sizeblue, sizealpha); 18 | 19 | // Set up state for incremental coefficient calculation, see GPU Gems 20 | // We use vec4s to store four copies of the state, for different size 21 | // red/green/blue/alpha blurs. We don't actually use that here because 22 | // doing both small and large blurs in one pass ruins the mipmap acceleration 23 | // trick - it means we always have to size the mipmap for the smallest blurs 24 | // which makes the large ones really slow 25 | vec4 gx = vec4(0.0); 26 | vec4 gy = vec4(0.0); 27 | vec4 gz = vec4(0.0); 28 | gx = 1.0 / (sqrt(2.0 * 3.141592653589793238) * sigmas); 29 | gy = exp(-0.5 / (sigmas * sigmas)); 30 | gz = gy * gy; 31 | vec4 a = vec4(0.0); 32 | vec4 centre = vec4(0.0); 33 | vec4 sample1 = vec4(0.0); 34 | vec4 sample2 = vec4(0.0); 35 | 36 | // First take the centre sample 37 | sample1 = texture2DLod(tex, xy / res, lod); 38 | a += gx * sample1; 39 | vec4 energy = gx; 40 | gx *= gy; 41 | gy *= gz; 42 | 43 | // Now the other samples 44 | float support = max(max(max(sigmas.r, sigmas.g), sigmas.b), sigmas.a) * 3.0; 45 | for(float i = 1.0; i <= support; i++) { 46 | sample1 = texture2DLod(tex, (xy - i * dir) / res, lod); 47 | sample2 = texture2DLod(tex, (xy + i * dir) / res, lod); 48 | a += gx * sample1; 49 | a += gx * sample2; 50 | energy += 2.0 * gx; 51 | gx *= gy; 52 | gy *= gz; 53 | } 54 | 55 | return a / energy; 56 | } 57 | 58 | void main() { 59 | vec2 res = vec2(adsk_result_w, adsk_result_h); 60 | float strength = texture2D(strength, gl_FragCoord.xy / res).b; 61 | 62 | // We do the blur in two stages: a box filter downres followed by a proper 63 | // Gaussian blur on that low res image. We get the downres for free 64 | // from the mipmaps of the texture, fetching from that mip level inside a normal 65 | // Gaussian convolution loop. 66 | // We balance the amount of downres against the amount of true convolution with 67 | // the quality parameter, which is the approximate size of the second stage blur 68 | // in pixels; it's not exact because the downres is limited to powers of two 69 | float s = max(size * strength / 4.000000, 0.0001); 70 | float downfactor = min(quality / s, 1.0); 71 | float downlod = floor(log2(1.0/downfactor)); 72 | downfactor = 1.0 / pow(2.0, downlod); 73 | float downs = downfactor * s; 74 | vec2 downres = downfactor * res; 75 | vec2 downxy = downfactor * gl_FragCoord.xy; 76 | 77 | gl_FragColor = gaussianblur(adsk_results_pass6, downlod, downxy, downres, downs, downs, downs, downs, vec2(0.0, 1.0)); 78 | } 79 | -------------------------------------------------------------------------------- /Ls_Airglow.08.glsl: -------------------------------------------------------------------------------- 1 | // Airglow pass 8: accelerated Gaussian blur, size / 8.000000, direction vec2(1.0, 0.0) 2 | // lewis@lewissaunders.com 3 | 4 | #extension GL_ARB_shader_texture_lod : enable 5 | 6 | uniform sampler2D strength, adsk_results_pass1; 7 | uniform float size, quality; 8 | uniform float adsk_result_w, adsk_result_h; 9 | 10 | // Return a 1D Gaussian blur from texture tex, sampling from mipmap level lod 11 | // xy: centre of blur in pixels 12 | // res: pixel size of mipmap level selected by lod param 13 | // sizes: sigma of blurs, in pixels 14 | // dir: direction of blur, usually vec2(1.0, 0.0) for horizontal followed by 15 | // another pass for vertical 16 | vec4 gaussianblur(sampler2D tex, float lod, vec2 xy, vec2 res, float sizered, float sizegreen, float sizeblue, float sizealpha, vec2 dir) { 17 | vec4 sigmas = vec4(sizered, sizegreen, sizeblue, sizealpha); 18 | 19 | // Set up state for incremental coefficient calculation, see GPU Gems 20 | // We use vec4s to store four copies of the state, for different size 21 | // red/green/blue/alpha blurs. We don't actually use that here because 22 | // doing both small and large blurs in one pass ruins the mipmap acceleration 23 | // trick - it means we always have to size the mipmap for the smallest blurs 24 | // which makes the large ones really slow 25 | vec4 gx = vec4(0.0); 26 | vec4 gy = vec4(0.0); 27 | vec4 gz = vec4(0.0); 28 | gx = 1.0 / (sqrt(2.0 * 3.141592653589793238) * sigmas); 29 | gy = exp(-0.5 / (sigmas * sigmas)); 30 | gz = gy * gy; 31 | vec4 a = vec4(0.0); 32 | vec4 centre = vec4(0.0); 33 | vec4 sample1 = vec4(0.0); 34 | vec4 sample2 = vec4(0.0); 35 | 36 | // First take the centre sample 37 | sample1 = texture2DLod(tex, xy / res, lod); 38 | a += gx * sample1; 39 | vec4 energy = gx; 40 | gx *= gy; 41 | gy *= gz; 42 | 43 | // Now the other samples 44 | float support = max(max(max(sigmas.r, sigmas.g), sigmas.b), sigmas.a) * 3.0; 45 | for(float i = 1.0; i <= support; i++) { 46 | sample1 = texture2DLod(tex, (xy - i * dir) / res, lod); 47 | sample2 = texture2DLod(tex, (xy + i * dir) / res, lod); 48 | a += gx * sample1; 49 | a += gx * sample2; 50 | energy += 2.0 * gx; 51 | gx *= gy; 52 | gy *= gz; 53 | } 54 | 55 | return a / energy; 56 | } 57 | 58 | void main() { 59 | vec2 res = vec2(adsk_result_w, adsk_result_h); 60 | float strength = texture2D(strength, gl_FragCoord.xy / res).b; 61 | 62 | // We do the blur in two stages: a box filter downres followed by a proper 63 | // Gaussian blur on that low res image. We get the downres for free 64 | // from the mipmaps of the texture, fetching from that mip level inside a normal 65 | // Gaussian convolution loop. 66 | // We balance the amount of downres against the amount of true convolution with 67 | // the quality parameter, which is the approximate size of the second stage blur 68 | // in pixels; it's not exact because the downres is limited to powers of two 69 | float s = max(size * strength / 8.000000, 0.0001); 70 | float downfactor = min(quality / s, 1.0); 71 | float downlod = floor(log2(1.0/downfactor)); 72 | downfactor = 1.0 / pow(2.0, downlod); 73 | float downs = downfactor * s; 74 | vec2 downres = downfactor * res; 75 | vec2 downxy = downfactor * gl_FragCoord.xy; 76 | 77 | gl_FragColor = gaussianblur(adsk_results_pass1, downlod, downxy, downres, downs, downs, downs, downs, vec2(1.0, 0.0)); 78 | } 79 | -------------------------------------------------------------------------------- /Ls_Airglow.09.glsl: -------------------------------------------------------------------------------- 1 | // Airglow pass 9: accelerated Gaussian blur, size / 8.000000, direction vec2(0.0, 1.0) 2 | // lewis@lewissaunders.com 3 | 4 | #extension GL_ARB_shader_texture_lod : enable 5 | 6 | uniform sampler2D strength, adsk_results_pass8; 7 | uniform float size, quality; 8 | uniform float adsk_result_w, adsk_result_h; 9 | 10 | // Return a 1D Gaussian blur from texture tex, sampling from mipmap level lod 11 | // xy: centre of blur in pixels 12 | // res: pixel size of mipmap level selected by lod param 13 | // sizes: sigma of blurs, in pixels 14 | // dir: direction of blur, usually vec2(1.0, 0.0) for horizontal followed by 15 | // another pass for vertical 16 | vec4 gaussianblur(sampler2D tex, float lod, vec2 xy, vec2 res, float sizered, float sizegreen, float sizeblue, float sizealpha, vec2 dir) { 17 | vec4 sigmas = vec4(sizered, sizegreen, sizeblue, sizealpha); 18 | 19 | // Set up state for incremental coefficient calculation, see GPU Gems 20 | // We use vec4s to store four copies of the state, for different size 21 | // red/green/blue/alpha blurs. We don't actually use that here because 22 | // doing both small and large blurs in one pass ruins the mipmap acceleration 23 | // trick - it means we always have to size the mipmap for the smallest blurs 24 | // which makes the large ones really slow 25 | vec4 gx = vec4(0.0); 26 | vec4 gy = vec4(0.0); 27 | vec4 gz = vec4(0.0); 28 | gx = 1.0 / (sqrt(2.0 * 3.141592653589793238) * sigmas); 29 | gy = exp(-0.5 / (sigmas * sigmas)); 30 | gz = gy * gy; 31 | vec4 a = vec4(0.0); 32 | vec4 centre = vec4(0.0); 33 | vec4 sample1 = vec4(0.0); 34 | vec4 sample2 = vec4(0.0); 35 | 36 | // First take the centre sample 37 | sample1 = texture2DLod(tex, xy / res, lod); 38 | a += gx * sample1; 39 | vec4 energy = gx; 40 | gx *= gy; 41 | gy *= gz; 42 | 43 | // Now the other samples 44 | float support = max(max(max(sigmas.r, sigmas.g), sigmas.b), sigmas.a) * 3.0; 45 | for(float i = 1.0; i <= support; i++) { 46 | sample1 = texture2DLod(tex, (xy - i * dir) / res, lod); 47 | sample2 = texture2DLod(tex, (xy + i * dir) / res, lod); 48 | a += gx * sample1; 49 | a += gx * sample2; 50 | energy += 2.0 * gx; 51 | gx *= gy; 52 | gy *= gz; 53 | } 54 | 55 | return a / energy; 56 | } 57 | 58 | void main() { 59 | vec2 res = vec2(adsk_result_w, adsk_result_h); 60 | float strength = texture2D(strength, gl_FragCoord.xy / res).b; 61 | 62 | // We do the blur in two stages: a box filter downres followed by a proper 63 | // Gaussian blur on that low res image. We get the downres for free 64 | // from the mipmaps of the texture, fetching from that mip level inside a normal 65 | // Gaussian convolution loop. 66 | // We balance the amount of downres against the amount of true convolution with 67 | // the quality parameter, which is the approximate size of the second stage blur 68 | // in pixels; it's not exact because the downres is limited to powers of two 69 | float s = max(size * strength / 8.000000, 0.0001); 70 | float downfactor = min(quality / s, 1.0); 71 | float downlod = floor(log2(1.0/downfactor)); 72 | downfactor = 1.0 / pow(2.0, downlod); 73 | float downs = downfactor * s; 74 | vec2 downres = downfactor * res; 75 | vec2 downxy = downfactor * gl_FragCoord.xy; 76 | 77 | gl_FragColor = gaussianblur(adsk_results_pass8, downlod, downxy, downres, downs, downs, downs, downs, vec2(0.0, 1.0)); 78 | } 79 | -------------------------------------------------------------------------------- /Ls_Airglow.10.glsl: -------------------------------------------------------------------------------- 1 | // Airglow pass 10: accelerated Gaussian blur, size / 16.000000, direction vec2(1.0, 0.0) 2 | // lewis@lewissaunders.com 3 | 4 | #extension GL_ARB_shader_texture_lod : enable 5 | 6 | uniform sampler2D strength, adsk_results_pass1; 7 | uniform float size, quality; 8 | uniform float adsk_result_w, adsk_result_h; 9 | 10 | // Return a 1D Gaussian blur from texture tex, sampling from mipmap level lod 11 | // xy: centre of blur in pixels 12 | // res: pixel size of mipmap level selected by lod param 13 | // sizes: sigma of blurs, in pixels 14 | // dir: direction of blur, usually vec2(1.0, 0.0) for horizontal followed by 15 | // another pass for vertical 16 | vec4 gaussianblur(sampler2D tex, float lod, vec2 xy, vec2 res, float sizered, float sizegreen, float sizeblue, float sizealpha, vec2 dir) { 17 | vec4 sigmas = vec4(sizered, sizegreen, sizeblue, sizealpha); 18 | 19 | // Set up state for incremental coefficient calculation, see GPU Gems 20 | // We use vec4s to store four copies of the state, for different size 21 | // red/green/blue/alpha blurs. We don't actually use that here because 22 | // doing both small and large blurs in one pass ruins the mipmap acceleration 23 | // trick - it means we always have to size the mipmap for the smallest blurs 24 | // which makes the large ones really slow 25 | vec4 gx = vec4(0.0); 26 | vec4 gy = vec4(0.0); 27 | vec4 gz = vec4(0.0); 28 | gx = 1.0 / (sqrt(2.0 * 3.141592653589793238) * sigmas); 29 | gy = exp(-0.5 / (sigmas * sigmas)); 30 | gz = gy * gy; 31 | vec4 a = vec4(0.0); 32 | vec4 centre = vec4(0.0); 33 | vec4 sample1 = vec4(0.0); 34 | vec4 sample2 = vec4(0.0); 35 | 36 | // First take the centre sample 37 | sample1 = texture2DLod(tex, xy / res, lod); 38 | a += gx * sample1; 39 | vec4 energy = gx; 40 | gx *= gy; 41 | gy *= gz; 42 | 43 | // Now the other samples 44 | float support = max(max(max(sigmas.r, sigmas.g), sigmas.b), sigmas.a) * 3.0; 45 | for(float i = 1.0; i <= support; i++) { 46 | sample1 = texture2DLod(tex, (xy - i * dir) / res, lod); 47 | sample2 = texture2DLod(tex, (xy + i * dir) / res, lod); 48 | a += gx * sample1; 49 | a += gx * sample2; 50 | energy += 2.0 * gx; 51 | gx *= gy; 52 | gy *= gz; 53 | } 54 | 55 | return a / energy; 56 | } 57 | 58 | void main() { 59 | vec2 res = vec2(adsk_result_w, adsk_result_h); 60 | float strength = texture2D(strength, gl_FragCoord.xy / res).b; 61 | 62 | // We do the blur in two stages: a box filter downres followed by a proper 63 | // Gaussian blur on that low res image. We get the downres for free 64 | // from the mipmaps of the texture, fetching from that mip level inside a normal 65 | // Gaussian convolution loop. 66 | // We balance the amount of downres against the amount of true convolution with 67 | // the quality parameter, which is the approximate size of the second stage blur 68 | // in pixels; it's not exact because the downres is limited to powers of two 69 | float s = max(size * strength / 16.000000, 0.0001); 70 | float downfactor = min(quality / s, 1.0); 71 | float downlod = floor(log2(1.0/downfactor)); 72 | downfactor = 1.0 / pow(2.0, downlod); 73 | float downs = downfactor * s; 74 | vec2 downres = downfactor * res; 75 | vec2 downxy = downfactor * gl_FragCoord.xy; 76 | 77 | gl_FragColor = gaussianblur(adsk_results_pass1, downlod, downxy, downres, downs, downs, downs, downs, vec2(1.0, 0.0)); 78 | } 79 | -------------------------------------------------------------------------------- /Ls_Airglow.11.glsl: -------------------------------------------------------------------------------- 1 | // Airglow pass 11: accelerated Gaussian blur, size / 16.000000, direction vec2(0.0, 1.0) 2 | // lewis@lewissaunders.com 3 | 4 | #extension GL_ARB_shader_texture_lod : enable 5 | 6 | uniform sampler2D strength, adsk_results_pass10; 7 | uniform float size, quality; 8 | uniform float adsk_result_w, adsk_result_h; 9 | 10 | // Return a 1D Gaussian blur from texture tex, sampling from mipmap level lod 11 | // xy: centre of blur in pixels 12 | // res: pixel size of mipmap level selected by lod param 13 | // sizes: sigma of blurs, in pixels 14 | // dir: direction of blur, usually vec2(1.0, 0.0) for horizontal followed by 15 | // another pass for vertical 16 | vec4 gaussianblur(sampler2D tex, float lod, vec2 xy, vec2 res, float sizered, float sizegreen, float sizeblue, float sizealpha, vec2 dir) { 17 | vec4 sigmas = vec4(sizered, sizegreen, sizeblue, sizealpha); 18 | 19 | // Set up state for incremental coefficient calculation, see GPU Gems 20 | // We use vec4s to store four copies of the state, for different size 21 | // red/green/blue/alpha blurs. We don't actually use that here because 22 | // doing both small and large blurs in one pass ruins the mipmap acceleration 23 | // trick - it means we always have to size the mipmap for the smallest blurs 24 | // which makes the large ones really slow 25 | vec4 gx = vec4(0.0); 26 | vec4 gy = vec4(0.0); 27 | vec4 gz = vec4(0.0); 28 | gx = 1.0 / (sqrt(2.0 * 3.141592653589793238) * sigmas); 29 | gy = exp(-0.5 / (sigmas * sigmas)); 30 | gz = gy * gy; 31 | vec4 a = vec4(0.0); 32 | vec4 centre = vec4(0.0); 33 | vec4 sample1 = vec4(0.0); 34 | vec4 sample2 = vec4(0.0); 35 | 36 | // First take the centre sample 37 | sample1 = texture2DLod(tex, xy / res, lod); 38 | a += gx * sample1; 39 | vec4 energy = gx; 40 | gx *= gy; 41 | gy *= gz; 42 | 43 | // Now the other samples 44 | float support = max(max(max(sigmas.r, sigmas.g), sigmas.b), sigmas.a) * 3.0; 45 | for(float i = 1.0; i <= support; i++) { 46 | sample1 = texture2DLod(tex, (xy - i * dir) / res, lod); 47 | sample2 = texture2DLod(tex, (xy + i * dir) / res, lod); 48 | a += gx * sample1; 49 | a += gx * sample2; 50 | energy += 2.0 * gx; 51 | gx *= gy; 52 | gy *= gz; 53 | } 54 | 55 | return a / energy; 56 | } 57 | 58 | void main() { 59 | vec2 res = vec2(adsk_result_w, adsk_result_h); 60 | float strength = texture2D(strength, gl_FragCoord.xy / res).b; 61 | 62 | // We do the blur in two stages: a box filter downres followed by a proper 63 | // Gaussian blur on that low res image. We get the downres for free 64 | // from the mipmaps of the texture, fetching from that mip level inside a normal 65 | // Gaussian convolution loop. 66 | // We balance the amount of downres against the amount of true convolution with 67 | // the quality parameter, which is the approximate size of the second stage blur 68 | // in pixels; it's not exact because the downres is limited to powers of two 69 | float s = max(size * strength / 16.000000, 0.0001); 70 | float downfactor = min(quality / s, 1.0); 71 | float downlod = floor(log2(1.0/downfactor)); 72 | downfactor = 1.0 / pow(2.0, downlod); 73 | float downs = downfactor * s; 74 | vec2 downres = downfactor * res; 75 | vec2 downxy = downfactor * gl_FragCoord.xy; 76 | 77 | gl_FragColor = gaussianblur(adsk_results_pass10, downlod, downxy, downres, downs, downs, downs, downs, vec2(0.0, 1.0)); 78 | } 79 | -------------------------------------------------------------------------------- /Ls_Airglow.12.glsl: -------------------------------------------------------------------------------- 1 | // Airglow pass 12: accelerated Gaussian blur, size / 32.000000, direction vec2(1.0, 0.0) 2 | // lewis@lewissaunders.com 3 | 4 | #extension GL_ARB_shader_texture_lod : enable 5 | 6 | uniform sampler2D strength, adsk_results_pass1; 7 | uniform float size, quality; 8 | uniform float adsk_result_w, adsk_result_h; 9 | 10 | // Return a 1D Gaussian blur from texture tex, sampling from mipmap level lod 11 | // xy: centre of blur in pixels 12 | // res: pixel size of mipmap level selected by lod param 13 | // sizes: sigma of blurs, in pixels 14 | // dir: direction of blur, usually vec2(1.0, 0.0) for horizontal followed by 15 | // another pass for vertical 16 | vec4 gaussianblur(sampler2D tex, float lod, vec2 xy, vec2 res, float sizered, float sizegreen, float sizeblue, float sizealpha, vec2 dir) { 17 | vec4 sigmas = vec4(sizered, sizegreen, sizeblue, sizealpha); 18 | 19 | // Set up state for incremental coefficient calculation, see GPU Gems 20 | // We use vec4s to store four copies of the state, for different size 21 | // red/green/blue/alpha blurs. We don't actually use that here because 22 | // doing both small and large blurs in one pass ruins the mipmap acceleration 23 | // trick - it means we always have to size the mipmap for the smallest blurs 24 | // which makes the large ones really slow 25 | vec4 gx = vec4(0.0); 26 | vec4 gy = vec4(0.0); 27 | vec4 gz = vec4(0.0); 28 | gx = 1.0 / (sqrt(2.0 * 3.141592653589793238) * sigmas); 29 | gy = exp(-0.5 / (sigmas * sigmas)); 30 | gz = gy * gy; 31 | vec4 a = vec4(0.0); 32 | vec4 centre = vec4(0.0); 33 | vec4 sample1 = vec4(0.0); 34 | vec4 sample2 = vec4(0.0); 35 | 36 | // First take the centre sample 37 | sample1 = texture2DLod(tex, xy / res, lod); 38 | a += gx * sample1; 39 | vec4 energy = gx; 40 | gx *= gy; 41 | gy *= gz; 42 | 43 | // Now the other samples 44 | float support = max(max(max(sigmas.r, sigmas.g), sigmas.b), sigmas.a) * 3.0; 45 | for(float i = 1.0; i <= support; i++) { 46 | sample1 = texture2DLod(tex, (xy - i * dir) / res, lod); 47 | sample2 = texture2DLod(tex, (xy + i * dir) / res, lod); 48 | a += gx * sample1; 49 | a += gx * sample2; 50 | energy += 2.0 * gx; 51 | gx *= gy; 52 | gy *= gz; 53 | } 54 | 55 | return a / energy; 56 | } 57 | 58 | void main() { 59 | vec2 res = vec2(adsk_result_w, adsk_result_h); 60 | float strength = texture2D(strength, gl_FragCoord.xy / res).b; 61 | 62 | // We do the blur in two stages: a box filter downres followed by a proper 63 | // Gaussian blur on that low res image. We get the downres for free 64 | // from the mipmaps of the texture, fetching from that mip level inside a normal 65 | // Gaussian convolution loop. 66 | // We balance the amount of downres against the amount of true convolution with 67 | // the quality parameter, which is the approximate size of the second stage blur 68 | // in pixels; it's not exact because the downres is limited to powers of two 69 | float s = max(size * strength / 32.000000, 0.0001); 70 | float downfactor = min(quality / s, 1.0); 71 | float downlod = floor(log2(1.0/downfactor)); 72 | downfactor = 1.0 / pow(2.0, downlod); 73 | float downs = downfactor * s; 74 | vec2 downres = downfactor * res; 75 | vec2 downxy = downfactor * gl_FragCoord.xy; 76 | 77 | gl_FragColor = gaussianblur(adsk_results_pass1, downlod, downxy, downres, downs, downs, downs, downs, vec2(1.0, 0.0)); 78 | } 79 | -------------------------------------------------------------------------------- /Ls_Airglow.13.glsl: -------------------------------------------------------------------------------- 1 | // Airglow pass 13: accelerated Gaussian blur, size / 32.000000, direction vec2(0.0, 1.0) 2 | // lewis@lewissaunders.com 3 | 4 | #extension GL_ARB_shader_texture_lod : enable 5 | 6 | uniform sampler2D strength, adsk_results_pass12; 7 | uniform float size, quality; 8 | uniform float adsk_result_w, adsk_result_h; 9 | 10 | // Return a 1D Gaussian blur from texture tex, sampling from mipmap level lod 11 | // xy: centre of blur in pixels 12 | // res: pixel size of mipmap level selected by lod param 13 | // sizes: sigma of blurs, in pixels 14 | // dir: direction of blur, usually vec2(1.0, 0.0) for horizontal followed by 15 | // another pass for vertical 16 | vec4 gaussianblur(sampler2D tex, float lod, vec2 xy, vec2 res, float sizered, float sizegreen, float sizeblue, float sizealpha, vec2 dir) { 17 | vec4 sigmas = vec4(sizered, sizegreen, sizeblue, sizealpha); 18 | 19 | // Set up state for incremental coefficient calculation, see GPU Gems 20 | // We use vec4s to store four copies of the state, for different size 21 | // red/green/blue/alpha blurs. We don't actually use that here because 22 | // doing both small and large blurs in one pass ruins the mipmap acceleration 23 | // trick - it means we always have to size the mipmap for the smallest blurs 24 | // which makes the large ones really slow 25 | vec4 gx = vec4(0.0); 26 | vec4 gy = vec4(0.0); 27 | vec4 gz = vec4(0.0); 28 | gx = 1.0 / (sqrt(2.0 * 3.141592653589793238) * sigmas); 29 | gy = exp(-0.5 / (sigmas * sigmas)); 30 | gz = gy * gy; 31 | vec4 a = vec4(0.0); 32 | vec4 centre = vec4(0.0); 33 | vec4 sample1 = vec4(0.0); 34 | vec4 sample2 = vec4(0.0); 35 | 36 | // First take the centre sample 37 | sample1 = texture2DLod(tex, xy / res, lod); 38 | a += gx * sample1; 39 | vec4 energy = gx; 40 | gx *= gy; 41 | gy *= gz; 42 | 43 | // Now the other samples 44 | float support = max(max(max(sigmas.r, sigmas.g), sigmas.b), sigmas.a) * 3.0; 45 | for(float i = 1.0; i <= support; i++) { 46 | sample1 = texture2DLod(tex, (xy - i * dir) / res, lod); 47 | sample2 = texture2DLod(tex, (xy + i * dir) / res, lod); 48 | a += gx * sample1; 49 | a += gx * sample2; 50 | energy += 2.0 * gx; 51 | gx *= gy; 52 | gy *= gz; 53 | } 54 | 55 | return a / energy; 56 | } 57 | 58 | void main() { 59 | vec2 res = vec2(adsk_result_w, adsk_result_h); 60 | float strength = texture2D(strength, gl_FragCoord.xy / res).b; 61 | 62 | // We do the blur in two stages: a box filter downres followed by a proper 63 | // Gaussian blur on that low res image. We get the downres for free 64 | // from the mipmaps of the texture, fetching from that mip level inside a normal 65 | // Gaussian convolution loop. 66 | // We balance the amount of downres against the amount of true convolution with 67 | // the quality parameter, which is the approximate size of the second stage blur 68 | // in pixels; it's not exact because the downres is limited to powers of two 69 | float s = max(size * strength / 32.000000, 0.0001); 70 | float downfactor = min(quality / s, 1.0); 71 | float downlod = floor(log2(1.0/downfactor)); 72 | downfactor = 1.0 / pow(2.0, downlod); 73 | float downs = downfactor * s; 74 | vec2 downres = downfactor * res; 75 | vec2 downxy = downfactor * gl_FragCoord.xy; 76 | 77 | gl_FragColor = gaussianblur(adsk_results_pass12, downlod, downxy, downres, downs, downs, downs, downs, vec2(0.0, 1.0)); 78 | } 79 | -------------------------------------------------------------------------------- /Ls_Airglow.14.glsl: -------------------------------------------------------------------------------- 1 | // Airglow pass 14: accelerated Gaussian blur, size / 64.000000, direction vec2(1.0, 0.0) 2 | // lewis@lewissaunders.com 3 | 4 | #extension GL_ARB_shader_texture_lod : enable 5 | 6 | uniform sampler2D strength, adsk_results_pass1; 7 | uniform float size, quality; 8 | uniform float adsk_result_w, adsk_result_h; 9 | 10 | // Return a 1D Gaussian blur from texture tex, sampling from mipmap level lod 11 | // xy: centre of blur in pixels 12 | // res: pixel size of mipmap level selected by lod param 13 | // sizes: sigma of blurs, in pixels 14 | // dir: direction of blur, usually vec2(1.0, 0.0) for horizontal followed by 15 | // another pass for vertical 16 | vec4 gaussianblur(sampler2D tex, float lod, vec2 xy, vec2 res, float sizered, float sizegreen, float sizeblue, float sizealpha, vec2 dir) { 17 | vec4 sigmas = vec4(sizered, sizegreen, sizeblue, sizealpha); 18 | 19 | // Set up state for incremental coefficient calculation, see GPU Gems 20 | // We use vec4s to store four copies of the state, for different size 21 | // red/green/blue/alpha blurs. We don't actually use that here because 22 | // doing both small and large blurs in one pass ruins the mipmap acceleration 23 | // trick - it means we always have to size the mipmap for the smallest blurs 24 | // which makes the large ones really slow 25 | vec4 gx = vec4(0.0); 26 | vec4 gy = vec4(0.0); 27 | vec4 gz = vec4(0.0); 28 | gx = 1.0 / (sqrt(2.0 * 3.141592653589793238) * sigmas); 29 | gy = exp(-0.5 / (sigmas * sigmas)); 30 | gz = gy * gy; 31 | vec4 a = vec4(0.0); 32 | vec4 centre = vec4(0.0); 33 | vec4 sample1 = vec4(0.0); 34 | vec4 sample2 = vec4(0.0); 35 | 36 | // First take the centre sample 37 | sample1 = texture2DLod(tex, xy / res, lod); 38 | a += gx * sample1; 39 | vec4 energy = gx; 40 | gx *= gy; 41 | gy *= gz; 42 | 43 | // Now the other samples 44 | float support = max(max(max(sigmas.r, sigmas.g), sigmas.b), sigmas.a) * 3.0; 45 | for(float i = 1.0; i <= support; i++) { 46 | sample1 = texture2DLod(tex, (xy - i * dir) / res, lod); 47 | sample2 = texture2DLod(tex, (xy + i * dir) / res, lod); 48 | a += gx * sample1; 49 | a += gx * sample2; 50 | energy += 2.0 * gx; 51 | gx *= gy; 52 | gy *= gz; 53 | } 54 | 55 | return a / energy; 56 | } 57 | 58 | void main() { 59 | vec2 res = vec2(adsk_result_w, adsk_result_h); 60 | float strength = texture2D(strength, gl_FragCoord.xy / res).b; 61 | 62 | // We do the blur in two stages: a box filter downres followed by a proper 63 | // Gaussian blur on that low res image. We get the downres for free 64 | // from the mipmaps of the texture, fetching from that mip level inside a normal 65 | // Gaussian convolution loop. 66 | // We balance the amount of downres against the amount of true convolution with 67 | // the quality parameter, which is the approximate size of the second stage blur 68 | // in pixels; it's not exact because the downres is limited to powers of two 69 | float s = max(size * strength / 64.000000, 0.0001); 70 | float downfactor = min(quality / s, 1.0); 71 | float downlod = floor(log2(1.0/downfactor)); 72 | downfactor = 1.0 / pow(2.0, downlod); 73 | float downs = downfactor * s; 74 | vec2 downres = downfactor * res; 75 | vec2 downxy = downfactor * gl_FragCoord.xy; 76 | 77 | gl_FragColor = gaussianblur(adsk_results_pass1, downlod, downxy, downres, downs, downs, downs, downs, vec2(1.0, 0.0)); 78 | } 79 | -------------------------------------------------------------------------------- /Ls_Airglow.15.glsl: -------------------------------------------------------------------------------- 1 | // Airglow pass 15: accelerated Gaussian blur, size / 64.000000, direction vec2(0.0, 1.0) 2 | // lewis@lewissaunders.com 3 | 4 | #extension GL_ARB_shader_texture_lod : enable 5 | 6 | uniform sampler2D strength, adsk_results_pass14; 7 | uniform float size, quality; 8 | uniform float adsk_result_w, adsk_result_h; 9 | 10 | // Return a 1D Gaussian blur from texture tex, sampling from mipmap level lod 11 | // xy: centre of blur in pixels 12 | // res: pixel size of mipmap level selected by lod param 13 | // sizes: sigma of blurs, in pixels 14 | // dir: direction of blur, usually vec2(1.0, 0.0) for horizontal followed by 15 | // another pass for vertical 16 | vec4 gaussianblur(sampler2D tex, float lod, vec2 xy, vec2 res, float sizered, float sizegreen, float sizeblue, float sizealpha, vec2 dir) { 17 | vec4 sigmas = vec4(sizered, sizegreen, sizeblue, sizealpha); 18 | 19 | // Set up state for incremental coefficient calculation, see GPU Gems 20 | // We use vec4s to store four copies of the state, for different size 21 | // red/green/blue/alpha blurs. We don't actually use that here because 22 | // doing both small and large blurs in one pass ruins the mipmap acceleration 23 | // trick - it means we always have to size the mipmap for the smallest blurs 24 | // which makes the large ones really slow 25 | vec4 gx = vec4(0.0); 26 | vec4 gy = vec4(0.0); 27 | vec4 gz = vec4(0.0); 28 | gx = 1.0 / (sqrt(2.0 * 3.141592653589793238) * sigmas); 29 | gy = exp(-0.5 / (sigmas * sigmas)); 30 | gz = gy * gy; 31 | vec4 a = vec4(0.0); 32 | vec4 centre = vec4(0.0); 33 | vec4 sample1 = vec4(0.0); 34 | vec4 sample2 = vec4(0.0); 35 | 36 | // First take the centre sample 37 | sample1 = texture2DLod(tex, xy / res, lod); 38 | a += gx * sample1; 39 | vec4 energy = gx; 40 | gx *= gy; 41 | gy *= gz; 42 | 43 | // Now the other samples 44 | float support = max(max(max(sigmas.r, sigmas.g), sigmas.b), sigmas.a) * 3.0; 45 | for(float i = 1.0; i <= support; i++) { 46 | sample1 = texture2DLod(tex, (xy - i * dir) / res, lod); 47 | sample2 = texture2DLod(tex, (xy + i * dir) / res, lod); 48 | a += gx * sample1; 49 | a += gx * sample2; 50 | energy += 2.0 * gx; 51 | gx *= gy; 52 | gy *= gz; 53 | } 54 | 55 | return a / energy; 56 | } 57 | 58 | void main() { 59 | vec2 res = vec2(adsk_result_w, adsk_result_h); 60 | float strength = texture2D(strength, gl_FragCoord.xy / res).b; 61 | 62 | // We do the blur in two stages: a box filter downres followed by a proper 63 | // Gaussian blur on that low res image. We get the downres for free 64 | // from the mipmaps of the texture, fetching from that mip level inside a normal 65 | // Gaussian convolution loop. 66 | // We balance the amount of downres against the amount of true convolution with 67 | // the quality parameter, which is the approximate size of the second stage blur 68 | // in pixels; it's not exact because the downres is limited to powers of two 69 | float s = max(size * strength / 64.000000, 0.0001); 70 | float downfactor = min(quality / s, 1.0); 71 | float downlod = floor(log2(1.0/downfactor)); 72 | downfactor = 1.0 / pow(2.0, downlod); 73 | float downs = downfactor * s; 74 | vec2 downres = downfactor * res; 75 | vec2 downxy = downfactor * gl_FragCoord.xy; 76 | 77 | gl_FragColor = gaussianblur(adsk_results_pass14, downlod, downxy, downres, downs, downs, downs, downs, vec2(0.0, 1.0)); 78 | } 79 | -------------------------------------------------------------------------------- /Ls_Airglow.16.glsl: -------------------------------------------------------------------------------- 1 | // Airglow pass 16: accelerated Gaussian blur, size / 128.000000, direction vec2(1.0, 0.0) 2 | // lewis@lewissaunders.com 3 | 4 | #extension GL_ARB_shader_texture_lod : enable 5 | 6 | uniform sampler2D strength, adsk_results_pass1; 7 | uniform float size, quality; 8 | uniform float adsk_result_w, adsk_result_h; 9 | 10 | // Return a 1D Gaussian blur from texture tex, sampling from mipmap level lod 11 | // xy: centre of blur in pixels 12 | // res: pixel size of mipmap level selected by lod param 13 | // sizes: sigma of blurs, in pixels 14 | // dir: direction of blur, usually vec2(1.0, 0.0) for horizontal followed by 15 | // another pass for vertical 16 | vec4 gaussianblur(sampler2D tex, float lod, vec2 xy, vec2 res, float sizered, float sizegreen, float sizeblue, float sizealpha, vec2 dir) { 17 | vec4 sigmas = vec4(sizered, sizegreen, sizeblue, sizealpha); 18 | 19 | // Set up state for incremental coefficient calculation, see GPU Gems 20 | // We use vec4s to store four copies of the state, for different size 21 | // red/green/blue/alpha blurs. We don't actually use that here because 22 | // doing both small and large blurs in one pass ruins the mipmap acceleration 23 | // trick - it means we always have to size the mipmap for the smallest blurs 24 | // which makes the large ones really slow 25 | vec4 gx = vec4(0.0); 26 | vec4 gy = vec4(0.0); 27 | vec4 gz = vec4(0.0); 28 | gx = 1.0 / (sqrt(2.0 * 3.141592653589793238) * sigmas); 29 | gy = exp(-0.5 / (sigmas * sigmas)); 30 | gz = gy * gy; 31 | vec4 a = vec4(0.0); 32 | vec4 centre = vec4(0.0); 33 | vec4 sample1 = vec4(0.0); 34 | vec4 sample2 = vec4(0.0); 35 | 36 | // First take the centre sample 37 | sample1 = texture2DLod(tex, xy / res, lod); 38 | a += gx * sample1; 39 | vec4 energy = gx; 40 | gx *= gy; 41 | gy *= gz; 42 | 43 | // Now the other samples 44 | float support = max(max(max(sigmas.r, sigmas.g), sigmas.b), sigmas.a) * 3.0; 45 | for(float i = 1.0; i <= support; i++) { 46 | sample1 = texture2DLod(tex, (xy - i * dir) / res, lod); 47 | sample2 = texture2DLod(tex, (xy + i * dir) / res, lod); 48 | a += gx * sample1; 49 | a += gx * sample2; 50 | energy += 2.0 * gx; 51 | gx *= gy; 52 | gy *= gz; 53 | } 54 | 55 | return a / energy; 56 | } 57 | 58 | void main() { 59 | vec2 res = vec2(adsk_result_w, adsk_result_h); 60 | float strength = texture2D(strength, gl_FragCoord.xy / res).b; 61 | 62 | // We do the blur in two stages: a box filter downres followed by a proper 63 | // Gaussian blur on that low res image. We get the downres for free 64 | // from the mipmaps of the texture, fetching from that mip level inside a normal 65 | // Gaussian convolution loop. 66 | // We balance the amount of downres against the amount of true convolution with 67 | // the quality parameter, which is the approximate size of the second stage blur 68 | // in pixels; it's not exact because the downres is limited to powers of two 69 | float s = max(size * strength / 128.000000, 0.0001); 70 | float downfactor = min(quality / s, 1.0); 71 | float downlod = floor(log2(1.0/downfactor)); 72 | downfactor = 1.0 / pow(2.0, downlod); 73 | float downs = downfactor * s; 74 | vec2 downres = downfactor * res; 75 | vec2 downxy = downfactor * gl_FragCoord.xy; 76 | 77 | gl_FragColor = gaussianblur(adsk_results_pass1, downlod, downxy, downres, downs, downs, downs, downs, vec2(1.0, 0.0)); 78 | } 79 | -------------------------------------------------------------------------------- /Ls_Ash.1.glsl: -------------------------------------------------------------------------------- 1 | // Adaptive sharpening 2 | // Pass 1: edge detection 3 | // lewis@lewissaunders.com 4 | 5 | uniform sampler2D front; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform float ksize, threshold; 8 | 9 | void main() { 10 | vec2 xy = gl_FragCoord.xy; 11 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 12 | 13 | vec4 orig = texture2D(front, xy * px); 14 | 15 | float ksize = 1.0; 16 | 17 | // Find gradients of front with X/Y Sobel convolution 18 | vec2 d; 19 | d.x = 1.0 * texture2D(front, (xy + ksize * vec2(-1.0, -1.0)) * px).g; 20 | d.x += 2.0 * texture2D(front, (xy + ksize * vec2(-1.0, 0.0)) * px).g; 21 | d.x += 1.0 * texture2D(front, (xy + ksize * vec2(-1.0, +1.0)) * px).g; 22 | d.x += -1.0 * texture2D(front, (xy + ksize * vec2(+1.0, -1.0)) * px).g; 23 | d.x += -2.0 * texture2D(front, (xy + ksize * vec2(+1.0, 0.0)) * px).g; 24 | d.x += -1.0 * texture2D(front, (xy + ksize * vec2(+1.0, +1.0)) * px).g; 25 | d.y = 1.0 * texture2D(front, (xy + ksize * vec2(-1.0, -1.0)) * px).g; 26 | d.y += 2.0 * texture2D(front, (xy + ksize * vec2( 0.0, -1.0)) * px).g; 27 | d.y += 1.0 * texture2D(front, (xy + ksize * vec2(+1.0, -1.0)) * px).g; 28 | d.y += -1.0 * texture2D(front, (xy + ksize * vec2(-1.0, +1.0)) * px).g; 29 | d.y += -2.0 * texture2D(front, (xy + ksize * vec2( 0.0, +1.0)) * px).g; 30 | d.y += -1.0 * texture2D(front, (xy + ksize * vec2(+1.0, +1.0)) * px).g; 31 | 32 | // Magnitude of gradients finds edges 33 | float mag = length(d); 34 | float edginess = mag; 35 | 36 | // Threshold removes minor edges 37 | edginess *= 1.0 - threshold; 38 | edginess -= threshold; 39 | 40 | gl_FragColor = vec4(orig.r, orig.g, orig.b, edginess); 41 | } 42 | -------------------------------------------------------------------------------- /Ls_Ash.1.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Ash.1.glsl.p -------------------------------------------------------------------------------- /Ls_Ash.2.glsl: -------------------------------------------------------------------------------- 1 | // Adaptive sharpening 2 | // Pass 2: horizontal Gaussian blur 3 | // lewis@lewissaunders.com 4 | 5 | uniform sampler2D adsk_results_pass1; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform float sigma; 8 | const float pi = 3.141592653589793238462643383279502884197969; 9 | 10 | void main() { 11 | vec2 xy = gl_FragCoord.xy; 12 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 13 | 14 | int support = int(sigma * 3.0); 15 | 16 | // Incremental coefficient calculation setup as per GPU Gems 3 17 | vec3 g; 18 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 19 | g.y = exp(-0.5 / (sigma * sigma)); 20 | g.z = g.y * g.y; 21 | 22 | if(sigma == 0.0) { 23 | g.x = 1.0; 24 | } 25 | 26 | // Centre sample 27 | vec4 a = g.x * texture2D(adsk_results_pass1, xy * px); 28 | float energy = g.x; 29 | g.xy *= g.yz; 30 | 31 | // The rest 32 | for(int i = 1; i <= support; i++) { 33 | a += g.x * texture2D(adsk_results_pass1, (xy - vec2(float(i), 0.0)) * px); 34 | a += g.x * texture2D(adsk_results_pass1, (xy + vec2(float(i), 0.0)) * px); 35 | energy += 2.0 * g.x; 36 | g.xy *= g.yz; 37 | } 38 | a /= energy; 39 | 40 | gl_FragColor = a; 41 | } 42 | -------------------------------------------------------------------------------- /Ls_Ash.3.glsl: -------------------------------------------------------------------------------- 1 | // Adaptive sharpening 2 | // Pass 2: vertical Gaussian blur, blend 3 | // lewis@lewissaunders.com 4 | 5 | uniform sampler2D adsk_results_pass2, front, strengthmap; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform float sigma, strength; 8 | uniform bool adaptive, onlyedges, showedges; 9 | const float pi = 3.141592653589793238462643383279502884197969; 10 | 11 | void main() { 12 | vec2 xy = gl_FragCoord.xy; 13 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 14 | 15 | float strength_here = strength * texture2D(strengthmap, xy * px).b; 16 | 17 | int support = int(sigma * 3.0); 18 | 19 | // Incremental coefficient calculation setup as per GPU Gems 3 20 | vec3 g; 21 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 22 | g.y = exp(-0.5 / (sigma * sigma)); 23 | g.z = g.y * g.y; 24 | 25 | if(sigma == 0.0) { 26 | g.x = 1.0; 27 | } 28 | 29 | // Centre sample 30 | vec4 a = g.x * texture2D(adsk_results_pass2, xy * px); 31 | float energy = g.x; 32 | g.xy *= g.yz; 33 | 34 | // The rest 35 | for(int i = 1; i <= support; i++) { 36 | a += g.x * texture2D(adsk_results_pass2, (xy - vec2(0.0, float(i))) * px); 37 | a += g.x * texture2D(adsk_results_pass2, (xy + vec2(0.0, float(i))) * px); 38 | energy += 2.0 * g.x; 39 | g.xy *= g.yz; 40 | } 41 | a /= energy; 42 | vec4 unsharp = a; 43 | 44 | // Inflate edge pass a little 45 | float edginess = clamp(unsharp.a * 3.0, 0.0, 1.0); 46 | 47 | if(onlyedges) { 48 | edginess = 1.0 - edginess; 49 | } 50 | 51 | // Sharpen 52 | vec4 orig = texture2D(front, xy * px); 53 | vec4 sharp = orig + vec4(strength_here) * (orig - unsharp); 54 | 55 | if(adaptive){ 56 | // Remove sharpening from edges 57 | sharp = edginess * orig + (1.0 - edginess) * sharp; 58 | } 59 | 60 | if(showedges) { 61 | sharp = vec4(edginess); 62 | } 63 | 64 | gl_FragColor = vec4(sharp.r, sharp.g, sharp.b, 1.0); 65 | } 66 | -------------------------------------------------------------------------------- /Ls_Bevel.1.glsl: -------------------------------------------------------------------------------- 1 | // Bevel 2 | // Pass 1: Dummy pass for front passthrough 3 | // lewis@lewissaunders.com 4 | 5 | uniform sampler2D front; 6 | uniform float adsk_result_w, adsk_result_h; 7 | 8 | void main() { 9 | vec2 xy = gl_FragCoord.xy; 10 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 11 | 12 | gl_FragColor = texture2D(front, xy * px); 13 | } 14 | -------------------------------------------------------------------------------- /Ls_Bevel.1.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Bevel.1.glsl.p -------------------------------------------------------------------------------- /Ls_Bevel.2.glsl: -------------------------------------------------------------------------------- 1 | // Bevel 2 | // Pass 2: horizontal Gaussian blur 3 | // lewis@lewissaunders.com 4 | 5 | uniform sampler2D adsk_results_pass1; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform float sigma; 8 | const float pi = 3.141592653589793238462643383279502884197969; 9 | 10 | void main() { 11 | vec2 xy = gl_FragCoord.xy; 12 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 13 | 14 | int support = int(sigma * 3.0); 15 | 16 | // Incremental coefficient calculation setup as per GPU Gems 3 17 | vec3 g; 18 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 19 | g.y = exp(-0.5 / (sigma * sigma)); 20 | g.z = g.y * g.y; 21 | 22 | if(sigma == 0.0) { 23 | g.x = 1.0; 24 | } 25 | 26 | // Centre sample 27 | vec4 a = g.x * texture2D(adsk_results_pass1, xy * px); 28 | float energy = g.x; 29 | g.xy *= g.yz; 30 | 31 | // The rest 32 | for(int i = 1; i <= support; i++) { 33 | a += g.x * texture2D(adsk_results_pass1, (xy - vec2(float(i), 0.0)) * px); 34 | a += g.x * texture2D(adsk_results_pass1, (xy + vec2(float(i), 0.0)) * px); 35 | energy += 2.0 * g.x; 36 | g.xy *= g.yz; 37 | } 38 | a /= energy; 39 | 40 | gl_FragColor = a; 41 | } 42 | -------------------------------------------------------------------------------- /Ls_Bevel.3.glsl: -------------------------------------------------------------------------------- 1 | // Bevel 2 | // Pass 3: vertical Gaussian blur 3 | // lewis@lewissaunders.com 4 | 5 | uniform sampler2D adsk_results_pass2; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform float sigma; 8 | const float pi = 3.141592653589793238462643383279502884197969; 9 | 10 | void main() { 11 | vec2 xy = gl_FragCoord.xy; 12 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 13 | 14 | int support = int(sigma * 3.0); 15 | 16 | // Incremental coefficient calculation setup as per GPU Gems 3 17 | vec3 g; 18 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 19 | g.y = exp(-0.5 / (sigma * sigma)); 20 | g.z = g.y * g.y; 21 | 22 | if(sigma == 0.0) { 23 | g.x = 1.0; 24 | } 25 | 26 | // Centre sample 27 | vec4 a = g.x * texture2D(adsk_results_pass2, xy * px); 28 | float energy = g.x; 29 | g.xy *= g.yz; 30 | 31 | // The rest 32 | for(int i = 1; i <= support; i++) { 33 | a += g.x * texture2D(adsk_results_pass2, (xy - vec2(0.0, float(i))) * px); 34 | a += g.x * texture2D(adsk_results_pass2, (xy + vec2(0.0, float(i))) * px); 35 | energy += 2.0 * g.x; 36 | g.xy *= g.yz; 37 | } 38 | a /= energy; 39 | vec4 unsharp = a; 40 | 41 | gl_FragColor = a; 42 | } 43 | -------------------------------------------------------------------------------- /Ls_Bevel.4.glsl: -------------------------------------------------------------------------------- 1 | // Bevel 2 | // Pass 4: gradient detection and actual beveling 3 | // Broadly, we use the gradient vector of the blurred 4 | // image as the X/Y components of a normal vector, which 5 | // we then dot with the light direction. 6 | // To get the sharp edge, we normalize the gradient, then 7 | // use smoothstep() to remove the nasty artifacts where 8 | // it was near zero. This gives us a kinda level-set iso-line 9 | // of the blurred image, which roughly follows the outline of 10 | // the text. It ain't perfect! 11 | // 12 | // This pass outputs the bevel based on the "Height map" input 13 | // 14 | // lewis@lewissaunders.com 15 | 16 | uniform sampler2D adsk_results_pass3, adsk_results_pass1; 17 | uniform float adsk_result_w, adsk_result_h; 18 | uniform float sigma, ambient, smoothy; 19 | uniform vec3 lite; 20 | uniform bool normals; 21 | 22 | void main() { 23 | vec2 xy = gl_FragCoord.xy; 24 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 25 | float fron = texture2D(adsk_results_pass1, xy * px).g; 26 | 27 | // Find gradients with X/Y Sobel convolution 28 | vec2 d; 29 | float ksize = sigma/2.0; 30 | d.x = 1.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2(-1.0, -1.0)) * px).g; 31 | d.x += 2.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2(-1.0, 0.0)) * px).g; 32 | d.x += 1.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2(-1.0, +1.0)) * px).g; 33 | d.x += -1.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2(+1.0, -1.0)) * px).g; 34 | d.x += -2.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2(+1.0, 0.0)) * px).g; 35 | d.x += -1.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2(+1.0, +1.0)) * px).g; 36 | d.y = 1.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2(-1.0, -1.0)) * px).g; 37 | d.y += 2.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2( 0.0, -1.0)) * px).g; 38 | d.y += 1.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2(+1.0, -1.0)) * px).g; 39 | d.y += -1.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2(-1.0, +1.0)) * px).g; 40 | d.y += -2.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2( 0.0, +1.0)) * px).g; 41 | d.y += -1.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2(+1.0, +1.0)) * px).g; 42 | d /= ksize; 43 | 44 | float len = length(d); 45 | float edge = smoothstep(0.0, smoothy/100.0, len); 46 | 47 | d /= len + 0.0001; 48 | 49 | float l = dot(d, normalize(lite.xy - vec2(0.5))); 50 | l = mix(l, fron, ambient); 51 | l = mix(ambient * fron, l, edge); 52 | l *= fron; 53 | 54 | vec4 o = vec4(l, l, l, fron); 55 | 56 | gl_FragColor = o; 57 | } 58 | -------------------------------------------------------------------------------- /Ls_Bevel.5.glsl: -------------------------------------------------------------------------------- 1 | // Bevel 2 | // Pass 5: gradient detection and actual beveling 3 | // Broadly, we use the gradient vector of the blurred 4 | // image as the X/Y components of a normal vector, which 5 | // we then dot with the light direction. 6 | // To get the sharp edge, we normalize the gradient, then 7 | // use smoothstep() to remove the nasty artifacts where 8 | // it was near zero. This gives us a kinda level-set iso-line 9 | // of the blurred image, which roughly follows the outline of 10 | // the text. It ain't perfect! 11 | // 12 | // This pass outputs the normals of the bevel based on the 13 | // "Height map" input 14 | // 15 | // lewis@lewissaunders.com 16 | 17 | uniform sampler2D adsk_results_pass3, adsk_results_pass1; 18 | uniform float adsk_result_w, adsk_result_h; 19 | uniform float sigma, smoothy; 20 | uniform bool normals; 21 | 22 | 23 | void main() { 24 | vec2 xy = gl_FragCoord.xy; 25 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 26 | float fron = texture2D(adsk_results_pass1, xy * px).g; 27 | 28 | // Find gradients with X/Y Sobel convolution 29 | vec2 d; 30 | float ksize = sigma/2.0; 31 | d.x = 1.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2(-1.0, -1.0)) * px).g; 32 | d.x += 2.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2(-1.0, 0.0)) * px).g; 33 | d.x += 1.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2(-1.0, +1.0)) * px).g; 34 | d.x += -1.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2(+1.0, -1.0)) * px).g; 35 | d.x += -2.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2(+1.0, 0.0)) * px).g; 36 | d.x += -1.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2(+1.0, +1.0)) * px).g; 37 | d.y = 1.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2(-1.0, -1.0)) * px).g; 38 | d.y += 2.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2( 0.0, -1.0)) * px).g; 39 | d.y += 1.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2(+1.0, -1.0)) * px).g; 40 | d.y += -1.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2(-1.0, +1.0)) * px).g; 41 | d.y += -2.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2( 0.0, +1.0)) * px).g; 42 | d.y += -1.0 * texture2D(adsk_results_pass3, (xy + ksize * vec2(+1.0, +1.0)) * px).g; 43 | d /= ksize; 44 | 45 | float len = length(d); 46 | float edge = smoothstep(0.0, smoothy/100.0, len); 47 | 48 | d /= len + 0.0001; 49 | 50 | vec3 n = vec3(d.x, d.y, 1.0); 51 | n = mix(vec3(0.0, 0.0, 1.0), n, edge); 52 | gl_FragColor = vec4(n, fron); 53 | 54 | } 55 | -------------------------------------------------------------------------------- /Ls_Bevel.6.glsl: -------------------------------------------------------------------------------- 1 | // Bevel 2 | // Pass 6: Multiply the bevel pass output by the back, and comp 3 | // over the back using the matte 4 | // graphistesmoke@gmail.com (Sébastien DELECOUR / Sebquismoke) 5 | 6 | uniform sampler2D adsk_results_pass4, adsk_results_pass5, back, matte; 7 | uniform float adsk_result_w, adsk_result_h; 8 | uniform bool normals; 9 | 10 | 11 | void main() { 12 | vec2 xy = gl_FragCoord.xy; 13 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 14 | vec3 matte = texture2D(matte, xy * px).rgb; 15 | vec3 back = texture2D(back, xy * px).rgb; 16 | vec3 bevel = texture2D(adsk_results_pass4, xy * px).rgb; 17 | vec3 bevelnormals = texture2D(adsk_results_pass5, xy * px).rgb; 18 | 19 | if(normals) { 20 | gl_FragColor = vec4(bevelnormals.rgb, matte.g); 21 | return; 22 | } 23 | 24 | vec3 o = mix(back, back*bevel, matte.g); 25 | 26 | gl_FragColor = vec4(o, matte.g); 27 | } 28 | -------------------------------------------------------------------------------- /Ls_Chips.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Chips.glsl.p -------------------------------------------------------------------------------- /Ls_Chips.hip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Chips.hip -------------------------------------------------------------------------------- /Ls_Chips.mx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Chips.mx -------------------------------------------------------------------------------- /Ls_Chips.textureGrid.exr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Chips.textureGrid.exr -------------------------------------------------------------------------------- /Ls_Colourmatrix.glsl: -------------------------------------------------------------------------------- 1 | // Colour matrix shader for Matchbox 2 | // I apologise for the incredibly stupid variable names but it's 3am yo 3 | // lewis@lewissaunders.com 4 | 5 | uniform sampler2D input1, strength; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform float r2r, r2g, r2b, g2r, g2g, g2b, b2r, b2g, b2b; 8 | uniform vec3 or, og, ob, ir, ig, ib; 9 | uniform float effect, gain, mixx; 10 | 11 | void main() { 12 | vec2 coords = gl_FragCoord.xy / vec2(adsk_result_w, adsk_result_h); 13 | float mixx_here = mixx * texture2D(strength, coords).r; 14 | vec3 i = texture2D(input1, coords).rgb; 15 | vec3 ii = vec3(r2r*i.r + g2r*i.g + b2r*i.b, r2g*i.r + g2g*i.g + b2g*i.b, r2b*i.r + g2b*i.g + b2b*i.b); 16 | vec3 iii = ii * mat3(or, og, ob); 17 | vec3 iv = mat3(ir, ig, ib) * iii; 18 | vec3 v = effect*iv + (1.0-effect)*i; 19 | vec3 vi = gain * v; 20 | vec3 vii = mixx_here*vi + (1.0-mixx_here)*i; 21 | gl_FragColor = vec4(vii, 1.0); 22 | } 23 | -------------------------------------------------------------------------------- /Ls_Colourmatrix.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Colourmatrix.glsl.p -------------------------------------------------------------------------------- /Ls_Colourspace.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Colourspace.glsl.p -------------------------------------------------------------------------------- /Ls_Contacts.glsl: -------------------------------------------------------------------------------- 1 | // Tiles the inputs into a grid for impressing clients 2 | // lewis@lewissaunders.com 3 | // TODO: 4 | // o Nonsquare pixels support... eek 5 | // o Variable width borders look gross, how can we get a nice even spacing? 6 | 7 | uniform sampler2D in1, in2, in3, in4, in5, in6; 8 | uniform int rows, cols, randomcount, seed; 9 | uniform bool random, perframe, filltiles; 10 | uniform float scale; 11 | uniform float adsk_result_w, adsk_result_h, adsk_time; 12 | 13 | // Mysterious dirty random number generator 14 | float rand(vec2 co){ 15 | return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); 16 | } 17 | 18 | void main() { 19 | vec2 coords = gl_FragCoord.xy / vec2(adsk_result_w, adsk_result_h); 20 | vec2 tilecoords = vec2(0.0, 0.0); 21 | vec4 o = vec4(0.0); 22 | float aspectdiff, tilew, tileh; 23 | int tilex, tiley, tileidx; 24 | 25 | // Figure out how big each tile will be, and which tile we're in 26 | tilew = adsk_result_w / float(cols); 27 | tileh = adsk_result_h / float(rows); 28 | tilex = int(gl_FragCoord.x / tilew); 29 | tiley = int((adsk_result_h - gl_FragCoord.y) / tileh); 30 | tileidx = tiley * cols + tilex; 31 | 32 | // Randomize the tile index 33 | if(random) { 34 | if(perframe) { 35 | tileidx = int(rand(vec2(float(tilex - seed), float(tiley) + 1234.0 * adsk_time)) * float(randomcount)); 36 | } else { 37 | tileidx = int(rand(vec2(float(tilex - seed), float(tiley))) * float(randomcount)); 38 | } 39 | } 40 | 41 | // Get current coordinates within this tile 42 | tilecoords.x = mod(gl_FragCoord.x, tilew) / tilew; 43 | tilecoords.y = mod(gl_FragCoord.y, tileh) / tileh; 44 | 45 | // Scale coordinates about the centre of each tile to maintain proportions and do fit/fill 46 | tilecoords -= vec2(0.5); 47 | tilecoords *= 100.0 / scale; 48 | aspectdiff = (tilew / tileh) / (adsk_result_w / adsk_result_h); 49 | if(aspectdiff > 1.0) { 50 | tilecoords.x *= aspectdiff; 51 | if(filltiles) { 52 | tilecoords /= aspectdiff; 53 | } 54 | } else { 55 | tilecoords.y /= aspectdiff; 56 | if(filltiles) { 57 | tilecoords *= aspectdiff; 58 | } 59 | } 60 | tilecoords += vec2(0.5); 61 | 62 | // Finally grab input for the tile we're in 63 | if(tileidx == 0) { 64 | o = texture2D(in1, tilecoords); 65 | } else if(tileidx == 1) { 66 | o = texture2D(in2, tilecoords); 67 | } else if(tileidx == 2) { 68 | o = texture2D(in3, tilecoords); 69 | } else if(tileidx == 3) { 70 | o = texture2D(in4, tilecoords); 71 | } else if(tileidx == 4) { 72 | o = texture2D(in5, tilecoords); 73 | } else if(tileidx == 5) { 74 | o = texture2D(in6, tilecoords); 75 | } 76 | 77 | // Draw black if we're in a border area 78 | if((tilecoords.x <= 0.0) || (tilecoords.x > 1.0)) { 79 | o = vec4(0.0); 80 | } 81 | if((tilecoords.y <= 0.0) || (tilecoords.y > 1.0)) { 82 | o = vec4(0.0); 83 | } 84 | 85 | gl_FragColor = o; 86 | } 87 | -------------------------------------------------------------------------------- /Ls_Contacts.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Contacts.glsl.p -------------------------------------------------------------------------------- /Ls_Dilate.1.glsl: -------------------------------------------------------------------------------- 1 | #version 120 2 | 3 | // Morphological dilate/erode using non-flat structuring elements 4 | // (see https://www.mathworks.com/help/images/structuring-elements.html) 5 | 6 | uniform sampler2D front, strength, cleanscreen; 7 | uniform float size, stretch; 8 | uniform int kernel; 9 | uniform bool usecolour, usecleanscreen; 10 | uniform vec3 screencolour; 11 | uniform float adsk_result_w, adsk_result_h; 12 | vec2 res = vec2(adsk_result_w, adsk_result_h); 13 | 14 | void main(void) { 15 | vec2 xy = gl_FragCoord.xy; 16 | vec2 sizexy = mix(vec2(2.0, 0.0), vec2(0.0, 2.0), stretch) * texture2D(strength, xy / res).b * size; 17 | vec3 screencol = usecleanscreen ? texture2D(cleanscreen, xy / res).rgb : screencolour; 18 | 19 | // Centre sample 20 | vec3 best = texture2D(front, xy / res).rgb + sign(sizexy.x) * vec3(1.0); 21 | if(usecolour) { 22 | // Ignore weighting if using colour 23 | best -= sign(sizexy.x) * vec3(1.0); 24 | } 25 | float bestdist = distance(best, screencol); 26 | 27 | // The rest 28 | int support = int(abs(sizexy.x) * 3.0); 29 | for(int i = 1; i <= support; i++) { 30 | float weight = 0.0; 31 | float x = float(i) / abs(sizexy.x); 32 | if(kernel == 0) { 33 | // Box 34 | weight = x < 1.0 ? 1.0 : 0.0; 35 | } else if(kernel == 1) { 36 | // Box AA 37 | if(x < 1.0) { 38 | weight = 1.0; 39 | } else if(x < 1.0 + (1.0 / abs(sizexy.x))) { 40 | weight = 1.0 - ((x - 1.0) / (1.0 / abs(sizexy.x))); 41 | } else { 42 | weight = 0.0; 43 | } 44 | } else if(kernel == 2) { 45 | // Triangle 46 | weight = 1.0 - clamp(x, 0.0, 1.0); 47 | } else if(kernel == 3) { 48 | // Ball 49 | weight = sqrt(1 - pow(clamp(x, 0.0, 1.0), 2)); 50 | } else if(kernel == 4) { 51 | // Gaussian 52 | weight = exp(-0.5 * pow(x, 2)); 53 | } 54 | // Add weights to pixel values before comparison 55 | vec3 a = texture2D(front, (xy - vec2(float(i), 0.0)) / res).rgb + sign(sizexy.x) * vec3(weight); 56 | vec3 b = texture2D(front, (xy + vec2(float(i), 0.0)) / res).rgb + sign(sizexy.x) * vec3(weight); 57 | if(usecolour) { 58 | // Ignore outer parts of support to match non-colour mode box kernel size 59 | if(x > 1.0) break; 60 | 61 | // Ignore weighting if using colour 62 | a -= sign(sizexy.x) * vec3(weight); 63 | b -= sign(sizexy.x) * vec3(weight); 64 | float adist = distance(a, screencol); 65 | float bdist = distance(b, screencol); 66 | if(sizexy.x > 0.0) { 67 | if(adist < bestdist) { 68 | best = a; 69 | bestdist = adist; 70 | } 71 | if(bdist < bestdist) { 72 | best = b; 73 | bestdist = bdist; 74 | } 75 | } else { 76 | if(adist > bestdist) { 77 | best = a; 78 | bestdist = adist; 79 | } 80 | if(bdist > bestdist) { 81 | best = b; 82 | bestdist = bdist; 83 | } 84 | } 85 | } else { 86 | if(sizexy.x > 0.0) { 87 | best = max(best, a); 88 | best = max(best, b); 89 | } else { 90 | best = min(best, a); 91 | best = min(best, b); 92 | } 93 | } 94 | } 95 | 96 | gl_FragColor = vec4(best.r, best.g, best.b, 0.0); 97 | } 98 | -------------------------------------------------------------------------------- /Ls_Dilate.1.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Dilate.1.glsl.p -------------------------------------------------------------------------------- /Ls_Dilate.2.glsl: -------------------------------------------------------------------------------- 1 | #version 120 2 | 3 | uniform sampler2D adsk_results_pass1, strength, cleanscreen; 4 | uniform float size, stretch; 5 | uniform int kernel; 6 | uniform bool usecolour, usecleanscreen; 7 | uniform vec3 screencolour; 8 | uniform float adsk_result_w, adsk_result_h; 9 | vec2 res = vec2(adsk_result_w, adsk_result_h); 10 | 11 | void main(void) { 12 | vec2 xy = gl_FragCoord.xy; 13 | vec2 sizexy = mix(vec2(2.0, 0.0), vec2(0.0, 2.0), stretch) * texture2D(strength, xy / res).b * size; 14 | vec3 screencol = usecleanscreen ? texture2D(cleanscreen, xy / res).rgb : screencolour; 15 | 16 | // Centre sample 17 | vec3 best = texture2D(adsk_results_pass1, xy / res).rgb + sign(sizexy.y) * vec3(1.0); 18 | if(usecolour) { 19 | // Ignore weighting if using colour 20 | best -= sign(sizexy.y) * vec3(1.0); 21 | } 22 | float bestdist = distance(best, screencol); 23 | 24 | // The rest 25 | int support = int(abs(sizexy.y) * 3.0); 26 | for(int i = 1; i <= support; i++) { 27 | float weight = 0.0; 28 | float x = float(i) / abs(sizexy.y); 29 | if(kernel == 0) { 30 | // Box 31 | weight = x < 1.0 ? 1.0 : 0.0; 32 | } else if(kernel == 1) { 33 | // Box AA 34 | if(x < 1.0) { 35 | weight = 1.0; 36 | } else if(x < 1.0 + (1.0 / abs(sizexy.y))) { 37 | weight = 1.0 - ((x - 1.0) / (1.0 / abs(sizexy.y))); 38 | } else { 39 | weight = 0.0; 40 | } 41 | } else if(kernel == 2) { 42 | // Triangle 43 | weight = 1.0 - clamp(x, 0.0, 1.0); 44 | } else if(kernel == 3) { 45 | // Ball 46 | weight = sqrt(1 - pow(clamp(x, 0.0, 1.0), 2)); 47 | } else if(kernel == 4) { 48 | // Gaussian 49 | weight = exp(-0.5 * pow(x, 2)); 50 | } 51 | // Add weights to pixel values before comparison 52 | vec3 a = texture2D(adsk_results_pass1, (xy - vec2(0.0, float(i))) / res).rgb + sign(sizexy.y) * vec3(weight); 53 | vec3 b = texture2D(adsk_results_pass1, (xy + vec2(0.0, float(i))) / res).rgb + sign(sizexy.y) * vec3(weight); 54 | if(usecolour) { 55 | // Ignore outer parts of support to match non-colour mode box kernel size 56 | if(x > 1.0) break; 57 | 58 | // Ignore weighting if using colour 59 | a -= sign(sizexy.y) * vec3(weight); 60 | b -= sign(sizexy.y) * vec3(weight); 61 | float adist = distance(a, screencol); 62 | float bdist = distance(b, screencol); 63 | if(sizexy.x > 0.0) { 64 | if(adist < bestdist) { 65 | best = a; 66 | bestdist = adist; 67 | } 68 | if(bdist < bestdist) { 69 | best = b; 70 | bestdist = bdist; 71 | } 72 | } else { 73 | if(adist > bestdist) { 74 | best = a; 75 | bestdist = adist; 76 | } 77 | if(bdist > bestdist) { 78 | best = b; 79 | bestdist = bdist; 80 | } 81 | } 82 | } else { 83 | if(sizexy.y > 0.0) { 84 | best = max(best, a); 85 | best = max(best, b); 86 | } else { 87 | best = min(best, a); 88 | best = min(best, b); 89 | } 90 | } 91 | } 92 | 93 | if(!usecolour) { 94 | // Remove weights from final output 95 | if(sizexy.y > 0.0) { 96 | best -= vec3(2.0); 97 | } else { 98 | best += vec3(2.0); 99 | } 100 | } 101 | 102 | gl_FragColor = vec4(best.r, best.g, best.b, 0.0); 103 | } 104 | -------------------------------------------------------------------------------- /Ls_Dollface.1.glsl: -------------------------------------------------------------------------------- 1 | // Blur only similar pixels 2 | // Pass 2: horizontal blur 3 | // lewis@lewissaunders.com 4 | 5 | uniform sampler2D front, strength; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform float sigma, threshold; 8 | uniform bool slow; 9 | uniform int quality; 10 | const float pi = 3.141592653589793238462643383279502884197969; 11 | 12 | void main() { 13 | vec2 xy = gl_FragCoord.xy; 14 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 15 | 16 | float strength_here = texture2D(strength, xy * px).b; 17 | float sigma_here = sigma * strength_here; 18 | 19 | int support = int(sigma_here * 3.0); 20 | 21 | float kernelhyp = length(vec2(support, support)); 22 | float rgbhyp = length(vec3(1.0, 1.0, 1.0)); 23 | 24 | if(slow) { 25 | // Use straightforward but slow algorithm 26 | vec4 centre = texture2D(front, xy * px); 27 | 28 | vec4 a = vec4(0.0); 29 | float energy = 0.0; 30 | 31 | float inc = pow(2.0, 3.0 - float(quality)); 32 | 33 | // Factor to make apparant sharpness of two algorithms similar 34 | float m = 1.666; 35 | 36 | // Yes, this is brute force and dirty 37 | // Making bilateral filtering separable is really hard 38 | // c.f. any number of SIGGRAPH papers 39 | for(float x = -sigma_here * m; x <= sigma_here * m; x += inc) { 40 | for(float y = -sigma_here * m; y <= sigma_here * m; y += inc) { 41 | vec4 b = texture2D(front, (xy + vec2(x, y)) * px); 42 | b.a = 1.0; 43 | 44 | // Mult this sample by colour similarity 45 | float fac = 1.0 - (length(b - centre) / rgbhyp); 46 | fac = pow(fac, threshold); 47 | b *= clamp(fac, 0.001, 1.0); 48 | 49 | // Mult this sample by distance from centre, i.e. triangular kernel 50 | b *= kernelhyp - length(vec2(x, y)); 51 | 52 | // Accumulate 53 | a += b; 54 | energy += b.a; 55 | } 56 | } 57 | 58 | if(energy < 0.05) { 59 | // No samples were taken! 60 | gl_FragColor = texture2D(front, xy * px); 61 | return; 62 | } 63 | 64 | a /= energy; 65 | gl_FragColor = a; 66 | return; 67 | } 68 | 69 | // Okay. On to complicated two-pass algorithm 70 | // Incremental coefficient calculation setup as per GPU Gems 3 71 | vec3 g; 72 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma_here); 73 | g.y = exp(-0.5 / (sigma_here * sigma_here)); 74 | g.z = g.y * g.y; 75 | 76 | if(sigma_here == 0.0) { 77 | g.x = 1.0; 78 | } 79 | 80 | vec4 a, b, c; 81 | a = vec4(0.0); 82 | float fac, energy = 0.0; 83 | 84 | // Centre sample 85 | vec4 orig = texture2D(front, xy * px); 86 | a += g.x * orig; 87 | energy += g.x; 88 | g.xy *= g.yz; 89 | 90 | int inc = int(pow(2.0, 3.0 - float(quality))); 91 | 92 | // The rest 93 | for(int i = 1; i <= support; i += inc) { 94 | b = texture2D(front, (xy - vec2(float(i), 0.0)) * px); 95 | c = texture2D(front, (xy + vec2(float(i), 0.0)) * px); 96 | 97 | b.a = 1.0; 98 | c.a = 1.0; 99 | 100 | fac = 1.0 - (length(b - orig) / rgbhyp); 101 | fac = pow(fac, threshold); 102 | b *= g.x * clamp(fac, 0.001, 1.0); 103 | a += b; 104 | energy += b.a; 105 | 106 | fac = 1.0 - (length(c - orig) / rgbhyp); 107 | fac = pow(fac, threshold); 108 | c *= g.x * clamp(fac, 0.001, 1.0); 109 | a += c; 110 | energy += c.a; 111 | 112 | g.xy *= g.yz; 113 | } 114 | a /= energy; 115 | 116 | gl_FragColor = a; 117 | } 118 | -------------------------------------------------------------------------------- /Ls_Dollface.1.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Dollface.1.glsl.p -------------------------------------------------------------------------------- /Ls_Dollface.2.glsl: -------------------------------------------------------------------------------- 1 | // Blur only similar pixels 2 | // Pass 2: vertical blur 3 | // lewis@lewissaunders.com 4 | 5 | uniform sampler2D adsk_results_pass1, strength; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform float sigma, threshold; 8 | uniform bool slow; 9 | uniform int quality; 10 | const float pi = 3.141592653589793238462643383279502884197969; 11 | 12 | void main() { 13 | vec2 xy = gl_FragCoord.xy; 14 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 15 | 16 | float strength_here = texture2D(strength, xy * px).b; 17 | float sigma_here = sigma * strength_here; 18 | 19 | int support = int(sigma_here * 3.0); 20 | 21 | float kernelhyp = length(vec2(support, support)); 22 | float rgbhyp = length(vec3(1.0, 1.0, 1.0)); 23 | 24 | if(slow) { 25 | // Use pass 1 results and quit 26 | gl_FragColor = texture2D(adsk_results_pass1, xy * px); 27 | return; 28 | } 29 | 30 | // Incremental coefficient calculation setup as per GPU Gems 3 31 | vec3 g; 32 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma_here); 33 | g.y = exp(-0.5 / (sigma_here * sigma_here)); 34 | g.z = g.y * g.y; 35 | 36 | if(sigma_here == 0.0) { 37 | g.x = 1.0; 38 | } 39 | 40 | vec4 a, b, c; 41 | a = vec4(0.0); 42 | float fac, energy = 0.0; 43 | 44 | // Centre sample 45 | vec4 orig = texture2D(adsk_results_pass1, xy * px); 46 | a += g.x * orig; 47 | energy += g.x; 48 | g.xy *= g.yz; 49 | 50 | int inc = int(pow(2.0, 3.0 - float(quality))); 51 | 52 | // The rest 53 | for(int i = 1; i <= support; i += inc) { 54 | b = texture2D(adsk_results_pass1, (xy - vec2(0.0, float(i))) * px); 55 | c = texture2D(adsk_results_pass1, (xy + vec2(0.0, float(i))) * px); 56 | 57 | b.a = 1.0; 58 | c.a = 1.0; 59 | 60 | fac = 1.0 - (length(b - orig) / rgbhyp); 61 | fac = pow(fac, threshold); 62 | b *= g.x * clamp(fac, 0.001, 1.0); 63 | a += b; 64 | energy += b.a; 65 | 66 | fac = 1.0 - (length(c - orig) / rgbhyp); 67 | fac = pow(fac, threshold); 68 | c *= g.x * clamp(fac, 0.001, 1.0); 69 | a += c; 70 | energy += c.a; 71 | 72 | g.xy *= g.yz; 73 | } 74 | a /= energy; 75 | 76 | gl_FragColor = a; 77 | } 78 | -------------------------------------------------------------------------------- /Ls_Dollface.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /Ls_FXAA.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_FXAA.glsl.p -------------------------------------------------------------------------------- /Ls_FXAA.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Ls_Filmstrip.glsl: -------------------------------------------------------------------------------- 1 | // Filmstrip 2 | // Arranges input frames into a grid 3 | // TOOD: figure out why increasing border squashes picture... 4 | // lewis@lewissaunders.com 5 | 6 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio, adsk_result_pixelratio; 7 | uniform float adsk_front_w, adsk_front_h, adsk_front_frameratio, adsk_front_pixelratio; 8 | uniform sampler2D front; 9 | uniform sampler2D adsk_accum_texture; 10 | uniform bool adsk_accum_no_prev_frame; 11 | uniform float adsk_time; 12 | uniform float cols; 13 | uniform float xborder; 14 | uniform bool allframes, centre; 15 | 16 | void main() { 17 | vec2 res = vec2(adsk_result_w, adsk_result_h); 18 | vec2 xy = gl_FragCoord.xy / res; 19 | xy.y = 1.0 - xy.y; 20 | 21 | // We want border widths the same horizontally and vertically 22 | vec2 border = vec2((xborder/1000.0), (xborder/1000.0) * adsk_result_frameratio); 23 | 24 | // How many rows can we fit of these columns? 25 | float rows = cols * adsk_front_frameratio / adsk_result_frameratio; 26 | float colsused = floor(cols); 27 | float rowsused = floor(rows); 28 | if(centre) { 29 | // If the rows and cols don't fill frame, offset so they're centred 30 | xy -= (vec2(cols-colsused, rows-rowsused) / vec2(cols, rows)) / 2.0; 31 | } 32 | 33 | // Offset to inside edge of frame border, which is not part of the individual cells 34 | vec2 noframe = xy; 35 | noframe *= vec2(1.0) + 2.0 * border; 36 | noframe -= border; 37 | 38 | vec2 cellsize = vec2(1.0) / vec2(cols, rows); 39 | 40 | // Figure out which cell we're in 41 | vec2 loc = floor(noframe / cellsize); 42 | float frame = loc.y * colsused + loc.x; 43 | 44 | // Figure out where we are in this cell 45 | vec2 cell = noframe / cellsize; 46 | cell = mod(cell, 1.0); 47 | 48 | // Offset to be inside border of this cell 49 | vec2 noborder = cell; 50 | noborder *= vec2(1.0) + 2.0 * (border / cellsize); 51 | noborder -= border / cellsize; 52 | 53 | // Read previous output frame 54 | vec4 a = texture2D(adsk_accum_texture, gl_FragCoord.xy / res); 55 | if(allframes || adsk_time == frame + 1.0) { 56 | // We're in the cell we need to add this time 57 | a = texture2D(front, vec2(noborder.x, 1.0 - noborder.y)); 58 | } 59 | 60 | // Output black in fill and matte for border areas 61 | bool isborder = false; 62 | if(noborder.x < 0.0 || noborder.x > 1.0 || noborder.y < 0.0 || noborder.y > 1.0) { 63 | isborder = true; 64 | } 65 | if(loc.x >= colsused || loc.x < 0.0 || loc.y >= rowsused || loc.y < 0.0) { 66 | isborder = true; 67 | } 68 | if(isborder) { 69 | a = vec4(0.0); 70 | } 71 | 72 | gl_FragColor = a; 73 | } 74 | -------------------------------------------------------------------------------- /Ls_Filmstrip.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Filmstrip.glsl.p -------------------------------------------------------------------------------- /Ls_Filmstrip.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Ls_Fireflies.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Fireflies.glsl.p -------------------------------------------------------------------------------- /Ls_Fireflies.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Ls_Fireflies_sortingnetwork.pl: -------------------------------------------------------------------------------- 1 | # Prints comparator orders for the sorting network used in Ls_Fireflies.1.glsl 2 | # The module needs to be installed from CPAN first with: 3 | # cpan Algorithm::Networksort 4 | 5 | use Algorithm::Networksort; 6 | use Algorithm::Networksort::Best qw(:all); 7 | 8 | my $inputs = 9; 9 | 10 | # First the standard algorithm-generated one: 11 | my $algorithm = "bosenelson"; 12 | my $nw = nwsrt(inputs => $inputs, algorithm => $algorithm); 13 | print $nw->title(), "\n"; 14 | print $nw, "\n"; 15 | print $nw->graph_text(), "\n"; 16 | $nw->formats([ "COMPARESWAP(%d, %d)\n" ]); 17 | print $nw->formatted(); 18 | 19 | # Then possible better ones discovered separately: 20 | my @nwkeys = nw_best_names($inputs); 21 | for my $name (@nwkeys) 22 | { 23 | my $nw = nwsrt_best(name => $name); 24 | print $nw->title(), "\n", $nw->formatted(), "\n\n"; 25 | print $nw->graph_text(), "\n"; 26 | $nw->formats([ "COMPARESWAP(%d, %d)\n" ]); 27 | print $nw->formatted(); 28 | } 29 | -------------------------------------------------------------------------------- /Ls_Flock.1.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Flock.1.glsl.p -------------------------------------------------------------------------------- /Ls_Flock.2.glsl: -------------------------------------------------------------------------------- 1 | // Flock pass 2 2 | // This pass simply trims off the top half of the simulation texture, 3 | // which stores velocities that are not useful for Action rendering 4 | // 5 | // lewis@lewissaunders.com 6 | // 7 | 8 | uniform float adsk_result_w, adsk_result_h; 9 | uniform sampler2D adsk_results_pass1; 10 | 11 | void main() { 12 | vec2 xy = gl_FragCoord.xy; 13 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 14 | 15 | gl_FragColor = texture2D(adsk_results_pass1, xy * px * vec2(1.0, 0.5)); 16 | } 17 | -------------------------------------------------------------------------------- /Ls_Fluid.1.glsl: -------------------------------------------------------------------------------- 1 | // Pass 1: advect the vectors by themselves, including the effect 2 | // of the obstacle input and the gravity vector. This takes its 3 | // input from the accumulation texture, or the vector input on frame 1. 4 | // It outputs the advected motion vectors in red/green, and a UV map in 5 | // blue/alpha 6 | // lewis@lewissaunders.com 7 | 8 | uniform sampler2D vecs, adsk_accum_texture, obstacles; 9 | uniform float adsk_result_w, adsk_result_h, velocity, sidestep, obstacleweight; 10 | uniform vec2 offset; 11 | uniform int samples, oversamples; 12 | uniform bool adsk_accum_no_prev_frame; 13 | 14 | vec4 get(vec2 uv) { 15 | if(adsk_accum_no_prev_frame) { 16 | // First frame is input vectors in rg, UV map in ba 17 | return vec4(texture2D(vecs, uv).rg, uv); 18 | } else { 19 | vec4 v = texture2D(adsk_accum_texture, uv); 20 | v.xy += offset/100.0; 21 | float obs = texture2D(obstacles, uv).b; 22 | v.xy *= 1.0 - obstacleweight * obs; 23 | return v; 24 | } 25 | } 26 | 27 | void main() { 28 | vec2 xy = gl_FragCoord.xy; 29 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); // Factor to convert pixels to [0,1] texture coords 30 | 31 | float sam = float(samples); 32 | vec4 acc = vec4(0.0); 33 | vec2 v; 34 | for(int j = 0; j < oversamples; j++) { 35 | for(int k = 0; k < oversamples; k++) { 36 | // Starting point for this sample 37 | xy = gl_FragCoord.xy + vec2(float(j) / (float(oversamples) + 1.0), float(k) / (float(oversamples) + 1.0)); 38 | // Walk along path by sampling vector image, moving, sampling, moving... 39 | for(float i = 0.0; i < sam; i++) { 40 | v = get(xy * px).rg; 41 | if(length(v) == 0.0) { 42 | // No gradient at this point in the map, early out 43 | break; 44 | } 45 | xy -= v * (velocity/sam) + sidestep/100.0 * vec2(-v.y, v.x); 46 | } 47 | // Sample front image where our walk ended up 48 | acc += get(xy * px); 49 | 50 | } 51 | } 52 | acc /= float(oversamples * oversamples); 53 | 54 | gl_FragColor = acc; 55 | } 56 | -------------------------------------------------------------------------------- /Ls_Fluid.1.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Fluid.1.glsl.p -------------------------------------------------------------------------------- /Ls_Fluid.2.glsl: -------------------------------------------------------------------------------- 1 | // Undiverge a vector field 2 | // Pass 2 - Gaussian blur 1, horizontal 3 | // lewis@lewissaunders.com 4 | 5 | uniform sampler2D adsk_results_pass1; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform float blur1size; 8 | const float pi = 3.141592653589793238462643383279502884197969; 9 | 10 | void main() { 11 | vec2 xy = gl_FragCoord.xy; 12 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 13 | 14 | float sigma = blur1size; 15 | int support = int(sigma * 3.0); 16 | 17 | // Incremental coefficient calculation setup as per GPU Gems 3 18 | vec3 g; 19 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 20 | g.y = exp(-0.5 / (sigma * sigma)); 21 | g.z = g.y * g.y; 22 | 23 | if(sigma == 0.0) { 24 | g.x = 1.0; 25 | } 26 | 27 | // Centre sample 28 | vec4 a = g.x * texture2D(adsk_results_pass1, xy * px); 29 | float energy = g.x; 30 | g.xy *= g.yz; 31 | 32 | // The rest 33 | for(int i = 1; i <= support; i++) { 34 | a += g.x * texture2D(adsk_results_pass1, (xy - vec2(float(i), 0.0)) * px); 35 | a += g.x * texture2D(adsk_results_pass1, (xy + vec2(float(i), 0.0)) * px); 36 | energy += 2.0 * g.x; 37 | g.xy *= g.yz; 38 | } 39 | a /= energy; 40 | 41 | gl_FragColor = a; 42 | } 43 | -------------------------------------------------------------------------------- /Ls_Fluid.3.glsl: -------------------------------------------------------------------------------- 1 | // Undiverge a vector field 2 | // Pass 3 - Gaussian blur 1, vertical 3 | // lewis@lewissaunders.com 4 | 5 | uniform sampler2D adsk_results_pass2; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform float blur1size; 8 | const float pi = 3.141592653589793238462643383279502884197969; 9 | 10 | void main() { 11 | vec2 xy = gl_FragCoord.xy; 12 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 13 | 14 | float sigma = blur1size; 15 | int support = int(sigma * 3.0); 16 | 17 | // Incremental coefficient calculation setup as per GPU Gems 3 18 | vec3 g; 19 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 20 | g.y = exp(-0.5 / (sigma * sigma)); 21 | g.z = g.y * g.y; 22 | 23 | if(sigma == 0.0) { 24 | g.x = 1.0; 25 | } 26 | 27 | // Centre sample 28 | vec4 a = g.x * texture2D(adsk_results_pass2, xy * px); 29 | float energy = g.x; 30 | g.xy *= g.yz; 31 | 32 | // The rest 33 | for(int i = 1; i <= support; i++) { 34 | a += g.x * texture2D(adsk_results_pass2, (xy - vec2(0.0, float(i))) * px); 35 | a += g.x * texture2D(adsk_results_pass2, (xy + vec2(0.0, float(i))) * px); 36 | energy += 2.0 * g.x; 37 | g.xy *= g.yz; 38 | } 39 | a /= energy; 40 | 41 | gl_FragColor = a; 42 | } 43 | -------------------------------------------------------------------------------- /Ls_Fluid.4.glsl: -------------------------------------------------------------------------------- 1 | // Undiverge a vector field 2 | // Pass 4 - Gaussian blur 2, horizontal 3 | // lewis@lewissaunders.com 4 | 5 | uniform sampler2D adsk_results_pass3; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform float blur2size; 8 | const float pi = 3.141592653589793238462643383279502884197969; 9 | 10 | void main() { 11 | vec2 xy = gl_FragCoord.xy; 12 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 13 | 14 | float sigma = blur2size; 15 | int support = int(sigma * 3.0); 16 | 17 | // Incremental coefficient calculation setup as per GPU Gems 3 18 | vec3 g; 19 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 20 | g.y = exp(-0.5 / (sigma * sigma)); 21 | g.z = g.y * g.y; 22 | 23 | if(sigma == 0.0) { 24 | g.x = 1.0; 25 | } 26 | 27 | // Centre sample 28 | vec4 a = g.x * texture2D(adsk_results_pass3, xy * px); 29 | float energy = g.x; 30 | g.xy *= g.yz; 31 | 32 | // The rest 33 | for(int i = 1; i <= support; i++) { 34 | a += g.x * texture2D(adsk_results_pass3, (xy - vec2(float(i), 0.0)) * px); 35 | a += g.x * texture2D(adsk_results_pass3, (xy + vec2(float(i), 0.0)) * px); 36 | energy += 2.0 * g.x; 37 | g.xy *= g.yz; 38 | } 39 | a /= energy; 40 | 41 | gl_FragColor = a; 42 | } 43 | -------------------------------------------------------------------------------- /Ls_Fluid.5.glsl: -------------------------------------------------------------------------------- 1 | // Undiverge a vector field 2 | // Pass 5 - Gaussian blur 2, vertical 3 | // lewis@lewissaunders.com 4 | 5 | uniform sampler2D adsk_results_pass4; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform float blur2size; 8 | const float pi = 3.141592653589793238462643383279502884197969; 9 | 10 | void main() { 11 | vec2 xy = gl_FragCoord.xy; 12 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 13 | 14 | float sigma = blur2size; 15 | int support = int(sigma * 3.0); 16 | 17 | // Incremental coefficient calculation setup as per GPU Gems 3 18 | vec3 g; 19 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 20 | g.y = exp(-0.5 / (sigma * sigma)); 21 | g.z = g.y * g.y; 22 | 23 | if(sigma == 0.0) { 24 | g.x = 1.0; 25 | } 26 | 27 | // Centre sample 28 | vec4 a = g.x * texture2D(adsk_results_pass4, xy * px); 29 | float energy = g.x; 30 | g.xy *= g.yz; 31 | 32 | // The rest 33 | for(int i = 1; i <= support; i++) { 34 | a += g.x * texture2D(adsk_results_pass4, (xy - vec2(0.0, float(i))) * px); 35 | a += g.x * texture2D(adsk_results_pass4, (xy + vec2(0.0, float(i))) * px); 36 | energy += 2.0 * g.x; 37 | g.xy *= g.yz; 38 | } 39 | a /= energy; 40 | 41 | gl_FragColor = a; 42 | } 43 | -------------------------------------------------------------------------------- /Ls_Fluid.6.glsl: -------------------------------------------------------------------------------- 1 | // Undiverge a vector field 2 | // Pass 6 - Gaussian blur 3, horizontal 3 | // lewis@lewissaunders.com 4 | 5 | uniform sampler2D adsk_results_pass5; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform float blur3size; 8 | const float pi = 3.141592653589793238462643383279502884197969; 9 | 10 | void main() { 11 | vec2 xy = gl_FragCoord.xy; 12 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 13 | 14 | float sigma = blur3size; 15 | int support = int(sigma * 3.0); 16 | 17 | // Incremental coefficient calculation setup as per GPU Gems 3 18 | vec3 g; 19 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 20 | g.y = exp(-0.5 / (sigma * sigma)); 21 | g.z = g.y * g.y; 22 | 23 | if(sigma == 0.0) { 24 | g.x = 1.0; 25 | } 26 | 27 | // Centre sample 28 | vec4 a = g.x * texture2D(adsk_results_pass5, xy * px); 29 | float energy = g.x; 30 | g.xy *= g.yz; 31 | 32 | // The rest 33 | for(int i = 1; i <= support; i++) { 34 | a += g.x * texture2D(adsk_results_pass5, (xy - vec2(float(i), 0.0)) * px); 35 | a += g.x * texture2D(adsk_results_pass5, (xy + vec2(float(i), 0.0)) * px); 36 | energy += 2.0 * g.x; 37 | g.xy *= g.yz; 38 | } 39 | a /= energy; 40 | 41 | gl_FragColor = a; 42 | } 43 | -------------------------------------------------------------------------------- /Ls_Fluid.7.glsl: -------------------------------------------------------------------------------- 1 | // Undiverge a vector field 2 | // Pass 7 - Gaussian blur 3, vertical 3 | // lewis@lewissaunders.com 4 | 5 | uniform sampler2D adsk_results_pass6; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform float blur3size; 8 | const float pi = 3.141592653589793238462643383279502884197969; 9 | 10 | void main() { 11 | vec2 xy = gl_FragCoord.xy; 12 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 13 | 14 | float sigma = blur3size; 15 | int support = int(sigma * 3.0); 16 | 17 | // Incremental coefficient calculation setup as per GPU Gems 3 18 | vec3 g; 19 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 20 | g.y = exp(-0.5 / (sigma * sigma)); 21 | g.z = g.y * g.y; 22 | 23 | if(sigma == 0.0) { 24 | g.x = 1.0; 25 | } 26 | 27 | // Centre sample 28 | vec4 a = g.x * texture2D(adsk_results_pass6, xy * px); 29 | float energy = g.x; 30 | g.xy *= g.yz; 31 | 32 | // The rest 33 | for(int i = 1; i <= support; i++) { 34 | a += g.x * texture2D(adsk_results_pass6, (xy - vec2(0.0, float(i))) * px); 35 | a += g.x * texture2D(adsk_results_pass6, (xy + vec2(0.0, float(i))) * px); 36 | energy += 2.0 * g.x; 37 | g.xy *= g.yz; 38 | } 39 | a /= energy; 40 | 41 | gl_FragColor = a; 42 | } 43 | -------------------------------------------------------------------------------- /Ls_Fluid.8.glsl: -------------------------------------------------------------------------------- 1 | // Undiverge a vector field 2 | // Pass 8 - combine the three blurs, and differentiate to get an approximation of the 3 | // pressure field 4 | // lewis@lewissaunders.com 5 | 6 | uniform sampler2D adsk_results_pass3, adsk_results_pass5, adsk_results_pass7; 7 | uniform float adsk_result_w, adsk_result_h; 8 | uniform float d1, d2, d3, amount1, amount2, amount3; 9 | 10 | void main() { 11 | vec2 xy = gl_FragCoord.xy; 12 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 13 | 14 | vec3 a = vec3(0.0); 15 | a.r -= (amount1/d1) * texture2D(adsk_results_pass3, (xy + vec2(+d1, 0.0)) * px).r; 16 | a.r += (amount1/d1) * texture2D(adsk_results_pass3, (xy + vec2(-d1, 0.0)) * px).r; 17 | a.g -= (amount1/d1) * texture2D(adsk_results_pass3, (xy + vec2(0.0, +d1)) * px).g; 18 | a.g += (amount1/d1) * texture2D(adsk_results_pass3, (xy + vec2(0.0, -d1)) * px).g; 19 | a.r -= (amount2/d2) * texture2D(adsk_results_pass5, (xy + vec2(+d2, 0.0)) * px).r; 20 | a.r += (amount2/d2) * texture2D(adsk_results_pass5, (xy + vec2(-d2, 0.0)) * px).r; 21 | a.g -= (amount2/d2) * texture2D(adsk_results_pass5, (xy + vec2(0.0, +d2)) * px).g; 22 | a.g += (amount2/d2) * texture2D(adsk_results_pass5, (xy + vec2(0.0, -d2)) * px).g; 23 | a.r -= (amount3/d3) * texture2D(adsk_results_pass7, (xy + vec2(+d3, 0.0)) * px).r; 24 | a.r += (amount3/d3) * texture2D(adsk_results_pass7, (xy + vec2(-d3, 0.0)) * px).r; 25 | a.g -= (amount3/d3) * texture2D(adsk_results_pass7, (xy + vec2(0.0, +d3)) * px).g; 26 | a.g += (amount3/d3) * texture2D(adsk_results_pass7, (xy + vec2(0.0, -d3)) * px).g; 27 | 28 | float pressure = a.r + a.g; 29 | 30 | gl_FragColor = vec4(pressure); 31 | } 32 | -------------------------------------------------------------------------------- /Ls_Glint.1.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Glint.1.glsl.p -------------------------------------------------------------------------------- /Ls_Glint.2.glsl: -------------------------------------------------------------------------------- 1 | // Glint pass 2: Gaussian blur horizontal 2 | // lewis@lewissaunders.com 3 | 4 | uniform sampler2D adsk_results_pass1; 5 | uniform float blursize, blursizer, blursizeg, blursizeb; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform int downsample; 8 | 9 | // Return a 1D Gaussian blur 10 | // sampler is hard-coded to "adsk_results_pass1" to avoid a Baselight bug when passing it as an arg 11 | // xy: centre of blur in pixels 12 | // res: pixel size of mipmap level selected by lod param 13 | // sizes: sigma of blurs, in pixels 14 | // dir: direction of blur, usually vec2(1.0, 0.0) for horizontal followed by 15 | // another pass for vertical 16 | vec4 gaussianblur(vec2 xy, vec2 res, float sizered, float sizegreen, float sizeblue, float sizealpha, vec2 dir) { 17 | vec4 sigmas = vec4(sizered, sizegreen, sizeblue, sizealpha); 18 | 19 | // Set up state for incremental coefficient calculation, see GPU Gems 20 | // We use vec4s to store four copies of the state, for different size 21 | // red/green/blue/alpha blurs 22 | vec4 gx = vec4(0.0); 23 | vec4 gy = vec4(0.0); 24 | vec4 gz = vec4(0.0); 25 | 26 | gx = 1.0 / (sqrt(2.0 * 3.141592653589793238) * sigmas); 27 | gy = exp(-0.5 / (sigmas * sigmas)); 28 | gz = gy * gy; 29 | // vec4 a, centre, sample1, sample2 = vec4(0.0); 30 | vec4 a = vec4(0.0); 31 | vec4 centre = vec4(0.0); 32 | vec4 sample1 = vec4(0.0); 33 | vec4 sample2 = vec4(0.0); 34 | 35 | // First take the centre sample 36 | centre = texture2D(adsk_results_pass1, xy / res); 37 | a += gx * centre; 38 | vec4 energy = gx; 39 | gx *= gy; 40 | gy *= gz; 41 | 42 | // Now the other samples 43 | float support = max(max(max(sigmas.r, sigmas.g), sigmas.b), sigmas.a) * 3.0; 44 | for(float i = 1.0; i <= support; i++) { 45 | sample1 = texture2D(adsk_results_pass1, (xy - i * dir) / res); 46 | sample2 = texture2D(adsk_results_pass1, (xy + i * dir) / res); 47 | a += gx * sample1; 48 | a += gx * sample2; 49 | energy += 2.0 * gx; 50 | gx *= gy; 51 | gy *= gz; 52 | } 53 | 54 | a /= energy; 55 | 56 | if(sizered < 0.1) a.r = centre.r; 57 | if(sizegreen < 0.1) a.g = centre.g; 58 | if(sizeblue < 0.1) a.b = centre.b; 59 | 60 | return a; 61 | } 62 | 63 | void main() { 64 | vec2 res = vec2(adsk_result_w, adsk_result_h); 65 | vec2 xy = gl_FragCoord.xy / float(downsample+1); 66 | gl_FragColor = gaussianblur(xy, res, blursize*blursizer, blursize*blursizeg, blursize*blursizeb, 0.0, vec2(1.0, 0.0)); 67 | } 68 | -------------------------------------------------------------------------------- /Ls_Glint.3.glsl: -------------------------------------------------------------------------------- 1 | // Glint pass 3: Gaussian blur vertical and comp 2 | // lewis@lewissaunders.com 3 | 4 | uniform sampler2D adsk_results_pass2, front, matte; 5 | uniform float blursize, blursizer, blursizeg, blursizeb; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform bool screen, usematte, useblendmatte, outputglints; 8 | 9 | // RGB to Rec709 YPbPr 10 | vec3 yuv(vec3 rgb) { 11 | return mat3(0.2215, -0.1145, 0.5016, 0.7154, -0.3855, -0.4556, 0.0721, 0.5, -0.0459) * rgb; 12 | } 13 | 14 | // Return a 1D Gaussian blur 15 | // sampler is hard-coded to "adsk_results_pass2" to avoid a Baselight bug when passing it as an arg 16 | // xy: centre of blur in pixels 17 | // res: pixel size of mipmap level selected by lod param 18 | // sizes: sigma of blurs, in pixels 19 | // dir: direction of blur, usually vec2(1.0, 0.0) for horizontal followed by 20 | // another pass for vertical 21 | vec4 gaussianblur(vec2 xy, vec2 res, float sizered, float sizegreen, float sizeblue, float sizealpha, vec2 dir) { 22 | vec4 sigmas = vec4(sizered, sizegreen, sizeblue, sizealpha); 23 | 24 | // Set up state for incremental coefficient calculation, see GPU Gems 25 | // We use vec4s to store four copies of the state, for different size 26 | // red/green/blue/alpha blurs 27 | vec4 gx, gy, gz; 28 | gx = 1.0 / (sqrt(2.0 * 3.141592653589793238) * sigmas); 29 | gy = exp(-0.5 / (sigmas * sigmas)); 30 | gz = gy * gy; 31 | // vec4 a, centre, sample1, sample2 = vec4(0.0); 32 | vec4 a = vec4(0.0); 33 | vec4 centre = vec4(0.0); 34 | vec4 sample1 = vec4(0.0); 35 | vec4 sample2 = vec4(0.0); 36 | 37 | // First take the centre sample 38 | centre = texture2D(adsk_results_pass2, xy / res); 39 | a += gx * centre; 40 | vec4 energy = gx; 41 | gx *= gy; 42 | gy *= gz; 43 | 44 | // Now the other samples 45 | float support = max(max(max(sigmas.r, sigmas.g), sigmas.b), sigmas.a) * 3.0; 46 | for(float i = 1.0; i <= support; i++) { 47 | sample1 = texture2D(adsk_results_pass2, (xy - i * dir) / res); 48 | sample2 = texture2D(adsk_results_pass2, (xy + i * dir) / res); 49 | a += gx * sample1; 50 | a += gx * sample2; 51 | energy += 2.0 * gx; 52 | gx *= gy; 53 | gy *= gz; 54 | } 55 | 56 | a /= energy; 57 | 58 | if(sizered < 0.1) a.r = centre.r; 59 | if(sizegreen < 0.1) a.g = centre.g; 60 | if(sizeblue < 0.1) a.b = centre.b; 61 | 62 | return a; 63 | } 64 | 65 | void main() { 66 | vec2 res = vec2(adsk_result_w, adsk_result_h); 67 | vec2 xy = gl_FragCoord.xy; 68 | 69 | vec3 frontpix = texture2D(front, xy/res).rgb; 70 | vec3 mattepix = texture2D(matte, xy/res).rgb; 71 | 72 | vec3 blurred = gaussianblur(xy, res, blursize*blursizer, blursize*blursizeg, blursize*blursizeb, 0.0, vec2(0.0, 1.0)).rgb; 73 | 74 | // Blend with front input 75 | vec3 result; 76 | float blurredluma = 0.0; 77 | if(useblendmatte) { 78 | blurred *= mattepix; 79 | blurredluma = yuv(blurred.rgb).r; // Luma is used for matte output below 80 | } 81 | if(screen) { 82 | result = max(max(frontpix, blurred), blurred+frontpix-(blurred*frontpix)); 83 | } else { 84 | result = frontpix + blurred; 85 | } 86 | if(outputglints) { 87 | result = blurred; 88 | } 89 | 90 | // Matte output is luma of glint only 91 | gl_FragColor = vec4(result, blurredluma); 92 | } 93 | -------------------------------------------------------------------------------- /Ls_GlueP.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_GlueP.glsl.p -------------------------------------------------------------------------------- /Ls_Lumps.1.glsl: -------------------------------------------------------------------------------- 1 | /* The three bands are made like this: 2 | colour = colourblur 3 | lumps = lumpsblur - colourblur 4 | detail = front input - lumpsblur 5 | 6 | There are quite a few passes so here's a diagram of how they connect: 7 | 8 | front input 9 | │ 10 | ┌────────┴───────────┬─────────────────────┬──────────┐ 11 | │ │ │ │ 12 | ▼ ▼ │ │ 13 | 01 colourblur h 03 lumpsblur h │ │ 14 | │ │ │ │ 15 | ▼ ▼ │ │ 16 | ┌── 02 colourblur v 04 lumpsblur v ───┬─────┐ │ │ 17 | │ │ │ │ │ │ │ 18 | │ ├──────────┬─────┐ │ │ │ │ │ 19 | │ │ │ │ │ │ │ │ │ 20 | │ ▼ │ ▼ ▼ │ ▼ ▼ │ 21 | │ 05 colourfilter h │ 07 lumpsfilter h │ 09 detailfilter h │ 22 | │ │ │ │ │ │ │ 23 | │ ▼ │ ▼ │───────┐ │ │ 24 | └► 06 colourfilter v └► 08 lumpsfilter v ◄┘ │ │ │ 25 | │ │ │ │ │ 26 | │ └───────────────┐ │ │ ┌───────┘ 27 | │ ▼ ▼ ▼ ▼ 28 | └────────────────────────────────► 10 detailfilter v, 29 | combine and output 30 | 31 | Passes 05, 06, 07, 08, 09 and 10 can also use the colour/lumps/detail inputs 32 | directly when in "recombine" mode, instead of calculating them from the blurs 33 | 34 | Pass 02 can also use the front input's top MIP level to compute a whole image 35 | average, instead of blurring 36 | */ 37 | 38 | // Colour blur horizontal pass 39 | // lewis@lewissaunders.com 40 | 41 | uniform sampler2D front; 42 | uniform float adsk_result_w, adsk_result_h; 43 | uniform float coloursize; 44 | uniform bool recombine, mipmapcolour; 45 | const float pi = 3.141592653589793238462643383279502884197969; 46 | 47 | void main() { 48 | if(recombine) discard; 49 | if(mipmapcolour) discard; 50 | 51 | vec2 xy = gl_FragCoord.xy; 52 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 53 | 54 | float sigma = coloursize; 55 | int support = int(sigma * 3.0); 56 | 57 | // Incremental coefficient calculation setup as per GPU Gems 3 58 | vec3 g; 59 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 60 | g.y = exp(-0.5 / (sigma * sigma)); 61 | g.z = g.y * g.y; 62 | 63 | if(sigma == 0.0) { 64 | g.x = 1.0; 65 | } 66 | 67 | // Centre sample 68 | vec4 a = g.x * texture2D(front, xy * px); 69 | float energy = g.x; 70 | g.xy *= g.yz; 71 | 72 | // The rest 73 | for(int i = 1; i <= support; i++) { 74 | a += g.x * texture2D(front, (xy - vec2(float(i), 0.0)) * px); 75 | a += g.x * texture2D(front, (xy + vec2(float(i), 0.0)) * px); 76 | energy += 2.0 * g.x; 77 | g.xy *= g.yz; 78 | } 79 | a /= energy; 80 | 81 | gl_FragColor = a; 82 | } 83 | -------------------------------------------------------------------------------- /Ls_Lumps.1.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Lumps.1.glsl.p -------------------------------------------------------------------------------- /Ls_Lumps.10.glsl: -------------------------------------------------------------------------------- 1 | // Detail filter vertical pass and split/scale/combine 2 | // lewis@lewissaunders.com 3 | 4 | uniform sampler2D front, adsk_results_pass4, adsk_results_pass6, adsk_results_pass8, adsk_results_pass9; 5 | uniform sampler2D colourt, lumpst, detailt; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform float detailfiltersize, detailsharpenamnt; 8 | uniform bool outputcolour, outputlumps, outputdetail; 9 | uniform float colourgamma, colourcontrast; 10 | uniform float lumpsgamma, lumpscontrast; 11 | uniform float detailgamma, detailcontrast; 12 | uniform float scolour, slumps, sdetail; 13 | uniform bool recombine, islin; 14 | const float pi = 3.141592653589793238462643383279502884197969; 15 | 16 | vec4 getdetail(vec2 xy) { 17 | if(recombine) { 18 | // Use node's detail input 19 | if(islin) { 20 | return texture2D(detailt, xy) - vec4(0.18); 21 | } else { 22 | return texture2D(detailt, xy) - vec4(0.5); 23 | } 24 | } else { 25 | // Use our calculated detail band 26 | return texture2D(front, xy) - texture2D(adsk_results_pass4, xy); 27 | } 28 | } 29 | 30 | void main() { 31 | vec2 xy = gl_FragCoord.xy; 32 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 33 | 34 | float sigma = abs(detailfiltersize); 35 | int support = int(sigma * 3.0); 36 | 37 | // Incremental coefficient calculation setup as per GPU Gems 3 38 | vec3 g; 39 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 40 | g.y = exp(-0.5 / (sigma * sigma)); 41 | g.z = g.y * g.y; 42 | 43 | if(sigma == 0.0) { 44 | g.x = 1.0; 45 | } 46 | 47 | // Centre sample 48 | vec4 a = g.x * texture2D(adsk_results_pass9, xy * px); 49 | float energy = g.x; 50 | g.xy *= g.yz; 51 | 52 | // The rest 53 | for(int i = 1; i <= support; i++) { 54 | a += g.x * texture2D(adsk_results_pass9, (xy - vec2(0.0, float(i))) * px); 55 | a += g.x * texture2D(adsk_results_pass9, (xy + vec2(0.0, float(i))) * px); 56 | energy += 2.0 * g.x; 57 | g.xy *= g.yz; 58 | } 59 | a /= energy; 60 | 61 | vec4 filtered = a; 62 | vec4 detailunfilt = getdetail(xy * px); 63 | if(detailfiltersize < 0.0) { 64 | // Sharpen rather than blur 65 | filtered = detailunfilt + detailsharpenamnt * (detailunfilt - filtered); 66 | } 67 | 68 | vec4 colour = texture2D(adsk_results_pass6, xy * px); 69 | vec4 lumps = texture2D(adsk_results_pass8, xy * px); 70 | vec4 detail = filtered; 71 | 72 | // Grade each band 73 | colour *= colourcontrast; 74 | colour = sign(colour) * pow(abs(colour), vec4(1.0/colourgamma)); 75 | lumps *= lumpscontrast; 76 | lumps = sign(lumps) * pow(abs(lumps), vec4(1.0/lumpsgamma)); 77 | detail *= detailcontrast; 78 | detail = sign(detail) * pow(abs(detail), vec4(1.0/detailgamma)); 79 | colour *= scolour; 80 | lumps *= slumps; 81 | detail *= sdetail; 82 | 83 | vec4 o = vec4(islin ? 0.18 : 0.5); 84 | if(outputcolour) o = colour; 85 | if(outputlumps) o += lumps; 86 | if(outputdetail) o += detail; 87 | gl_FragColor = o; 88 | 89 | } 90 | -------------------------------------------------------------------------------- /Ls_Lumps.2.glsl: -------------------------------------------------------------------------------- 1 | // Colour blur vertical pass 2 | // lewis@lewissaunders.com 3 | 4 | #extension GL_ARB_shader_texture_lod : enable 5 | 6 | uniform sampler2D front, adsk_results_pass1; 7 | uniform float adsk_result_w, adsk_result_h; 8 | uniform float coloursize; 9 | uniform bool recombine, mipmapcolour; 10 | const float pi = 3.141592653589793238462643383279502884197969; 11 | 12 | void main() { 13 | if(recombine) discard; 14 | 15 | vec2 xy = gl_FragCoord.xy; 16 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 17 | 18 | if(mipmapcolour) { 19 | // Instead of blurring, use the top MIP level as a whole-image average 20 | gl_FragColor = texture2DLod(front, xy * px, 99.0); 21 | return; 22 | } 23 | 24 | float sigma = coloursize; 25 | int support = int(sigma * 3.0); 26 | 27 | // Incremental coefficient calculation setup as per GPU Gems 3 28 | vec3 g; 29 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 30 | g.y = exp(-0.5 / (sigma * sigma)); 31 | g.z = g.y * g.y; 32 | 33 | if(sigma == 0.0) { 34 | g.x = 1.0; 35 | } 36 | 37 | // Centre sample 38 | vec4 a = g.x * texture2D(adsk_results_pass1, xy * px); 39 | float energy = g.x; 40 | g.xy *= g.yz; 41 | 42 | // The rest 43 | for(int i = 1; i <= support; i++) { 44 | a += g.x * texture2D(adsk_results_pass1, (xy - vec2(0.0, float(i))) * px); 45 | a += g.x * texture2D(adsk_results_pass1, (xy + vec2(0.0, float(i))) * px); 46 | energy += 2.0 * g.x; 47 | g.xy *= g.yz; 48 | } 49 | a /= energy; 50 | 51 | gl_FragColor = a; 52 | } 53 | -------------------------------------------------------------------------------- /Ls_Lumps.3.glsl: -------------------------------------------------------------------------------- 1 | // Lumps blur horizontal pass 2 | // lewis@lewissaunders.com 3 | 4 | uniform sampler2D front; 5 | uniform float adsk_result_w, adsk_result_h; 6 | uniform float lumpsize; 7 | uniform bool recombine; 8 | const float pi = 3.141592653589793238462643383279502884197969; 9 | 10 | void main() { 11 | if(recombine) discard; 12 | 13 | vec2 xy = gl_FragCoord.xy; 14 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 15 | 16 | float sigma = lumpsize; 17 | int support = int(sigma * 3.0); 18 | 19 | // Incremental coefficient calculation setup as per GPU Gems 3 20 | vec3 g; 21 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 22 | g.y = exp(-0.5 / (sigma * sigma)); 23 | g.z = g.y * g.y; 24 | 25 | if(sigma == 0.0) { 26 | g.x = 1.0; 27 | } 28 | 29 | // Centre sample 30 | vec4 a = g.x * texture2D(front, xy * px); 31 | float energy = g.x; 32 | g.xy *= g.yz; 33 | 34 | // The rest 35 | for(int i = 1; i <= support; i++) { 36 | a += g.x * texture2D(front, (xy - vec2(float(i), 0.0)) * px); 37 | a += g.x * texture2D(front, (xy + vec2(float(i), 0.0)) * px); 38 | energy += 2.0 * g.x; 39 | g.xy *= g.yz; 40 | } 41 | a /= energy; 42 | 43 | gl_FragColor = a; 44 | } 45 | -------------------------------------------------------------------------------- /Ls_Lumps.4.glsl: -------------------------------------------------------------------------------- 1 | // Lumps blur vertical pass 2 | // lewis@lewissaunders.com 3 | 4 | uniform sampler2D adsk_results_pass3; 5 | uniform float adsk_result_w, adsk_result_h; 6 | uniform float lumpsize; 7 | uniform bool recombine; 8 | const float pi = 3.141592653589793238462643383279502884197969; 9 | 10 | void main() { 11 | if(recombine) discard; 12 | 13 | vec2 xy = gl_FragCoord.xy; 14 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 15 | 16 | float sigma = lumpsize; 17 | int support = int(sigma * 3.0); 18 | 19 | // Incremental coefficient calculation setup as per GPU Gems 3 20 | vec3 g; 21 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 22 | g.y = exp(-0.5 / (sigma * sigma)); 23 | g.z = g.y * g.y; 24 | 25 | if(sigma == 0.0) { 26 | g.x = 1.0; 27 | } 28 | 29 | // Centre sample 30 | vec4 a = g.x * texture2D(adsk_results_pass3, xy * px); 31 | float energy = g.x; 32 | g.xy *= g.yz; 33 | 34 | // The rest 35 | for(int i = 1; i <= support; i++) { 36 | a += g.x * texture2D(adsk_results_pass3, (xy - vec2(0.0, float(i))) * px); 37 | a += g.x * texture2D(adsk_results_pass3, (xy + vec2(0.0, float(i))) * px); 38 | energy += 2.0 * g.x; 39 | g.xy *= g.yz; 40 | } 41 | a /= energy; 42 | 43 | gl_FragColor = a; 44 | } 45 | -------------------------------------------------------------------------------- /Ls_Lumps.5.glsl: -------------------------------------------------------------------------------- 1 | // Colour filter horizontal pass 2 | // lewis@lewissaunders.com 3 | 4 | uniform sampler2D adsk_results_pass2, colourt; 5 | uniform float adsk_result_w, adsk_result_h; 6 | uniform float colourfiltersize; 7 | uniform bool recombine; 8 | const float pi = 3.141592653589793238462643383279502884197969; 9 | 10 | vec4 getcolour(vec2 xy) { 11 | if(recombine) { 12 | // Use node's colour input 13 | return texture2D(colourt, xy); 14 | } else { 15 | // Use our calculated colour band 16 | return texture2D(adsk_results_pass2, xy); 17 | } 18 | } 19 | 20 | void main() { 21 | vec2 xy = gl_FragCoord.xy; 22 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 23 | 24 | float sigma = abs(colourfiltersize); 25 | int support = int(sigma * 3.0); 26 | 27 | // Incremental coefficient calculation setup as per GPU Gems 3 28 | vec3 g; 29 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 30 | g.y = exp(-0.5 / (sigma * sigma)); 31 | g.z = g.y * g.y; 32 | 33 | if(sigma == 0.0) { 34 | g.x = 1.0; 35 | } 36 | 37 | // Centre sample 38 | vec4 a = g.x * getcolour(xy * px); 39 | float energy = g.x; 40 | g.xy *= g.yz; 41 | 42 | // The rest 43 | for(int i = 1; i <= support; i++) { 44 | a += g.x * getcolour((xy - vec2(float(i), 0.0)) * px); 45 | a += g.x * getcolour((xy + vec2(float(i), 0.0)) * px); 46 | energy += 2.0 * g.x; 47 | g.xy *= g.yz; 48 | } 49 | a /= energy; 50 | 51 | gl_FragColor = a; 52 | } 53 | -------------------------------------------------------------------------------- /Ls_Lumps.6.glsl: -------------------------------------------------------------------------------- 1 | // Colour filter vertical pass 2 | // lewis@lewissaunders.com 3 | 4 | uniform sampler2D adsk_results_pass2, adsk_results_pass5, colourt; 5 | uniform float adsk_result_w, adsk_result_h; 6 | uniform float colourfiltersize, coloursharpenamnt; 7 | uniform bool recombine; 8 | const float pi = 3.141592653589793238462643383279502884197969; 9 | 10 | vec4 getcolour(vec2 xy) { 11 | if(recombine) { 12 | // Use node's colour input 13 | return texture2D(colourt, xy); 14 | } else { 15 | // Use our calculated colour band 16 | return texture2D(adsk_results_pass2, xy); 17 | } 18 | } 19 | 20 | void main() { 21 | vec2 xy = gl_FragCoord.xy; 22 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 23 | 24 | float sigma = abs(colourfiltersize); 25 | int support = int(sigma * 3.0); 26 | 27 | // Incremental coefficient calculation setup as per GPU Gems 3 28 | vec3 g; 29 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 30 | g.y = exp(-0.5 / (sigma * sigma)); 31 | g.z = g.y * g.y; 32 | 33 | if(sigma == 0.0) { 34 | g.x = 1.0; 35 | } 36 | 37 | // Centre sample 38 | vec4 a = g.x * texture2D(adsk_results_pass5, xy * px); 39 | float energy = g.x; 40 | g.xy *= g.yz; 41 | 42 | // The rest 43 | for(int i = 1; i <= support; i++) { 44 | a += g.x * texture2D(adsk_results_pass5, (xy - vec2(0.0, float(i))) * px); 45 | a += g.x * texture2D(adsk_results_pass5, (xy + vec2(0.0, float(i))) * px); 46 | energy += 2.0 * g.x; 47 | g.xy *= g.yz; 48 | } 49 | a /= energy; 50 | 51 | vec4 filtered = a; 52 | vec4 colour = getcolour(xy * px); 53 | if(colourfiltersize < 0.0) { 54 | // Sharpen rather than blur 55 | filtered = colour + coloursharpenamnt * (colour - filtered); 56 | } 57 | 58 | gl_FragColor = filtered; 59 | } 60 | -------------------------------------------------------------------------------- /Ls_Lumps.7.glsl: -------------------------------------------------------------------------------- 1 | // Lumps filter horizontal pass 2 | // lewis@lewissaunders.com 3 | 4 | uniform sampler2D adsk_results_pass2, adsk_results_pass4, lumpst; 5 | uniform float adsk_result_w, adsk_result_h; 6 | uniform float lumpsfiltersize; 7 | uniform bool recombine, islin; 8 | const float pi = 3.141592653589793238462643383279502884197969; 9 | 10 | vec4 getlumps(vec2 xy) { 11 | if(recombine) { 12 | // Use node's lumps input 13 | if(islin) { 14 | return texture2D(lumpst, xy) - vec4(0.18); 15 | } else { 16 | return texture2D(lumpst, xy) - vec4(0.5); 17 | } 18 | } else { 19 | // Use our calculated lumps band 20 | return texture2D(adsk_results_pass4, xy) - texture2D(adsk_results_pass2, xy); 21 | } 22 | } 23 | 24 | void main() { 25 | vec2 xy = gl_FragCoord.xy; 26 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 27 | 28 | float sigma = abs(lumpsfiltersize); 29 | int support = int(sigma * 3.0); 30 | 31 | // Incremental coefficient calculation setup as per GPU Gems 3 32 | vec3 g; 33 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 34 | g.y = exp(-0.5 / (sigma * sigma)); 35 | g.z = g.y * g.y; 36 | 37 | if(sigma == 0.0) { 38 | g.x = 1.0; 39 | } 40 | 41 | // Centre sample 42 | vec4 a = g.x * getlumps(xy * px); 43 | float energy = g.x; 44 | g.xy *= g.yz; 45 | 46 | // The rest 47 | for(int i = 1; i <= support; i++) { 48 | a += g.x * getlumps((xy - vec2(float(i), 0.0)) * px); 49 | a += g.x * getlumps((xy + vec2(float(i), 0.0)) * px); 50 | energy += 2.0 * g.x; 51 | g.xy *= g.yz; 52 | } 53 | a /= energy; 54 | 55 | gl_FragColor = a; 56 | } 57 | -------------------------------------------------------------------------------- /Ls_Lumps.8.glsl: -------------------------------------------------------------------------------- 1 | // Lumps filter vertical pass 2 | // lewis@lewissaunders.com 3 | 4 | uniform sampler2D adsk_results_pass2, adsk_results_pass4, adsk_results_pass7, lumpst; 5 | uniform float adsk_result_w, adsk_result_h; 6 | uniform float lumpsfiltersize, lumpssharpenamnt; 7 | uniform bool recombine, islin; 8 | const float pi = 3.141592653589793238462643383279502884197969; 9 | 10 | vec4 getlumps(vec2 xy) { 11 | if(recombine) { 12 | // Use node's lumps input 13 | if(islin) { 14 | return texture2D(lumpst, xy) - vec4(0.18); 15 | } else { 16 | return texture2D(lumpst, xy) - vec4(0.5); 17 | } 18 | } else { 19 | // Use our calculated lumps band 20 | return texture2D(adsk_results_pass4, xy) - texture2D(adsk_results_pass2, xy); 21 | } 22 | } 23 | 24 | void main() { 25 | vec2 xy = gl_FragCoord.xy; 26 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 27 | 28 | float sigma = abs(lumpsfiltersize); 29 | int support = int(sigma * 3.0); 30 | 31 | // Incremental coefficient calculation setup as per GPU Gems 3 32 | vec3 g; 33 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 34 | g.y = exp(-0.5 / (sigma * sigma)); 35 | g.z = g.y * g.y; 36 | 37 | if(sigma == 0.0) { 38 | g.x = 1.0; 39 | } 40 | 41 | // Centre sample 42 | vec4 a = g.x * texture2D(adsk_results_pass7, xy * px); 43 | float energy = g.x; 44 | g.xy *= g.yz; 45 | 46 | // The rest 47 | for(int i = 1; i <= support; i++) { 48 | a += g.x * texture2D(adsk_results_pass7, (xy - vec2(0.0, float(i))) * px); 49 | a += g.x * texture2D(adsk_results_pass7, (xy + vec2(0.0, float(i))) * px); 50 | energy += 2.0 * g.x; 51 | g.xy *= g.yz; 52 | } 53 | a /= energy; 54 | 55 | vec4 filtered = a; 56 | vec4 lumps = getlumps(xy * px); 57 | if(lumpsfiltersize < 0.0) { 58 | // Sharpen rather than blur 59 | filtered = lumps + lumpssharpenamnt * (lumps - filtered); 60 | } 61 | 62 | gl_FragColor = filtered; 63 | } 64 | -------------------------------------------------------------------------------- /Ls_Lumps.9.glsl: -------------------------------------------------------------------------------- 1 | // Detail filter horizontal pass 2 | // lewis@lewissaunders.com 3 | 4 | uniform sampler2D front, adsk_results_pass4, detailt; 5 | uniform float adsk_result_w, adsk_result_h; 6 | uniform float detailfiltersize; 7 | uniform bool recombine, islin; 8 | const float pi = 3.141592653589793238462643383279502884197969; 9 | 10 | vec4 getdetail(vec2 xy) { 11 | if(recombine) { 12 | // Use node's detail input 13 | if(islin) { 14 | return texture2D(detailt, xy) - vec4(0.18); 15 | } else { 16 | return texture2D(detailt, xy) - vec4(0.5); 17 | } 18 | } else { 19 | // Use our calculated detail band 20 | return texture2D(front, xy) - texture2D(adsk_results_pass4, xy); 21 | } 22 | } 23 | 24 | void main() { 25 | vec2 xy = gl_FragCoord.xy; 26 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 27 | 28 | float sigma = abs(detailfiltersize); 29 | int support = int(sigma * 3.0); 30 | 31 | // Incremental coefficient calculation setup as per GPU Gems 3 32 | vec3 g; 33 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 34 | g.y = exp(-0.5 / (sigma * sigma)); 35 | g.z = g.y * g.y; 36 | 37 | if(sigma == 0.0) { 38 | g.x = 1.0; 39 | } 40 | 41 | // Centre sample 42 | vec4 a = g.x * getdetail(xy * px); 43 | float energy = g.x; 44 | g.xy *= g.yz; 45 | 46 | // The rest 47 | for(int i = 1; i <= support; i++) { 48 | a += g.x * getdetail((xy - vec2(float(i), 0.0)) * px); 49 | a += g.x * getdetail((xy + vec2(float(i), 0.0)) * px); 50 | energy += 2.0 * g.x; 51 | g.xy *= g.yz; 52 | } 53 | a /= energy; 54 | 55 | gl_FragColor = a; 56 | } 57 | -------------------------------------------------------------------------------- /Ls_NaNfix.glsl: -------------------------------------------------------------------------------- 1 | // NaNfix - interpolate NaN pixels from surroundings 2 | // lewis@lewissaunders.com 3 | 4 | uniform float adsk_result_w, adsk_result_h; 5 | uniform sampler2D front; 6 | uniform vec3 tempcolour; 7 | uniform int radius; 8 | 9 | bool isnan(float f) { 10 | // Try a few things. Some drivers optimise some of them away :/ 11 | if(f != f) { 12 | return true; 13 | } 14 | if(f < 0.0 || 0.0 < f || f == 0.0) { 15 | return false; 16 | } else { 17 | return true; 18 | } 19 | } 20 | 21 | bool anynans(vec3 v) { 22 | if(isnan(v.r)) return true; 23 | if(isnan(v.g)) return true; 24 | if(isnan(v.b)) return true; 25 | return false; 26 | } 27 | 28 | void main() { 29 | vec2 res = vec2(adsk_result_w, adsk_result_h); 30 | vec2 xy = gl_FragCoord.xy; 31 | 32 | vec3 o = texture2D(front, xy / res).rgb; 33 | float m = 0.0; 34 | 35 | if(anynans(o)) { 36 | o = vec3(0.0); 37 | m = 1.0; 38 | float count = 0.0; 39 | float r = float(radius); 40 | for(float i = -r; i <= r; i += 1.0) { 41 | for(float j = -r; j <= r; j += 1.0) { 42 | vec3 here = texture2D(front, (xy + vec2(i, j))/res).rgb; 43 | if(!anynans(here)) { 44 | o += here; 45 | count += 1.0; 46 | } 47 | } 48 | } 49 | if(count == 0.0) { 50 | // Couldn't find any good pixels in surroundings! Output black. 51 | o = vec3(0.0); 52 | } else { 53 | o /= count; 54 | } 55 | } 56 | 57 | gl_FragColor = vec4(o, m); 58 | } 59 | -------------------------------------------------------------------------------- /Ls_NaNfix.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_NaNfix.glsl.p -------------------------------------------------------------------------------- /Ls_NaNfix.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Ls_Nail.glsl: -------------------------------------------------------------------------------- 1 | // Transforms the area inside the nail matte by the difference between two tracks 2 | // Use to stick down floating CG, by nailing from a track on the CG to a track on the BG 3 | // lewis@lewissaunders.com 4 | // TODO: 5 | // o Anti-aliased overlay 6 | // o Rotate, scale, shear? 7 | // o Better filtering probably. Not sure if EWA would work because no dFdx? 8 | 9 | uniform sampler2D front, matte, nailmatte; 10 | uniform float adsk_result_w, adsk_result_h; 11 | uniform vec2 trackfrom, trackto, offset; 12 | uniform float extra, amount, edgeswoop; 13 | uniform bool manualtracks, matteistarget, overlay; 14 | uniform vec3 areatint; 15 | 16 | float distanceToSegment(vec2 p0, vec2 p1, vec2 p) { 17 | vec2 v = p1 - p0; 18 | vec2 w = p - p0; 19 | float c1 = dot(w, v); 20 | float c2 = dot(v, v); 21 | 22 | if(c1 <= 0.0) 23 | return length(p0 - p); 24 | if(c2 <= c1) 25 | return length(p1 - p); 26 | 27 | float b = c1 / c2; 28 | vec2 pb = p0 + b * v; 29 | return length(pb - p); 30 | } 31 | 32 | void main() { 33 | vec2 res = vec2(adsk_result_w, adsk_result_h); 34 | vec2 coords = gl_FragCoord.xy / res; 35 | 36 | vec2 diff = trackto - trackfrom + offset; 37 | diff *= extra; 38 | diff *= amount; 39 | 40 | if(!manualtracks) { 41 | diff /= res; 42 | } 43 | 44 | float coeff = 0.0; 45 | if(matteistarget) { 46 | coeff = texture2D(nailmatte, coords).b; 47 | } else { 48 | coeff = texture2D(nailmatte, coords - diff).b; 49 | } 50 | coeff = mix(coeff, smoothstep(0.0, 1.0, coeff), edgeswoop); 51 | diff *= coeff; 52 | 53 | vec2 q = coords - diff; 54 | 55 | vec3 o = texture2D(front, q).rgb; 56 | float m = texture2D(matte, q).b; 57 | 58 | if(overlay) { 59 | vec2 trackfromp = trackfrom; 60 | vec2 tracktop = trackto; 61 | vec2 offsetp = offset; 62 | vec2 coordsp = coords * res; 63 | 64 | if(manualtracks) { 65 | trackfromp *= res; 66 | tracktop *= res; 67 | offsetp *= res; 68 | } 69 | 70 | if(length(coordsp - trackfromp) < 5.0) 71 | o = vec3(0.8, 0.2, 0.2); 72 | 73 | if(length(coordsp - tracktop) < 5.0) 74 | o = vec3(0.2, 0.8, 0.2); 75 | 76 | if(length(offsetp) > 0.0) { 77 | if(length(coordsp - (tracktop + offsetp)) < 5.0) { 78 | o = vec3(0.2, 0.2, 0.8); 79 | } 80 | } 81 | 82 | if(distanceToSegment(trackfromp, tracktop + offsetp, coordsp) < 1.0) { 83 | if(mod(length(trackfromp - coordsp), 8.0) < 4.0) { 84 | o = vec3(0.4, 0.4, 0.8); 85 | } 86 | } 87 | o += coeff * areatint; 88 | } 89 | 90 | gl_FragColor = vec4(o, m); 91 | } 92 | -------------------------------------------------------------------------------- /Ls_Nail.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Nail.glsl.p -------------------------------------------------------------------------------- /Ls_Pentatone.glsl: -------------------------------------------------------------------------------- 1 | // Pentatone 2 | // Move colours towards 2, 3, 4 or 5 target colours 3 | // lewis@lewissaunders.com 4 | 5 | uniform sampler2D front, matte; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform vec3 target1, target2, target3, target4, target5; 8 | uniform float s, t; 9 | 10 | vec2 res = vec2(adsk_result_w, adsk_result_h); 11 | vec2 xy = gl_FragCoord.xy / res; 12 | 13 | void main() { 14 | vec3 rgb = texture2D(front, xy).rgb; 15 | float matte = texture2D(matte, xy).b; 16 | 17 | vec3 force1 = t * (target1 - rgb) * (1.0 - smoothstep(0.0, s, length(target1 - rgb))); 18 | /*vec3 to2 = normalize(target2 - rgb) * s * length(target2 - rgb); 19 | vec3 to3 = normalize(target3 - rgb) * s * length(target3 - rgb); 20 | vec3 to4 = normalize(target4 - rgb) * s * length(target4 - rgb); 21 | vec3 to5 = normalize(target5 - rgb) * s * length(target5 - rgb);*/ 22 | 23 | rgb += force1; 24 | 25 | gl_FragColor = vec4(rgb, 1.0); 26 | } 27 | -------------------------------------------------------------------------------- /Ls_Poly.01.glsl: -------------------------------------------------------------------------------- 1 | /* Poly 2 | lewis@lewissaunders.com 3 | 4 | Create Voronoi diagrams and Deluanay triangulations from seed points in image by 5 | jump flooding, as per "Jump Flooding in GPU" paper 6 | http://www.comp.nus.edu.sg/~tants/jfa.html 7 | 8 | This was inspired by Tom Dobrowolski's shader, reading which was very instructive: 9 | https://www.shadertoy.com/view/ldV3Wc 10 | 11 | TODO: 12 | o There are still occasional glitches and black triangles 13 | o Use 1+JFA instead of standard JFA? 14 | o Seed generation clusters a lot, could be more sophisticated 15 | o Does sdTriangle take into account anamorphicity of 0-1 texel coord space? 16 | o Trimming long thin triangles might help more than trimming small ones 17 | o Fake anchor points at image corners/edges? 18 | o Output dual of seeds, i.e. points at junctions of Voronoi diagram 19 | o Figure out if/why our distance transform output is inferior to OpenCV 20 | o Remove 4096.0 flood steps, since running at 8k uses impossible amount of VRAM? 21 | o Strength inputs which module scale/rotation of sprites/dots/edges/magnify modes 22 | 23 | Pass 1: create seed points from input video 24 | */ 25 | 26 | #extension GL_ARB_shader_texture_lod : enable 27 | 28 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio; 29 | uniform sampler2D front, thresholdi; 30 | uniform float seedthres; 31 | uniform bool inputisseeds; 32 | vec2 res = vec2(adsk_result_w, adsk_result_h); 33 | 34 | void main() { 35 | vec2 xy = gl_FragCoord.xy / res; 36 | 37 | vec3 frontrgb = texture2D(front, xy).rgb; 38 | float frontluma = dot(frontrgb, vec3(0.2126, 0.7152, 0.0722)); 39 | 40 | vec3 miprgb = texture2DLod(front, xy, 3.0).rgb; 41 | float mipluma = dot(miprgb, vec3(0.2126, 0.7152, 0.0722)); 42 | 43 | float seedness = abs(frontluma - mipluma); 44 | 45 | if(inputisseeds) { 46 | seedness = frontluma; 47 | } 48 | 49 | vec4 o; 50 | float modulated_threshold = pow(seedthres, 3.0); 51 | modulated_threshold *= texture2D(thresholdi, xy).g; 52 | if(seedness > modulated_threshold) { 53 | // This is a seed pixel, output current coords 54 | o = vec4(xy, 0.0, 0.0); 55 | } else { 56 | // This is not a seed, we don't know the closest seed, output -999 57 | o = vec4(-999.0); 58 | } 59 | gl_FragColor = o; 60 | } 61 | -------------------------------------------------------------------------------- /Ls_Poly.01.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Poly.01.glsl.p -------------------------------------------------------------------------------- /Ls_Poly.02.glsl: -------------------------------------------------------------------------------- 1 | // Poly 2 | // Pass 2: jump flood out coords of closest seeds, round 1, distance 4096 3 | 4 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio, normp; 5 | uniform sampler2D adsk_results_pass1; 6 | vec2 res = vec2(adsk_result_w, adsk_result_h); 7 | 8 | float alength(vec2 v) { 9 | v.y /= adsk_result_frameratio; 10 | return pow(pow(abs(v.x), normp) + pow(abs(v.y), normp), 1.0/normp); 11 | } 12 | 13 | void main() { 14 | vec2 xy = gl_FragCoord.xy / res; 15 | 16 | vec4 bestseed = vec4(-999.0); 17 | float bestdist = 99999.0; 18 | for(float j = -1.0; j <= 1.0; j += 1.0) { 19 | for(float k = -1.0; k <= 1.0; k += 1.0) { 20 | vec4 s = texture2D(adsk_results_pass1, xy + vec2(j, k) * (vec2(4096.0)/res)); 21 | if(s.x == -999.0) { 22 | // This sample has not been flooded yet 23 | continue; 24 | } 25 | float dist = alength(s.xy - xy); 26 | if(dist < bestdist) { 27 | // This seed is the closest yet 28 | bestdist = dist; 29 | bestseed = s; 30 | } 31 | } 32 | } 33 | 34 | gl_FragColor = bestseed; 35 | } 36 | -------------------------------------------------------------------------------- /Ls_Poly.03.glsl: -------------------------------------------------------------------------------- 1 | // Poly 2 | // Pass 3: jump flood out coords of closest seeds, round 2, distance 2048 3 | 4 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio, normp; 5 | uniform sampler2D adsk_results_pass2; 6 | vec2 res = vec2(adsk_result_w, adsk_result_h); 7 | 8 | float alength(vec2 v) { 9 | v.y /= adsk_result_frameratio; 10 | return pow(pow(abs(v.x), normp) + pow(abs(v.y), normp), 1.0/normp); 11 | } 12 | 13 | void main() { 14 | vec2 xy = gl_FragCoord.xy / res; 15 | 16 | vec4 bestseed = vec4(-999.0); 17 | float bestdist = 99999.0; 18 | for(float j = -1.0; j <= 1.0; j += 1.0) { 19 | for(float k = -1.0; k <= 1.0; k += 1.0) { 20 | vec4 s = texture2D(adsk_results_pass2, xy + vec2(j, k) * (vec2(2048.0)/res)); 21 | if(s.x == -999.0) { 22 | // This sample has not been flooded yet 23 | continue; 24 | } 25 | float dist = alength(s.xy - xy); 26 | if(dist < bestdist) { 27 | // This seed is the closest yet 28 | bestdist = dist; 29 | bestseed = s; 30 | } 31 | } 32 | } 33 | 34 | gl_FragColor = bestseed; 35 | } 36 | -------------------------------------------------------------------------------- /Ls_Poly.04.glsl: -------------------------------------------------------------------------------- 1 | // Poly 2 | // Pass 4: jump flood out coords of closest seeds, round 3, distance 1024 3 | 4 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio, normp; 5 | uniform sampler2D adsk_results_pass3; 6 | vec2 res = vec2(adsk_result_w, adsk_result_h); 7 | 8 | float alength(vec2 v) { 9 | v.y /= adsk_result_frameratio; 10 | return pow(pow(abs(v.x), normp) + pow(abs(v.y), normp), 1.0/normp); 11 | } 12 | 13 | void main() { 14 | vec2 xy = gl_FragCoord.xy / res; 15 | 16 | vec4 bestseed = vec4(-999.0); 17 | float bestdist = 99999.0; 18 | for(float j = -1.0; j <= 1.0; j += 1.0) { 19 | for(float k = -1.0; k <= 1.0; k += 1.0) { 20 | vec4 s = texture2D(adsk_results_pass3, xy + vec2(j, k) * (vec2(1024.0)/res)); 21 | if(s.x == -999.0) { 22 | // This sample has not been flooded yet 23 | continue; 24 | } 25 | float dist = alength(s.xy - xy); 26 | if(dist < bestdist) { 27 | // This seed is the closest yet 28 | bestdist = dist; 29 | bestseed = s; 30 | } 31 | } 32 | } 33 | 34 | gl_FragColor = bestseed; 35 | } 36 | -------------------------------------------------------------------------------- /Ls_Poly.05.glsl: -------------------------------------------------------------------------------- 1 | // Poly 2 | // Pass 5: jump flood out coords of closest seeds, round 4, distance 512 3 | 4 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio, normp; 5 | uniform sampler2D adsk_results_pass4; 6 | vec2 res = vec2(adsk_result_w, adsk_result_h); 7 | 8 | float alength(vec2 v) { 9 | v.y /= adsk_result_frameratio; 10 | return pow(pow(abs(v.x), normp) + pow(abs(v.y), normp), 1.0/normp); 11 | } 12 | 13 | void main() { 14 | vec2 xy = gl_FragCoord.xy / res; 15 | 16 | vec4 bestseed = vec4(-999.0); 17 | float bestdist = 99999.0; 18 | for(float j = -1.0; j <= 1.0; j += 1.0) { 19 | for(float k = -1.0; k <= 1.0; k += 1.0) { 20 | vec4 s = texture2D(adsk_results_pass4, xy + vec2(j, k) * (vec2(512.0)/res)); 21 | if(s.x == -999.0) { 22 | // This sample has not been flooded yet 23 | continue; 24 | } 25 | float dist = alength(s.xy - xy); 26 | if(dist < bestdist) { 27 | // This seed is the closest yet 28 | bestdist = dist; 29 | bestseed = s; 30 | } 31 | } 32 | } 33 | 34 | gl_FragColor = bestseed; 35 | } 36 | -------------------------------------------------------------------------------- /Ls_Poly.06.glsl: -------------------------------------------------------------------------------- 1 | // Poly 2 | // Pass 6: jump flood out coords of closest seeds, round 5, distance 256 3 | 4 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio, normp; 5 | uniform sampler2D adsk_results_pass5; 6 | vec2 res = vec2(adsk_result_w, adsk_result_h); 7 | 8 | float alength(vec2 v) { 9 | v.y /= adsk_result_frameratio; 10 | return pow(pow(abs(v.x), normp) + pow(abs(v.y), normp), 1.0/normp); 11 | } 12 | 13 | void main() { 14 | vec2 xy = gl_FragCoord.xy / res; 15 | 16 | vec4 bestseed = vec4(-999.0); 17 | float bestdist = 99999.0; 18 | for(float j = -1.0; j <= 1.0; j += 1.0) { 19 | for(float k = -1.0; k <= 1.0; k += 1.0) { 20 | vec4 s = texture2D(adsk_results_pass5, xy + vec2(j, k) * (vec2(256.0)/res)); 21 | if(s.x == -999.0) { 22 | // This sample has not been flooded yet 23 | continue; 24 | } 25 | float dist = alength(s.xy - xy); 26 | if(dist < bestdist) { 27 | // This seed is the closest yet 28 | bestdist = dist; 29 | bestseed = s; 30 | } 31 | } 32 | } 33 | 34 | gl_FragColor = bestseed; 35 | } 36 | -------------------------------------------------------------------------------- /Ls_Poly.07.glsl: -------------------------------------------------------------------------------- 1 | // Poly 2 | // Pass 7: jump flood out coords of closest seeds, round 6, distance 128 3 | 4 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio, normp; 5 | uniform sampler2D adsk_results_pass6; 6 | vec2 res = vec2(adsk_result_w, adsk_result_h); 7 | 8 | float alength(vec2 v) { 9 | v.y /= adsk_result_frameratio; 10 | return pow(pow(abs(v.x), normp) + pow(abs(v.y), normp), 1.0/normp); 11 | } 12 | 13 | void main() { 14 | vec2 xy = gl_FragCoord.xy / res; 15 | 16 | vec4 bestseed = vec4(-999.0); 17 | float bestdist = 99999.0; 18 | for(float j = -1.0; j <= 1.0; j += 1.0) { 19 | for(float k = -1.0; k <= 1.0; k += 1.0) { 20 | vec4 s = texture2D(adsk_results_pass6, xy + vec2(j, k) * (vec2(128.0)/res)); 21 | if(s.x == -999.0) { 22 | // This sample has not been flooded yet 23 | continue; 24 | } 25 | float dist = alength(s.xy - xy); 26 | if(dist < bestdist) { 27 | // This seed is the closest yet 28 | bestdist = dist; 29 | bestseed = s; 30 | } 31 | } 32 | } 33 | 34 | gl_FragColor = bestseed; 35 | } 36 | -------------------------------------------------------------------------------- /Ls_Poly.08.glsl: -------------------------------------------------------------------------------- 1 | // Poly 2 | // Pass 8: jump flood out coords of closest seeds, round 7, distance 64 3 | 4 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio, normp; 5 | uniform sampler2D adsk_results_pass7; 6 | vec2 res = vec2(adsk_result_w, adsk_result_h); 7 | 8 | float alength(vec2 v) { 9 | v.y /= adsk_result_frameratio; 10 | return pow(pow(abs(v.x), normp) + pow(abs(v.y), normp), 1.0/normp); 11 | } 12 | 13 | void main() { 14 | vec2 xy = gl_FragCoord.xy / res; 15 | 16 | vec4 bestseed = vec4(-999.0); 17 | float bestdist = 99999.0; 18 | for(float j = -1.0; j <= 1.0; j += 1.0) { 19 | for(float k = -1.0; k <= 1.0; k += 1.0) { 20 | vec4 s = texture2D(adsk_results_pass7, xy + vec2(j, k) * (vec2(64.0)/res)); 21 | if(s.x == -999.0) { 22 | // This sample has not been flooded yet 23 | continue; 24 | } 25 | float dist = alength(s.xy - xy); 26 | if(dist < bestdist) { 27 | // This seed is the closest yet 28 | bestdist = dist; 29 | bestseed = s; 30 | } 31 | } 32 | } 33 | 34 | gl_FragColor = bestseed; 35 | } 36 | -------------------------------------------------------------------------------- /Ls_Poly.09.glsl: -------------------------------------------------------------------------------- 1 | // Poly 2 | // Pass 9: jump flood out coords of closest seeds, round 8, distance 32 3 | 4 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio, normp; 5 | uniform sampler2D adsk_results_pass8; 6 | vec2 res = vec2(adsk_result_w, adsk_result_h); 7 | 8 | float alength(vec2 v) { 9 | v.y /= adsk_result_frameratio; 10 | return pow(pow(abs(v.x), normp) + pow(abs(v.y), normp), 1.0/normp); 11 | } 12 | 13 | void main() { 14 | vec2 xy = gl_FragCoord.xy / res; 15 | 16 | vec4 bestseed = vec4(-999.0); 17 | float bestdist = 99999.0; 18 | for(float j = -1.0; j <= 1.0; j += 1.0) { 19 | for(float k = -1.0; k <= 1.0; k += 1.0) { 20 | vec4 s = texture2D(adsk_results_pass8, xy + vec2(j, k) * (vec2(32.0)/res)); 21 | if(s.x == -999.0) { 22 | // This sample has not been flooded yet 23 | continue; 24 | } 25 | float dist = alength(s.xy - xy); 26 | if(dist < bestdist) { 27 | // This seed is the closest yet 28 | bestdist = dist; 29 | bestseed = s; 30 | } 31 | } 32 | } 33 | 34 | gl_FragColor = bestseed; 35 | } 36 | -------------------------------------------------------------------------------- /Ls_Poly.10.glsl: -------------------------------------------------------------------------------- 1 | // Poly 2 | // Pass 10: jump flood out coords of closest seeds, round 9, distance 16 3 | 4 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio, normp; 5 | uniform sampler2D adsk_results_pass9; 6 | vec2 res = vec2(adsk_result_w, adsk_result_h); 7 | 8 | float alength(vec2 v) { 9 | v.y /= adsk_result_frameratio; 10 | return pow(pow(abs(v.x), normp) + pow(abs(v.y), normp), 1.0/normp); 11 | } 12 | 13 | void main() { 14 | vec2 xy = gl_FragCoord.xy / res; 15 | 16 | vec4 bestseed = vec4(-999.0); 17 | float bestdist = 99999.0; 18 | for(float j = -1.0; j <= 1.0; j += 1.0) { 19 | for(float k = -1.0; k <= 1.0; k += 1.0) { 20 | vec4 s = texture2D(adsk_results_pass9, xy + vec2(j, k) * (vec2(16.0)/res)); 21 | if(s.x == -999.0) { 22 | // This sample has not been flooded yet 23 | continue; 24 | } 25 | float dist = alength(s.xy - xy); 26 | if(dist < bestdist) { 27 | // This seed is the closest yet 28 | bestdist = dist; 29 | bestseed = s; 30 | } 31 | } 32 | } 33 | 34 | gl_FragColor = bestseed; 35 | } 36 | -------------------------------------------------------------------------------- /Ls_Poly.11.glsl: -------------------------------------------------------------------------------- 1 | // Poly 2 | // Pass 11: jump flood out coords of closest seeds, round 10, distance 8 3 | 4 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio, normp; 5 | uniform sampler2D adsk_results_pass10; 6 | vec2 res = vec2(adsk_result_w, adsk_result_h); 7 | 8 | float alength(vec2 v) { 9 | v.y /= adsk_result_frameratio; 10 | return pow(pow(abs(v.x), normp) + pow(abs(v.y), normp), 1.0/normp); 11 | } 12 | 13 | void main() { 14 | vec2 xy = gl_FragCoord.xy / res; 15 | 16 | vec4 bestseed = vec4(-999.0); 17 | float bestdist = 99999.0; 18 | for(float j = -1.0; j <= 1.0; j += 1.0) { 19 | for(float k = -1.0; k <= 1.0; k += 1.0) { 20 | vec4 s = texture2D(adsk_results_pass10, xy + vec2(j, k) * (vec2(8.0)/res)); 21 | if(s.x == -999.0) { 22 | // This sample has not been flooded yet 23 | continue; 24 | } 25 | float dist = alength(s.xy - xy); 26 | if(dist < bestdist) { 27 | // This seed is the closest yet 28 | bestdist = dist; 29 | bestseed = s; 30 | } 31 | } 32 | } 33 | 34 | gl_FragColor = bestseed; 35 | } 36 | -------------------------------------------------------------------------------- /Ls_Poly.12.glsl: -------------------------------------------------------------------------------- 1 | // Poly 2 | // Pass 12: jump flood out coords of closest seeds, round 11, distance 4 3 | 4 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio, normp; 5 | uniform sampler2D adsk_results_pass11; 6 | vec2 res = vec2(adsk_result_w, adsk_result_h); 7 | 8 | float alength(vec2 v) { 9 | v.y /= adsk_result_frameratio; 10 | return pow(pow(abs(v.x), normp) + pow(abs(v.y), normp), 1.0/normp); 11 | } 12 | 13 | void main() { 14 | vec2 xy = gl_FragCoord.xy / res; 15 | 16 | vec4 bestseed = vec4(-999.0); 17 | float bestdist = 99999.0; 18 | for(float j = -1.0; j <= 1.0; j += 1.0) { 19 | for(float k = -1.0; k <= 1.0; k += 1.0) { 20 | vec4 s = texture2D(adsk_results_pass11, xy + vec2(j, k) * (vec2(4.0)/res)); 21 | if(s.x == -999.0) { 22 | // This sample has not been flooded yet 23 | continue; 24 | } 25 | float dist = alength(s.xy - xy); 26 | if(dist < bestdist) { 27 | // This seed is the closest yet 28 | bestdist = dist; 29 | bestseed = s; 30 | } 31 | } 32 | } 33 | 34 | gl_FragColor = bestseed; 35 | } 36 | -------------------------------------------------------------------------------- /Ls_Poly.13.glsl: -------------------------------------------------------------------------------- 1 | // Poly 2 | // Pass 13: jump flood out coords of closest seeds, round 12, distance 2 3 | 4 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio, normp; 5 | uniform sampler2D adsk_results_pass12; 6 | vec2 res = vec2(adsk_result_w, adsk_result_h); 7 | 8 | float alength(vec2 v) { 9 | v.y /= adsk_result_frameratio; 10 | return pow(pow(abs(v.x), normp) + pow(abs(v.y), normp), 1.0/normp); 11 | } 12 | 13 | void main() { 14 | vec2 xy = gl_FragCoord.xy / res; 15 | 16 | vec4 bestseed = vec4(-999.0); 17 | float bestdist = 99999.0; 18 | for(float j = -1.0; j <= 1.0; j += 1.0) { 19 | for(float k = -1.0; k <= 1.0; k += 1.0) { 20 | vec4 s = texture2D(adsk_results_pass12, xy + vec2(j, k) * (vec2(2.0)/res)); 21 | if(s.x == -999.0) { 22 | // This sample has not been flooded yet 23 | continue; 24 | } 25 | float dist = alength(s.xy - xy); 26 | if(dist < bestdist) { 27 | // This seed is the closest yet 28 | bestdist = dist; 29 | bestseed = s; 30 | } 31 | } 32 | } 33 | 34 | gl_FragColor = bestseed; 35 | } 36 | -------------------------------------------------------------------------------- /Ls_Poly.14.glsl: -------------------------------------------------------------------------------- 1 | // Poly 2 | // Pass 14: jump flood out coords of closest seeds, round 13, distance 1 3 | 4 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio, normp; 5 | uniform sampler2D adsk_results_pass13; 6 | vec2 res = vec2(adsk_result_w, adsk_result_h); 7 | 8 | float alength(vec2 v) { 9 | v.y /= adsk_result_frameratio; 10 | return pow(pow(abs(v.x), normp) + pow(abs(v.y), normp), 1.0/normp); 11 | } 12 | 13 | void main() { 14 | vec2 xy = gl_FragCoord.xy / res; 15 | 16 | vec4 bestseed = vec4(-999.0); 17 | float bestdist = 99999.0; 18 | for(float j = -1.0; j <= 1.0; j += 1.0) { 19 | for(float k = -1.0; k <= 1.0; k += 1.0) { 20 | vec4 s = texture2D(adsk_results_pass13, xy + vec2(j, k) * (vec2(1.0)/res)); 21 | if(s.x == -999.0) { 22 | // This sample has not been flooded yet 23 | continue; 24 | } 25 | float dist = alength(s.xy - xy); 26 | if(dist < bestdist) { 27 | // This seed is the closest yet 28 | bestdist = dist; 29 | bestseed = s; 30 | } 31 | } 32 | } 33 | 34 | gl_FragColor = bestseed; 35 | } 36 | -------------------------------------------------------------------------------- /Ls_Poly.22.glsl: -------------------------------------------------------------------------------- 1 | // Poly 2 | // Pass 22: jump flood out addresses of closest seeds, round 7, distance 64 3 | // We check if the surrounding pixels tell us about triangles that are closer than our own 4 | 5 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio; 6 | uniform sampler2D adsk_results_pass21; 7 | vec2 res = vec2(adsk_result_w, adsk_result_h); 8 | 9 | vec2 address2coords(float a) { 10 | vec2 c; 11 | c.y = floor(a / (adsk_result_w+50.0)); 12 | c.x = a - (c.y * (adsk_result_w+50.0)); 13 | return (c + vec2(0.5)) / res; 14 | } 15 | 16 | // Signed distance to a triangle 17 | float sdTriangle(vec2 p0, vec2 p1, vec2 p2, vec2 p) { 18 | // The MIT License 19 | // Copyright © 2014 Inigo Quilez 20 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | vec2 e0 = p1 - p0; 22 | vec2 e1 = p2 - p1; 23 | vec2 e2 = p0 - p2; 24 | 25 | vec2 v0 = p - p0; 26 | vec2 v1 = p - p1; 27 | vec2 v2 = p - p2; 28 | 29 | vec2 pq0 = v0 - e0*clamp(dot(v0,e0)/dot(e0,e0), 0.0, 1.0); 30 | vec2 pq1 = v1 - e1*clamp(dot(v1,e1)/dot(e1,e1), 0.0, 1.0); 31 | vec2 pq2 = v2 - e2*clamp(dot(v2,e2)/dot(e2,e2), 0.0, 1.0); 32 | 33 | vec2 d = min(min(vec2(dot(pq0, pq0), v0.x*e0.y-v0.y*e0.x), vec2(dot(pq1, pq1), v1.x*e1.y-v1.y*e1.x)), vec2(dot(pq2, pq2), v2.x*e2.y-v2.y*e2.x)); 34 | 35 | return -sqrt(d.x)*sign(d.y); 36 | } 37 | 38 | void main() { 39 | vec2 xy = gl_FragCoord.xy / res; 40 | 41 | vec4 bestseeds = vec4(-999.0); 42 | float bestdist = 99999.0; 43 | 44 | for(float j = -1.0; j <= 1.0; j += 1.0) { 45 | for(float k = -1.0; k <= 1.0; k += 1.0) { 46 | vec4 seeds = texture2D(adsk_results_pass21, xy + vec2(j, k) * (vec2(64.0)/res)); 47 | if(seeds.r < 0.0) { 48 | // This point doesn't know about any seeds yet 49 | continue; 50 | } 51 | float dist = sdTriangle(address2coords(seeds.r), address2coords(seeds.g), address2coords(seeds.b), xy); 52 | if(dist < bestdist) { 53 | bestseeds.rgba = seeds.rgba; 54 | bestdist = dist; 55 | } 56 | if(seeds.a >= 0.0) { 57 | // This point knows about 4 seeds, so there's another tri to check 58 | dist = sdTriangle(address2coords(seeds.r), address2coords(seeds.b), address2coords(seeds.a), xy); 59 | if(dist < bestdist) { 60 | bestseeds.rgba = seeds.barg; // This tri is flooded out in RGB, the other in RBA 61 | bestdist = dist; 62 | } 63 | } 64 | } 65 | } 66 | 67 | gl_FragColor = bestseeds; 68 | } 69 | -------------------------------------------------------------------------------- /Ls_Poly.23.glsl: -------------------------------------------------------------------------------- 1 | // Poly 2 | // Pass 23: jump flood out addresses of closest seeds, round 8, distance 32 3 | // We check if the surrounding pixels tell us about triangles that are closer than our own 4 | 5 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio; 6 | uniform sampler2D adsk_results_pass22; 7 | vec2 res = vec2(adsk_result_w, adsk_result_h); 8 | 9 | vec2 address2coords(float a) { 10 | vec2 c; 11 | c.y = floor(a / (adsk_result_w+50.0)); 12 | c.x = a - (c.y * (adsk_result_w+50.0)); 13 | return (c + vec2(0.5)) / res; 14 | } 15 | 16 | // Signed distance to a triangle 17 | float sdTriangle(vec2 p0, vec2 p1, vec2 p2, vec2 p) { 18 | // The MIT License 19 | // Copyright © 2014 Inigo Quilez 20 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | vec2 e0 = p1 - p0; 22 | vec2 e1 = p2 - p1; 23 | vec2 e2 = p0 - p2; 24 | 25 | vec2 v0 = p - p0; 26 | vec2 v1 = p - p1; 27 | vec2 v2 = p - p2; 28 | 29 | vec2 pq0 = v0 - e0*clamp(dot(v0,e0)/dot(e0,e0), 0.0, 1.0); 30 | vec2 pq1 = v1 - e1*clamp(dot(v1,e1)/dot(e1,e1), 0.0, 1.0); 31 | vec2 pq2 = v2 - e2*clamp(dot(v2,e2)/dot(e2,e2), 0.0, 1.0); 32 | 33 | vec2 d = min(min(vec2(dot(pq0, pq0), v0.x*e0.y-v0.y*e0.x), vec2(dot(pq1, pq1), v1.x*e1.y-v1.y*e1.x)), vec2(dot(pq2, pq2), v2.x*e2.y-v2.y*e2.x)); 34 | 35 | return -sqrt(d.x)*sign(d.y); 36 | } 37 | 38 | void main() { 39 | vec2 xy = gl_FragCoord.xy / res; 40 | 41 | vec4 bestseeds = vec4(-999.0); 42 | float bestdist = 99999.0; 43 | 44 | for(float j = -1.0; j <= 1.0; j += 1.0) { 45 | for(float k = -1.0; k <= 1.0; k += 1.0) { 46 | vec4 seeds = texture2D(adsk_results_pass22, xy + vec2(j, k) * (vec2(32.0)/res)); 47 | if(seeds.r < 0.0) { 48 | // This point doesn't know about any seeds yet 49 | continue; 50 | } 51 | float dist = sdTriangle(address2coords(seeds.r), address2coords(seeds.g), address2coords(seeds.b), xy); 52 | if(dist < bestdist) { 53 | bestseeds.rgba = seeds.rgba; 54 | bestdist = dist; 55 | } 56 | if(seeds.a >= 0.0) { 57 | // This point knows about 4 seeds, so there's another tri to check 58 | dist = sdTriangle(address2coords(seeds.r), address2coords(seeds.b), address2coords(seeds.a), xy); 59 | if(dist < bestdist) { 60 | bestseeds.rgba = seeds.barg; // This tri is flooded out in RGB, the other in RBA 61 | bestdist = dist; 62 | } 63 | } 64 | } 65 | } 66 | 67 | gl_FragColor = bestseeds; 68 | } 69 | -------------------------------------------------------------------------------- /Ls_Poly.24.glsl: -------------------------------------------------------------------------------- 1 | // Poly 2 | // Pass 24: jump flood out addresses of closest seeds, round 9, distance 16 3 | // We check if the surrounding pixels tell us about triangles that are closer than our own 4 | 5 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio; 6 | uniform sampler2D adsk_results_pass23; 7 | vec2 res = vec2(adsk_result_w, adsk_result_h); 8 | 9 | vec2 address2coords(float a) { 10 | vec2 c; 11 | c.y = floor(a / (adsk_result_w+50.0)); 12 | c.x = a - (c.y * (adsk_result_w+50.0)); 13 | return (c + vec2(0.5)) / res; 14 | } 15 | 16 | // Signed distance to a triangle 17 | float sdTriangle(vec2 p0, vec2 p1, vec2 p2, vec2 p) { 18 | // The MIT License 19 | // Copyright © 2014 Inigo Quilez 20 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | vec2 e0 = p1 - p0; 22 | vec2 e1 = p2 - p1; 23 | vec2 e2 = p0 - p2; 24 | 25 | vec2 v0 = p - p0; 26 | vec2 v1 = p - p1; 27 | vec2 v2 = p - p2; 28 | 29 | vec2 pq0 = v0 - e0*clamp(dot(v0,e0)/dot(e0,e0), 0.0, 1.0); 30 | vec2 pq1 = v1 - e1*clamp(dot(v1,e1)/dot(e1,e1), 0.0, 1.0); 31 | vec2 pq2 = v2 - e2*clamp(dot(v2,e2)/dot(e2,e2), 0.0, 1.0); 32 | 33 | vec2 d = min(min(vec2(dot(pq0, pq0), v0.x*e0.y-v0.y*e0.x), vec2(dot(pq1, pq1), v1.x*e1.y-v1.y*e1.x)), vec2(dot(pq2, pq2), v2.x*e2.y-v2.y*e2.x)); 34 | 35 | return -sqrt(d.x)*sign(d.y); 36 | } 37 | 38 | void main() { 39 | vec2 xy = gl_FragCoord.xy / res; 40 | 41 | vec4 bestseeds = vec4(-999.0); 42 | float bestdist = 99999.0; 43 | 44 | for(float j = -1.0; j <= 1.0; j += 1.0) { 45 | for(float k = -1.0; k <= 1.0; k += 1.0) { 46 | vec4 seeds = texture2D(adsk_results_pass23, xy + vec2(j, k) * (vec2(16.0)/res)); 47 | if(seeds.r < 0.0) { 48 | // This point doesn't know about any seeds yet 49 | continue; 50 | } 51 | float dist = sdTriangle(address2coords(seeds.r), address2coords(seeds.g), address2coords(seeds.b), xy); 52 | if(dist < bestdist) { 53 | bestseeds.rgba = seeds.rgba; 54 | bestdist = dist; 55 | } 56 | if(seeds.a >= 0.0) { 57 | // This point knows about 4 seeds, so there's another tri to check 58 | dist = sdTriangle(address2coords(seeds.r), address2coords(seeds.b), address2coords(seeds.a), xy); 59 | if(dist < bestdist) { 60 | bestseeds.rgba = seeds.barg; // This tri is flooded out in RGB, the other in RBA 61 | bestdist = dist; 62 | } 63 | } 64 | } 65 | } 66 | 67 | gl_FragColor = bestseeds; 68 | } 69 | -------------------------------------------------------------------------------- /Ls_Poly.25.glsl: -------------------------------------------------------------------------------- 1 | // Poly 2 | // Pass 25: jump flood out addresses of closest seeds, round 10, distance 8 3 | // We check if the surrounding pixels tell us about triangles that are closer than our own 4 | 5 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio; 6 | uniform sampler2D adsk_results_pass24; 7 | vec2 res = vec2(adsk_result_w, adsk_result_h); 8 | 9 | vec2 address2coords(float a) { 10 | vec2 c; 11 | c.y = floor(a / (adsk_result_w+50.0)); 12 | c.x = a - (c.y * (adsk_result_w+50.0)); 13 | return (c + vec2(0.5)) / res; 14 | } 15 | 16 | // Signed distance to a triangle 17 | float sdTriangle(vec2 p0, vec2 p1, vec2 p2, vec2 p) { 18 | // The MIT License 19 | // Copyright © 2014 Inigo Quilez 20 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | vec2 e0 = p1 - p0; 22 | vec2 e1 = p2 - p1; 23 | vec2 e2 = p0 - p2; 24 | 25 | vec2 v0 = p - p0; 26 | vec2 v1 = p - p1; 27 | vec2 v2 = p - p2; 28 | 29 | vec2 pq0 = v0 - e0*clamp(dot(v0,e0)/dot(e0,e0), 0.0, 1.0); 30 | vec2 pq1 = v1 - e1*clamp(dot(v1,e1)/dot(e1,e1), 0.0, 1.0); 31 | vec2 pq2 = v2 - e2*clamp(dot(v2,e2)/dot(e2,e2), 0.0, 1.0); 32 | 33 | vec2 d = min(min(vec2(dot(pq0, pq0), v0.x*e0.y-v0.y*e0.x), vec2(dot(pq1, pq1), v1.x*e1.y-v1.y*e1.x)), vec2(dot(pq2, pq2), v2.x*e2.y-v2.y*e2.x)); 34 | 35 | return -sqrt(d.x)*sign(d.y); 36 | } 37 | 38 | void main() { 39 | vec2 xy = gl_FragCoord.xy / res; 40 | 41 | vec4 bestseeds = vec4(-999.0); 42 | float bestdist = 99999.0; 43 | 44 | for(float j = -1.0; j <= 1.0; j += 1.0) { 45 | for(float k = -1.0; k <= 1.0; k += 1.0) { 46 | vec4 seeds = texture2D(adsk_results_pass24, xy + vec2(j, k) * (vec2(8.0)/res)); 47 | if(seeds.r < 0.0) { 48 | // This point doesn't know about any seeds yet 49 | continue; 50 | } 51 | float dist = sdTriangle(address2coords(seeds.r), address2coords(seeds.g), address2coords(seeds.b), xy); 52 | if(dist < bestdist) { 53 | bestseeds.rgba = seeds.rgba; 54 | bestdist = dist; 55 | } 56 | if(seeds.a >= 0.0) { 57 | // This point knows about 4 seeds, so there's another tri to check 58 | dist = sdTriangle(address2coords(seeds.r), address2coords(seeds.b), address2coords(seeds.a), xy); 59 | if(dist < bestdist) { 60 | bestseeds.rgba = seeds.barg; // This tri is flooded out in RGB, the other in RBA 61 | bestdist = dist; 62 | } 63 | } 64 | } 65 | } 66 | 67 | gl_FragColor = bestseeds; 68 | } 69 | -------------------------------------------------------------------------------- /Ls_Poly.26.glsl: -------------------------------------------------------------------------------- 1 | // Poly 2 | // Pass 26: jump flood out addresses of closest seeds, round 11, distance 4 3 | // We check if the surrounding pixels tell us about triangles that are closer than our own 4 | 5 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio; 6 | uniform sampler2D adsk_results_pass25; 7 | vec2 res = vec2(adsk_result_w, adsk_result_h); 8 | 9 | vec2 address2coords(float a) { 10 | vec2 c; 11 | c.y = floor(a / (adsk_result_w+50.0)); 12 | c.x = a - (c.y * (adsk_result_w+50.0)); 13 | return (c + vec2(0.5)) / res; 14 | } 15 | 16 | // Signed distance to a triangle 17 | float sdTriangle(vec2 p0, vec2 p1, vec2 p2, vec2 p) { 18 | // The MIT License 19 | // Copyright © 2014 Inigo Quilez 20 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | vec2 e0 = p1 - p0; 22 | vec2 e1 = p2 - p1; 23 | vec2 e2 = p0 - p2; 24 | 25 | vec2 v0 = p - p0; 26 | vec2 v1 = p - p1; 27 | vec2 v2 = p - p2; 28 | 29 | vec2 pq0 = v0 - e0*clamp(dot(v0,e0)/dot(e0,e0), 0.0, 1.0); 30 | vec2 pq1 = v1 - e1*clamp(dot(v1,e1)/dot(e1,e1), 0.0, 1.0); 31 | vec2 pq2 = v2 - e2*clamp(dot(v2,e2)/dot(e2,e2), 0.0, 1.0); 32 | 33 | vec2 d = min(min(vec2(dot(pq0, pq0), v0.x*e0.y-v0.y*e0.x), vec2(dot(pq1, pq1), v1.x*e1.y-v1.y*e1.x)), vec2(dot(pq2, pq2), v2.x*e2.y-v2.y*e2.x)); 34 | 35 | return -sqrt(d.x)*sign(d.y); 36 | } 37 | 38 | void main() { 39 | vec2 xy = gl_FragCoord.xy / res; 40 | 41 | vec4 bestseeds = vec4(-999.0); 42 | float bestdist = 99999.0; 43 | 44 | for(float j = -1.0; j <= 1.0; j += 1.0) { 45 | for(float k = -1.0; k <= 1.0; k += 1.0) { 46 | vec4 seeds = texture2D(adsk_results_pass25, xy + vec2(j, k) * (vec2(4.0)/res)); 47 | if(seeds.r < 0.0) { 48 | // This point doesn't know about any seeds yet 49 | continue; 50 | } 51 | float dist = sdTriangle(address2coords(seeds.r), address2coords(seeds.g), address2coords(seeds.b), xy); 52 | if(dist < bestdist) { 53 | bestseeds.rgba = seeds.rgba; 54 | bestdist = dist; 55 | } 56 | if(seeds.a >= 0.0) { 57 | // This point knows about 4 seeds, so there's another tri to check 58 | dist = sdTriangle(address2coords(seeds.r), address2coords(seeds.b), address2coords(seeds.a), xy); 59 | if(dist < bestdist) { 60 | bestseeds.rgba = seeds.barg; // This tri is flooded out in RGB, the other in RBA 61 | bestdist = dist; 62 | } 63 | } 64 | } 65 | } 66 | 67 | gl_FragColor = bestseeds; 68 | } 69 | -------------------------------------------------------------------------------- /Ls_Poly.27.glsl: -------------------------------------------------------------------------------- 1 | // Poly 2 | // Pass 27: jump flood out addresses of closest seeds, round 12, distance 2 3 | // We check if the surrounding pixels tell us about triangles that are closer than our own 4 | 5 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio; 6 | uniform sampler2D adsk_results_pass26; 7 | vec2 res = vec2(adsk_result_w, adsk_result_h); 8 | 9 | vec2 address2coords(float a) { 10 | vec2 c; 11 | c.y = floor(a / (adsk_result_w+50.0)); 12 | c.x = a - (c.y * (adsk_result_w+50.0)); 13 | return (c + vec2(0.5)) / res; 14 | } 15 | 16 | // Signed distance to a triangle 17 | float sdTriangle(vec2 p0, vec2 p1, vec2 p2, vec2 p) { 18 | // The MIT License 19 | // Copyright © 2014 Inigo Quilez 20 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | vec2 e0 = p1 - p0; 22 | vec2 e1 = p2 - p1; 23 | vec2 e2 = p0 - p2; 24 | 25 | vec2 v0 = p - p0; 26 | vec2 v1 = p - p1; 27 | vec2 v2 = p - p2; 28 | 29 | vec2 pq0 = v0 - e0*clamp(dot(v0,e0)/dot(e0,e0), 0.0, 1.0); 30 | vec2 pq1 = v1 - e1*clamp(dot(v1,e1)/dot(e1,e1), 0.0, 1.0); 31 | vec2 pq2 = v2 - e2*clamp(dot(v2,e2)/dot(e2,e2), 0.0, 1.0); 32 | 33 | vec2 d = min(min(vec2(dot(pq0, pq0), v0.x*e0.y-v0.y*e0.x), vec2(dot(pq1, pq1), v1.x*e1.y-v1.y*e1.x)), vec2(dot(pq2, pq2), v2.x*e2.y-v2.y*e2.x)); 34 | 35 | return -sqrt(d.x)*sign(d.y); 36 | } 37 | 38 | void main() { 39 | vec2 xy = gl_FragCoord.xy / res; 40 | 41 | vec4 bestseeds = vec4(-999.0); 42 | float bestdist = 99999.0; 43 | 44 | for(float j = -1.0; j <= 1.0; j += 1.0) { 45 | for(float k = -1.0; k <= 1.0; k += 1.0) { 46 | vec4 seeds = texture2D(adsk_results_pass26, xy + vec2(j, k) * (vec2(2.0)/res)); 47 | if(seeds.r < 0.0) { 48 | // This point doesn't know about any seeds yet 49 | continue; 50 | } 51 | float dist = sdTriangle(address2coords(seeds.r), address2coords(seeds.g), address2coords(seeds.b), xy); 52 | if(dist < bestdist) { 53 | bestseeds.rgba = seeds.rgba; 54 | bestdist = dist; 55 | } 56 | if(seeds.a >= 0.0) { 57 | // This point knows about 4 seeds, so there's another tri to check 58 | dist = sdTriangle(address2coords(seeds.r), address2coords(seeds.b), address2coords(seeds.a), xy); 59 | if(dist < bestdist) { 60 | bestseeds.rgba = seeds.barg; // This tri is flooded out in RGB, the other in RBA 61 | bestdist = dist; 62 | } 63 | } 64 | } 65 | } 66 | 67 | gl_FragColor = bestseeds; 68 | } 69 | -------------------------------------------------------------------------------- /Ls_Poly.28.glsl: -------------------------------------------------------------------------------- 1 | // Poly 2 | // Pass 28: jump flood out addresses of closest seeds, round 13, distance 1 3 | // We check if the surrounding pixels tell us about triangles that are closer than our own 4 | 5 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio; 6 | uniform sampler2D adsk_results_pass27; 7 | vec2 res = vec2(adsk_result_w, adsk_result_h); 8 | 9 | vec2 address2coords(float a) { 10 | vec2 c; 11 | c.y = floor(a / (adsk_result_w+50.0)); 12 | c.x = a - (c.y * (adsk_result_w+50.0)); 13 | return (c + vec2(0.5)) / res; 14 | } 15 | 16 | // Signed distance to a triangle 17 | float sdTriangle(vec2 p0, vec2 p1, vec2 p2, vec2 p) { 18 | // The MIT License 19 | // Copyright © 2014 Inigo Quilez 20 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | vec2 e0 = p1 - p0; 22 | vec2 e1 = p2 - p1; 23 | vec2 e2 = p0 - p2; 24 | 25 | vec2 v0 = p - p0; 26 | vec2 v1 = p - p1; 27 | vec2 v2 = p - p2; 28 | 29 | vec2 pq0 = v0 - e0*clamp(dot(v0,e0)/dot(e0,e0), 0.0, 1.0); 30 | vec2 pq1 = v1 - e1*clamp(dot(v1,e1)/dot(e1,e1), 0.0, 1.0); 31 | vec2 pq2 = v2 - e2*clamp(dot(v2,e2)/dot(e2,e2), 0.0, 1.0); 32 | 33 | vec2 d = min(min(vec2(dot(pq0, pq0), v0.x*e0.y-v0.y*e0.x), vec2(dot(pq1, pq1), v1.x*e1.y-v1.y*e1.x)), vec2(dot(pq2, pq2), v2.x*e2.y-v2.y*e2.x)); 34 | 35 | return -sqrt(d.x)*sign(d.y); 36 | } 37 | 38 | void main() { 39 | vec2 xy = gl_FragCoord.xy / res; 40 | 41 | vec4 bestseeds = vec4(-999.0); 42 | float bestdist = 99999.0; 43 | 44 | for(float j = -1.0; j <= 1.0; j += 1.0) { 45 | for(float k = -1.0; k <= 1.0; k += 1.0) { 46 | vec4 seeds = texture2D(adsk_results_pass27, xy + vec2(j, k) * (vec2(1.0)/res)); 47 | if(seeds.r < 0.0) { 48 | // This point doesn't know about any seeds yet 49 | continue; 50 | } 51 | float dist = sdTriangle(address2coords(seeds.r), address2coords(seeds.g), address2coords(seeds.b), xy); 52 | if(dist < bestdist) { 53 | bestseeds.rgba = seeds.rgba; 54 | bestdist = dist; 55 | } 56 | if(seeds.a >= 0.0) { 57 | // This point knows about 4 seeds, so there's another tri to check 58 | dist = sdTriangle(address2coords(seeds.r), address2coords(seeds.b), address2coords(seeds.a), xy); 59 | if(dist < bestdist) { 60 | bestseeds.rgba = seeds.barg; // This tri is flooded out in RGB, the other in RBA 61 | bestdist = dist; 62 | } 63 | } 64 | } 65 | } 66 | 67 | gl_FragColor = bestseeds; 68 | } 69 | -------------------------------------------------------------------------------- /Ls_Poly_builder.py: -------------------------------------------------------------------------------- 1 | # Python script which builds the repeated passes for Ls_Poly 2 | 3 | # This writes out the first set of flooding passes from a template 4 | template = open('Ls_Poly.02.glsl').readlines() 5 | 6 | for p in range(3, 15): 7 | r = p - 1 8 | d = pow(2, 13-r) 9 | f = 'Ls_Poly.%02d.glsl' % p 10 | print f 11 | t = list(template) 12 | 13 | t[1] = "// Pass %d: jump flood out coords of closest seeds, round %d, distance %d\n" % (p, r, d) 14 | t[4] = "uniform sampler2D adsk_results_pass%d;\n" % (p - 1) 15 | t[19] = " vec4 s = texture2D(adsk_results_pass%d, xy + vec2(j, k) * (vec2(%d.0)/res));\n" % (p - 1, d) 16 | print t[1] + t[4] + t[19] 17 | 18 | open(f, 'w').write('' .join(t)) 19 | 20 | 21 | # The second set of flooding passes 22 | template = open('Ls_Poly.16.glsl').readlines() 23 | 24 | for p in range(17, 29): 25 | r = p - 15 26 | d = pow(2, 13-r) 27 | f = 'Ls_Poly.%d.glsl' % p 28 | print f 29 | t = list(template) 30 | 31 | t[1] = "// Pass %d: jump flood out addresses of closest seeds, round %d, distance %d\n" % (p, r, d) 32 | t[5] = "uniform sampler2D adsk_results_pass%d;\n" % (p - 1) 33 | t[45] = " vec4 seeds = texture2D(adsk_results_pass%d, xy + vec2(j, k) * (vec2(%d.0)/res));\n" % (p - 1, d) 34 | print t[1] + t[5] + t[45] 35 | 36 | open(f, 'w').write('' .join(t)) 37 | -------------------------------------------------------------------------------- /Ls_Posmatte.glsl: -------------------------------------------------------------------------------- 1 | // Pick an ellipsoidal area matte from an XYZ position pass 2 | // lewis@lewissaunders.com 3 | // TODO: 4 | // o Rotation 5 | // o Skew 6 | // o Cube-shaped matte - with rounded corners? 7 | 8 | uniform float adsk_result_w, adsk_result_h; 9 | uniform vec3 pick, overlaycol; 10 | uniform float tolerance, softness, falloffswoop, offsetx, offsety, offsetz, scalex, scaley, scalez; 11 | uniform bool overlay, hatch; 12 | uniform sampler2D front, matte, pos; 13 | 14 | void main() { 15 | vec2 coords = gl_FragCoord.xy / vec2(adsk_result_w, adsk_result_h); 16 | vec3 o, frontpix, pospix, mattepix, centered, diff = vec3(0.0); 17 | float m = 0.0; 18 | 19 | frontpix = texture2D(front, coords).rgb; 20 | mattepix = texture2D(matte, coords).rgb; 21 | pospix = texture2D(pos, coords).rgb; 22 | 23 | // Center coordinate space about the picked colour so we can scale easily 24 | centered = pospix - pick - vec3(offsetx, offsety, offsetz); 25 | diff = centered / vec3(scalex, scaley, scalez); 26 | 27 | m = length(diff); 28 | if(m < tolerance) { 29 | m = 0.0; 30 | } else { 31 | m = (m - tolerance) / softness; 32 | } 33 | m = clamp(1.0 - m, 0.0, 1.0); 34 | m = mix(m, smoothstep(0.0, 1.0, m), falloffswoop); 35 | m *= mattepix.b; 36 | 37 | o = frontpix; 38 | if(overlay) { 39 | o += m * overlaycol; 40 | if(hatch) { 41 | // Cheap-ass diagonal lines 42 | float h = mod(gl_FragCoord.x - gl_FragCoord.y, 20.0); 43 | h = h > 10.0 ? 0.0 : 1.0; 44 | o = mix(o, frontpix, h); 45 | } 46 | } 47 | 48 | gl_FragColor = vec4(o, m); 49 | } 50 | -------------------------------------------------------------------------------- /Ls_Posmatte.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Posmatte.glsl.p -------------------------------------------------------------------------------- /Ls_Relax.glsl: -------------------------------------------------------------------------------- 1 | // Relaxxxx 2 | // This actually is mostly just mixing incoming pixels with 3 | // the target colours, which is equivalent to a pivoted contrast 4 | // sort of operator. I really miss ContrastRGB from Shake, basically 5 | // lewis@lewissaunders.com 6 | 7 | uniform float adsk_result_w, adsk_result_h; 8 | uniform vec3 mastercolour, shadowcolour, midtonecolour, highlightcolour; 9 | uniform float mastercontrast, shadowtweak, midtonetweak, highlighttweak; 10 | uniform float shadowrestore, highlightrestore; 11 | uniform float midtonesat, mixx; 12 | uniform bool showranges; 13 | uniform sampler2D front, matte; 14 | 15 | float adsk_getLuminance(vec3 rgb); 16 | float adsk_highlights(float lum, float mid); 17 | float adsk_shadows(float lum, float mid); 18 | 19 | void main() { 20 | vec2 uv = gl_FragCoord.xy / vec2(adsk_result_w, adsk_result_h); 21 | vec3 f = texture2D(front, uv).rgb; 22 | float m = texture2D(matte, uv).b; 23 | 24 | vec3 mastermisted = mix(f, mastercolour, 1.0 - mastercontrast); 25 | 26 | float fluma = adsk_getLuminance(f); 27 | float shadowness = adsk_shadows(fluma, mix(midtonesat, 0.0, 0.5)); 28 | float highlightness = adsk_highlights(fluma, mix(midtonesat, 1.0, 0.5)); 29 | float midtoneness = 1.0 - (shadowness + highlightness); 30 | 31 | vec3 shadowrestored = mix(mastermisted, f, shadowrestore * shadowness); 32 | vec3 restored = mix(shadowrestored, f, highlightrestore * highlightness); 33 | 34 | vec3 shadowtweaked = mix(restored, shadowcolour, shadowtweak); 35 | vec3 midtonetweaked = mix(restored, midtonecolour, midtonetweak); 36 | vec3 highlighttweaked = mix(restored, highlightcolour, highlighttweak); 37 | 38 | vec3 alltonestweaked = shadowness * shadowtweaked + midtoneness * midtonetweaked + highlightness * highlighttweaked; 39 | 40 | vec3 matted = mix(f, alltonestweaked, m * mixx); 41 | 42 | if(showranges) { 43 | matted = vec3(shadowness, midtoneness, highlightness); 44 | } 45 | 46 | gl_FragColor = vec4(matted, m); 47 | } 48 | -------------------------------------------------------------------------------- /Ls_Relax.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Relax.glsl.p -------------------------------------------------------------------------------- /Ls_RndmGrade.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_RndmGrade.glsl.p -------------------------------------------------------------------------------- /Ls_Shadowplate.1.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Shadowplate.1.glsl.p -------------------------------------------------------------------------------- /Ls_Shadowplate.2.glsl: -------------------------------------------------------------------------------- 1 | #version 120 2 | 3 | // Pass 2: blur horizontally 4 | 5 | uniform sampler2D adsk_results_pass1; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform vec2 blursize; 8 | const float pi = 3.141592653589793238462643383279502884197969; 9 | 10 | void main() { 11 | vec2 xy = gl_FragCoord.xy; 12 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 13 | 14 | float sigma = blursize.x; 15 | int support = int(sigma * 3.0); 16 | 17 | // Incremental coefficient calculation setup as per GPU Gems 3 18 | vec3 g; 19 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 20 | g.y = exp(-0.5 / (sigma * sigma)); 21 | g.z = g.y * g.y; 22 | 23 | if(sigma == 0.0) { 24 | g.x = 1.0; 25 | } 26 | 27 | // Centre sample 28 | vec4 a = g.x * texture2D(adsk_results_pass1, xy * px); 29 | float energy = g.x; 30 | g.xy *= g.yz; 31 | 32 | // The rest 33 | for(int i = 1; i <= support; i++) { 34 | a += g.x * texture2D(adsk_results_pass1, (xy - vec2(float(i), 0.0)) * px); 35 | a += g.x * texture2D(adsk_results_pass1, (xy + vec2(float(i), 0.0)) * px); 36 | energy += 2.0 * g.x; 37 | g.xy *= g.yz; 38 | } 39 | a /= energy; 40 | 41 | gl_FragColor = a; 42 | } 43 | -------------------------------------------------------------------------------- /Ls_Shadowplate.3.glsl: -------------------------------------------------------------------------------- 1 | #version 120 2 | 3 | // Pass 3: blur vertically 4 | 5 | uniform sampler2D adsk_results_pass2; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform vec2 blursize; 8 | const float pi = 3.141592653589793238462643383279502884197969; 9 | 10 | void main() { 11 | vec2 xy = gl_FragCoord.xy; 12 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 13 | 14 | float sigma = blursize.y; 15 | int support = int(sigma * 3.0); 16 | 17 | // Incremental coefficient calculation setup as per GPU Gems 3 18 | vec3 g; 19 | g.x = 1.0 / (sqrt(2.0 * pi) * sigma); 20 | g.y = exp(-0.5 / (sigma * sigma)); 21 | g.z = g.y * g.y; 22 | 23 | if(sigma == 0.0) { 24 | g.x = 1.0; 25 | } 26 | 27 | // Centre sample 28 | vec4 a = g.x * texture2D(adsk_results_pass2, xy * px); 29 | float energy = g.x; 30 | g.xy *= g.yz; 31 | 32 | // The rest 33 | for(int i = 1; i <= support; i++) { 34 | a += g.x * texture2D(adsk_results_pass2, (xy - vec2(0.0, float(i))) * px); 35 | a += g.x * texture2D(adsk_results_pass2, (xy + vec2(0.0, float(i))) * px); 36 | energy += 2.0 * g.x; 37 | g.xy *= g.yz; 38 | } 39 | a /= energy; 40 | 41 | gl_FragColor = a; 42 | } 43 | -------------------------------------------------------------------------------- /Ls_Splineblur.1.glsl: -------------------------------------------------------------------------------- 1 | // Directional blur driven by gradient vectors of front input 2 | // Pass 1: make the vectors 3 | // lewis@lewissaunders.com 4 | // TODO: 5 | // o Bigger Sobel kernels? 6 | // o Pre-blur input in case of GMask kinks? 7 | // o Could probably use dfdx,dfdy instead of manual convolution 8 | 9 | uniform sampler2D map; 10 | uniform float adsk_result_w, adsk_result_h, ksize; 11 | uniform bool radial, directvectors; 12 | 13 | void main() { 14 | vec2 xy = gl_FragCoord.xy; 15 | 16 | // Factor to convert [0,1] texture coords to pixels 17 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 18 | 19 | vec2 d = vec2(0.0); 20 | 21 | if(directvectors) { 22 | // Map input is already vectors, yay! 23 | d = texture2D(map, xy * px).xy; 24 | gl_FragColor = vec4(d.x, d.y, 0.0, 1.0); 25 | return; 26 | } 27 | 28 | // Convolve by x and y Sobel matrices to get gradient vector 29 | d.x = 1.0 * texture2D(map, (xy + ksize * vec2(-1.0, -1.0)) * px).g; 30 | d.x += 2.0 * texture2D(map, (xy + ksize * vec2(-1.0, 0.0)) * px).g; 31 | d.x += 1.0 * texture2D(map, (xy + ksize * vec2(-1.0, +1.0)) * px).g; 32 | d.x += -1.0 * texture2D(map, (xy + ksize * vec2(+1.0, -1.0)) * px).g; 33 | d.x += -2.0 * texture2D(map, (xy + ksize * vec2(+1.0, 0.0)) * px).g; 34 | d.x += -1.0 * texture2D(map, (xy + ksize * vec2(+1.0, +1.0)) * px).g; 35 | d.y += 1.0 * texture2D(map, (xy + ksize * vec2(-1.0, -1.0)) * px).g; 36 | d.y += 2.0 * texture2D(map, (xy + ksize * vec2( 0.0, -1.0)) * px).g; 37 | d.y += 1.0 * texture2D(map, (xy + ksize * vec2(+1.0, -1.0)) * px).g; 38 | d.y += -1.0 * texture2D(map, (xy + ksize * vec2(-1.0, +1.0)) * px).g; 39 | d.y += -2.0 * texture2D(map, (xy + ksize * vec2( 0.0, +1.0)) * px).g; 40 | d.y += -1.0 * texture2D(map, (xy + ksize * vec2(+1.0, +1.0)) * px).g; 41 | 42 | if(!radial) { 43 | // Rotate 90 degrees 44 | d = vec2(-d.y, d.x); 45 | } 46 | 47 | // Bit of a bodge factor right here 48 | d *= 32.0 / ksize; 49 | 50 | // Output vectors for second pass 51 | gl_FragColor = vec4(d.x, d.y, 0.0, 1.0); 52 | } 53 | -------------------------------------------------------------------------------- /Ls_Splineblur.1.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Splineblur.1.glsl.p -------------------------------------------------------------------------------- /Ls_Splineblur.2.glsl: -------------------------------------------------------------------------------- 1 | // Directional blur driven by gradient vectors of front input 2 | // Pass 2: do the blur 3 | // lewis@lewissaunders.com 4 | // TOOD: 5 | // o Adaptive sampling based on length? 6 | // o Figure out correct calibration of length slider to pixel lengths? 7 | // o Triangular or gaussian window on samples? 8 | // o Normalize gradient vector and use another input for length control? 9 | // Currently, normalizing would give a super hard edge where the front 10 | // image is a solid colour 11 | // o Variable mix between the two algorithms would be neat 12 | 13 | uniform sampler2D front, map, adsk_results_pass1; 14 | uniform float adsk_result_w, adsk_result_h, blength; 15 | uniform int samples; 16 | uniform bool radial, vectors, normalize, pathy, adsk_degrade; 17 | 18 | void main() { 19 | vec2 xy = gl_FragCoord.xy; 20 | 21 | // Factor to convert [0,1] texture coords to pixels 22 | vec2 px = vec2(1.0) / vec2(adsk_result_w, adsk_result_h); 23 | 24 | // Get vectors from previous pass 25 | vec2 d = texture2D(adsk_results_pass1, xy * px).xy; 26 | 27 | if(vectors) { 28 | // Return the vectors, not the blur 29 | if(normalize) { 30 | // Bodge factor for a resonable result from PixelSpread 31 | d /= 4.0; 32 | d += 0.5; 33 | gl_FragColor = vec4(d.x, d.y, 1.0, 1.0); 34 | } else { 35 | gl_FragColor = vec4(d.x, d.y, 0.0, 1.0); 36 | } 37 | return; 38 | } 39 | 40 | if(length(d) == 0.0) { 41 | // No gradient at this point in the map, early out 42 | gl_FragColor = texture2D(front, xy * px); 43 | return; 44 | } 45 | 46 | vec4 a = vec4(0.0); 47 | float sam = float(samples); 48 | float steps; 49 | bool odd = false; 50 | 51 | if(adsk_degrade) { 52 | sam /= 4.0; 53 | } 54 | 55 | if(!pathy) { 56 | // Do a way simpler blur along a line and get outta here 57 | vec2 step = d * blength / (sam - 1.0); 58 | for(float i = 0.0; i < sam; i++) { 59 | a += texture2D(front, (xy + (i - ((sam-1.0)/2.0)) * step) * px); 60 | } 61 | a /= sam; 62 | gl_FragColor = a; 63 | return; 64 | } 65 | 66 | if(mod(sam, 2.0) == 1.0) { 67 | odd = true; 68 | } 69 | if(odd) { 70 | // Odd number of samples, start with a sample from the current position 71 | a = texture2D(front, xy * px); 72 | steps = (sam - 1.0) / 2.0; 73 | } else { 74 | // Even number of samples, start with nothing 75 | a = vec4(0.0); 76 | steps = (sam / 2.0) - 1.0; 77 | } 78 | 79 | // Now accumulate along the path forwards... 80 | if(!odd) { 81 | // Even number of samples, first step is half length 82 | xy += 0.5 * d * blength / (sam - 1.0); 83 | a += texture2D(front, xy * px); 84 | } 85 | for(float i = 0.0; i < steps; i++) { 86 | d = texture2D(adsk_results_pass1, xy * px).xy; 87 | xy += d * blength / (sam - 1.0); 88 | a += texture2D(front, xy * px); 89 | } 90 | 91 | // ...and backwards 92 | xy = gl_FragCoord.xy; 93 | d = texture2D(adsk_results_pass1, xy * px).xy; 94 | if(!odd) { 95 | // Even number of samples, first step is half length 96 | xy -= 0.5 * d * blength / (sam - 1.0); 97 | a += texture2D(front, xy * px); 98 | } 99 | for(float i = 0.0; i < steps; i++) { 100 | xy -= d * blength / (sam - 1.0); 101 | a += texture2D(front, xy * px); 102 | d = texture2D(adsk_results_pass1, xy * px).xy; 103 | } 104 | 105 | a /= sam; 106 | gl_FragColor = a; 107 | } 108 | -------------------------------------------------------------------------------- /Ls_Splineblur.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Ls_Stickon.1.glsl: -------------------------------------------------------------------------------- 1 | // Recursively warp an image by motion vectors to stick it to something 2 | // lewis@lewissaunders.com 3 | // Pass 1: recursively distort image or UV map by the motion vectors 4 | 5 | uniform sampler2D front, matte, vectors, adsk_accum_texture; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform bool adsk_accum_no_prev_frame; 8 | uniform bool accumulateUVs; 9 | 10 | void main() { 11 | vec2 res = vec2(adsk_result_w, adsk_result_h); 12 | vec2 uv = gl_FragCoord.xy / res; 13 | vec2 v = texture2D(vectors, uv).rg / res; 14 | vec4 o; 15 | 16 | if(adsk_accum_no_prev_frame) { 17 | // We're at the first frame, about to start accumulating 18 | if(accumulateUVs) { 19 | // Start out with an identity UV map 20 | o.rg = uv; 21 | o.ba = vec2(0.0); 22 | } else { 23 | // Start out with the first frame of the front/matte 24 | o.rgb = texture2D(front, uv).rgb; 25 | o.a = texture2D(matte, uv).b; 26 | } 27 | } else { 28 | // We are mid-accumulation 29 | // Take the previous output frame, offseting each sample 30 | // by the vectors for this frame 31 | o = texture2D(adsk_accum_texture, uv + v); 32 | } 33 | 34 | gl_FragColor = o; 35 | } 36 | -------------------------------------------------------------------------------- /Ls_Stickon.1.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Stickon.1.glsl.p -------------------------------------------------------------------------------- /Ls_Stickon.2.glsl: -------------------------------------------------------------------------------- 1 | // Recursively warp an image by motion vectors to stick it to something 2 | // lewis@lewissaunders.com 3 | // Pass 2: comp and output distorted image 4 | 5 | uniform sampler2D front, matte, back, adsk_results_pass1; 6 | uniform float adsk_result_w, adsk_result_h; 7 | uniform bool accumulateUVs; 8 | uniform bool outputUVs; 9 | uniform bool comp, ispremult; 10 | 11 | void main() { 12 | vec2 res = vec2(adsk_result_w, adsk_result_h); 13 | vec2 uv = gl_FragCoord.xy / res; 14 | vec4 o; 15 | 16 | if(accumulateUVs) { 17 | vec2 accumulatedUV = texture2D(adsk_results_pass1, uv).rg; 18 | if(outputUVs) { 19 | // Output accumulated UVs directly 20 | o.rg = accumulatedUV; 21 | o.ba = vec2(0.0); 22 | } else { 23 | // Output of pass 1 is UVs, distort front and matte using them 24 | o.rgb = texture2D(front, accumulatedUV).rgb; 25 | o.a = texture2D(matte, accumulatedUV).b; 26 | } 27 | } else { 28 | // Output of pass 1 is image, we can use directly 29 | o.rgb = texture2D(adsk_results_pass1, uv).rgb; 30 | o.a = texture2D(adsk_results_pass1, uv).a; 31 | } 32 | 33 | if(!(outputUVs && accumulateUVs) && comp) { 34 | vec3 bg = texture2D(back, uv).rgb; 35 | if(ispremult) { 36 | o.rgb = bg * (1.0 - o.a) + o.rgb; 37 | } else { 38 | o.rgb = mix(bg.rgb, o.rgb, o.a); 39 | } 40 | } 41 | 42 | gl_FragColor = o; 43 | } 44 | -------------------------------------------------------------------------------- /Ls_Sweat.1.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Sweat.1.glsl.p -------------------------------------------------------------------------------- /Ls_Sweat.3.glsl: -------------------------------------------------------------------------------- 1 | // Sweat, pass 3: read sim matte and derive UVs 2 | // This is in a seperate pass to cache the UVs so we can multisample 3 | // them more cheaply 4 | // lewis@lewissaunders.com 5 | 6 | uniform sampler2D adsk_results_pass2, front; 7 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio; 8 | uniform float ksize; 9 | 10 | void main() { 11 | vec2 res = vec2(adsk_result_w, adsk_result_h); 12 | vec2 xy = gl_FragCoord.xy; 13 | float h = texture2D(adsk_results_pass2, xy/res).r; 14 | 15 | // Convolve by x and y Sobel matrices to get gradient vector 16 | vec2 d; 17 | d.x = -1.0 * texture2D(adsk_results_pass2, (xy + ksize * vec2(-1.0, -1.0)) / res).g; 18 | d.x += -2.0 * texture2D(adsk_results_pass2, (xy + ksize * vec2(-1.0, 0.0)) / res).g; 19 | d.x += -1.0 * texture2D(adsk_results_pass2, (xy + ksize * vec2(-1.0, +1.0)) / res).g; 20 | d.x += 1.0 * texture2D(adsk_results_pass2, (xy + ksize * vec2(+1.0, -1.0)) / res).g; 21 | d.x += 2.0 * texture2D(adsk_results_pass2, (xy + ksize * vec2(+1.0, 0.0)) / res).g; 22 | d.x += 1.0 * texture2D(adsk_results_pass2, (xy + ksize * vec2(+1.0, +1.0)) / res).g; 23 | d.y = -1.0 * texture2D(adsk_results_pass2, (xy + ksize * vec2(-1.0, -1.0)) / res).g; 24 | d.y += -2.0 * texture2D(adsk_results_pass2, (xy + ksize * vec2( 0.0, -1.0)) / res).g; 25 | d.y += -1.0 * texture2D(adsk_results_pass2, (xy + ksize * vec2(+1.0, -1.0)) / res).g; 26 | d.y += 1.0 * texture2D(adsk_results_pass2, (xy + ksize * vec2(-1.0, +1.0)) / res).g; 27 | d.y += 2.0 * texture2D(adsk_results_pass2, (xy + ksize * vec2( 0.0, +1.0)) / res).g; 28 | d.y += 1.0 * texture2D(adsk_results_pass2, (xy + ksize * vec2(+1.0, +1.0)) / res).g; 29 | d /= ksize; 30 | 31 | gl_FragColor = vec4(d, h, h); 32 | } 33 | -------------------------------------------------------------------------------- /Ls_Sweat.4.glsl: -------------------------------------------------------------------------------- 1 | // Sweat, pass 4: read UVs and distort the image 2 | // lewis@lewissaunders.com 3 | 4 | uniform sampler2D adsk_results_pass3, front; 5 | uniform float adsk_result_w, adsk_result_h, adsk_result_frameratio; 6 | uniform float distomult; 7 | uniform int isamples; 8 | uniform bool outputuvs; 9 | 10 | void main() { 11 | vec2 res = vec2(adsk_result_w, adsk_result_h); 12 | vec2 xy = gl_FragCoord.xy; 13 | vec2 uv = texture2D(adsk_results_pass3, xy/res).rg; 14 | float h = texture2D(adsk_results_pass3, xy/res).b; 15 | vec3 bg = texture2D(front, xy/res).rgb; 16 | 17 | // Multisampled UV mapping - read from the texture a bunch 18 | // of times and average to reduce noise. This seems more effective 19 | // than EWA filtering a lot of the time and is much faster 20 | vec3 rgb = vec3(0.0); 21 | float samps = float(isamples); 22 | float spacing = 1.0 / (samps + 1.0); 23 | for(float i = 1.0; i <= samps; i++) { 24 | for(float j = 1.0; j <= samps; j++) { 25 | vec2 sample_xy = floor(gl_FragCoord.xy); 26 | sample_xy += vec2(i, j) * vec2(spacing); 27 | vec2 sample_uv = texture2D(adsk_results_pass3, sample_xy/res).rg; 28 | sample_uv *= distomult; 29 | sample_uv += xy/res; 30 | rgb += texture2D(front, sample_uv).rgb; 31 | } 32 | } 33 | rgb /= samps * samps; 34 | 35 | if(outputuvs) { 36 | rgb.rg = uv; 37 | rgb.rg *= distomult; 38 | rgb.rg += xy/res; 39 | rgb.b = 0.0; 40 | bg.rg = xy/res; 41 | bg.b = 0.0; 42 | } 43 | 44 | // Comp the distorted front over the clean one with a cropped in matte 45 | // This removes some horrible edges 46 | float matte = clamp(pow((h * 2.0), 3.0), 0.0, 1.0); 47 | vec3 o = mix(bg, rgb, matte); 48 | 49 | gl_FragColor = vec4(o, matte); 50 | } 51 | -------------------------------------------------------------------------------- /Ls_Tinyplanet.glsl: -------------------------------------------------------------------------------- 1 | // Stereographic projection of a 360x180 latlong panorama, tiny planets style 2 | // lewis@lewissaunders.com 3 | 4 | uniform float adsk_result_w, adsk_result_h; 5 | uniform sampler2D front; 6 | uniform float yo, xo, long0, lat1, r; 7 | uniform float latm, longm, lato, longo; 8 | 9 | // Defaults set in XML: 10 | // xo = 0.5 11 | // yo = 0.5 12 | // long0, lat1, r = adjusted to taste 13 | // latm = 1.0 / PI 14 | // longm = 1.0 / (2.0 * PI) 15 | // lato = -PI / 2.0 16 | // longo = -PI 17 | 18 | void main() { 19 | vec2 res = vec2(adsk_result_w, adsk_result_h); 20 | vec2 coords = gl_FragCoord.xy / res; 21 | coords.x -= 0.5; 22 | coords.x *= (res.x / res.y); 23 | coords.x += 0.5; 24 | 25 | float p = sqrt((coords.x-xo)*(coords.x-xo)+(coords.y-yo)*(coords.y-yo)); 26 | float c = 2.0 * atan(p, 2.0 * r); 27 | float longg = (long0 + atan((coords.x-xo)*sin(c), p*cos(lat1)*cos(c) - (coords.y-yo)*sin(lat1)*sin(c))); 28 | float lat = asin(cos(c)*sin(lat1) + (((coords.y-yo)*sin(c)*cos(lat1)) / p)); 29 | vec2 uv; 30 | uv.x = (longg - longo) * longm; 31 | uv.y = (lat - lato) * latm; 32 | 33 | vec3 o = texture2D(front, uv).rgb; 34 | 35 | gl_FragColor = vec4(o, 1.00); 36 | } 37 | -------------------------------------------------------------------------------- /Ls_Tinyplanet.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Tinyplanet.glsl.p -------------------------------------------------------------------------------- /Ls_Tinyplanet.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Ls_UVewa.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_UVewa.glsl.p -------------------------------------------------------------------------------- /Ls_Vignette.glsl: -------------------------------------------------------------------------------- 1 | // Vignette 2 | // lewis@lewissaunders.com 3 | 4 | uniform float adsk_result_w, adsk_result_h; 5 | uniform float adsk_result_frameratio; 6 | uniform vec3 edgetint, midtint; 7 | uniform vec2 centre; 8 | uniform float radius, mixamt, abruptness, aspect; 9 | uniform sampler2D front; 10 | uniform bool clampblack, applyoffset; 11 | 12 | // S-shaped function with variable steepness s 13 | // Maps 0..1 to 0..1 14 | float smoothishstep(float x, float s) { 15 | if(x < 0.5) { 16 | return 0.5*((s*2.0*x - 2.0*x)/(2.0*s*2.0*x - s - 1.0)); 17 | } else { 18 | float z = x - 0.5; 19 | float t = -s; 20 | return 0.5*((t*2.0*z - 2.0*z)/(2.0*t*2.0*z - t - 1.0)) + 0.5; 21 | } 22 | } 23 | 24 | void main() { 25 | vec2 uv = gl_FragCoord.xy / vec2(adsk_result_w, adsk_result_h); 26 | vec3 f = texture2D(front, uv).rgb; 27 | 28 | vec2 tocent = uv - centre; 29 | tocent.x *= adsk_result_frameratio; 30 | tocent.x *= aspect; 31 | float rad = length(tocent); 32 | rad /= radius; 33 | float v = pow(cos(clamp(rad, 0.0, 3.1415926535/2.0)), 4.0); 34 | v = smoothishstep(v, abruptness); 35 | 36 | vec3 o; 37 | if(applyoffset) { 38 | o = f - 0.3333 * (1.0 - v); 39 | o = mix(o, o + (edgetint - vec3(0.5)), 1.0 - v); 40 | o = mix(o, o + (midtint - vec3(0.5)), v); 41 | } else { 42 | o = f * v; 43 | o = mix(o, o * (edgetint + vec3(0.5)), 1.0 - v); 44 | o = mix(o, o * (midtint + vec3(0.5)), v); 45 | } 46 | 47 | o = mix(f, o, mixamt); 48 | 49 | if(clampblack) { 50 | o = clamp(o, 0.0, 999999.0); 51 | } 52 | 53 | float m = v; 54 | m = mix(1.0, m, mixamt); 55 | 56 | gl_FragColor = vec4(o, m); 57 | } 58 | -------------------------------------------------------------------------------- /Ls_Vignette.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Vignette.glsl.p -------------------------------------------------------------------------------- /Ls_Vops.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Vops.glsl.p -------------------------------------------------------------------------------- /Ls_Wireless.glsl.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lcrs/matchboxes/24c50c71de7681c7a86ed276e9f1c6b3e0f06ea2/Ls_Wireless.glsl.p --------------------------------------------------------------------------------