I've found this really neat glitch effect written with GLSL and was banging my head trying to apply it to LOVE since, but to no avail. Here's a link.
https://www.shadertoy.com/view/XtyXzW
The main problem is that it's written for 3D environment and all of it's rendering logic is tied into that. Any hints?
Glitch shader?
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
Re: Glitch shader?
Shadertoy is not 3d nor uses non-standard OpenGL so you shouldn't have any problems. I indeed did not.
Code: Select all
local shader = [[
uniform vec3 iResolution; // viewport resolution (in pixels)
uniform float iTime; // shader playback time (in seconds)
uniform vec4 iMouse; // mouse pixel coords. xy: current (if MLB down), zw: click
#define MODEL_ROTATION vec2(.5, .5)
#define LIGHT_ROTATION vec2(.3, .8)
#define CAMERA_ROTATION vec2(.5, .67)
// Mouse control
// 0: Defaults
// 1: Model
// 2: Lighting
// 3: Camera
#define MOUSE_CONTROL 1
// Debugging
//#define NORMALS
//#define NO_GLITCH
//#define GLITCH_MASK
float time;
float round(float n) {
return floor(n + .5);
}
vec2 round(vec2 n) {
return floor(n + .5);
}
// --------------------------------------------------------
// HG_SDF
// https://www.shadertoy.com/view/Xs3GRB
// --------------------------------------------------------
#define PI 3.14159265359
#define PHI (1.618033988749895)
#define TAU 6.283185307179586
float vmax(vec3 v) {
return max(max(v.x, v.y), v.z);
}
// Rotate around a coordinate axis (i.e. in a plane perpendicular to that axis) by angle <a>.
// Read like this: R(p.xz, a) rotates "x towards z".
// This is fast if <a> is a compile-time constant and slower (but still practical) if not.
void pR(inout vec2 p, float a) {
p = cos(a)*p + sin(a)*vec2(p.y, -p.x);
}
// Plane with normal n (n is normalized) at some distance from the origin
float fPlane(vec3 p, vec3 n, float distanceFromOrigin) {
return dot(p, n) + distanceFromOrigin;
}
// Box: correct distance to corners
float fBox(vec3 p, vec3 b) {
vec3 d = abs(p) - b;
return length(max(d, vec3(0))) + vmax(min(d, vec3(0)));
}
#define GDFVector3 normalize(vec3(1, 1, 1 ))
#define GDFVector4 normalize(vec3(-1, 1, 1))
#define GDFVector5 normalize(vec3(1, -1, 1))
#define GDFVector6 normalize(vec3(1, 1, -1))
#define GDFVector7 normalize(vec3(0, 1, PHI+1.))
#define GDFVector8 normalize(vec3(0, -1, PHI+1.))
#define GDFVector9 normalize(vec3(PHI+1., 0, 1))
#define GDFVector10 normalize(vec3(-PHI-1., 0, 1))
#define GDFVector11 normalize(vec3(1, PHI+1., 0))
#define GDFVector12 normalize(vec3(-1, PHI+1., 0))
#define GDFVector13 normalize(vec3(0, PHI, 1))
#define GDFVector14 normalize(vec3(0, -PHI, 1))
#define GDFVector15 normalize(vec3(1, 0, PHI))
#define GDFVector16 normalize(vec3(-1, 0, PHI))
#define GDFVector17 normalize(vec3(PHI, 1, 0))
#define GDFVector18 normalize(vec3(-PHI, 1, 0))
#define fGDFBegin float d = 0.;
#define fGDF(v) d = max(d, abs(dot(p, v)));
#define fGDFEnd return d - r;
float fDodecahedron(vec3 p, float r) {
fGDFBegin
fGDF(GDFVector13) fGDF(GDFVector14) fGDF(GDFVector15) fGDF(GDFVector16)
fGDF(GDFVector17) fGDF(GDFVector18)
fGDFEnd
}
float fIcosahedron(vec3 p, float r) {
fGDFBegin
fGDF(GDFVector3) fGDF(GDFVector4) fGDF(GDFVector5) fGDF(GDFVector6)
fGDF(GDFVector7) fGDF(GDFVector8) fGDF(GDFVector9) fGDF(GDFVector10)
fGDF(GDFVector11) fGDF(GDFVector12)
fGDFEnd
}
// --------------------------------------------------------
// Rotation
// --------------------------------------------------------
mat3 sphericalMatrix(float theta, float phi) {
float cx = cos(theta);
float cy = cos(phi);
float sx = sin(theta);
float sy = sin(phi);
return mat3(
cy, -sy * -sx, -sy * cx,
0, cx, sx,
sy, cy * -sx, cy * cx
);
}
mat3 mouseRotation(bool enable, vec2 xy) {
if (enable) {
vec2 mouse = iMouse.xy / iResolution.xy;
if (mouse.x != 0. && mouse.y != 0.) {
xy.x = mouse.x;
xy.y = mouse.y;
}
}
float rx, ry;
rx = (xy.y + .5) * PI;
ry = (-xy.x) * 2. * PI;
return sphericalMatrix(rx, ry);
}
mat3 modelRotation() {
mat3 m = mouseRotation(MOUSE_CONTROL==1, MODEL_ROTATION);
return m;
}
mat3 lightRotation() {
mat3 m = mouseRotation(MOUSE_CONTROL==2, LIGHT_ROTATION);
return m;
}
mat3 cameraRotation() {
mat3 m = mouseRotation(MOUSE_CONTROL==3, CAMERA_ROTATION);
return m;
}
// --------------------------------------------------------
// Modelling
// --------------------------------------------------------
struct Material {
vec3 albedo;
};
struct Model {
float dist;
Material material;
};
Material defaultMaterial = Material(
vec3(.5)
);
Model newModel() {
return Model(
10000.,
defaultMaterial
);
}
const float modelSize = 1.2;
float blend(float y, float blend, float progress) {
float a = (y / modelSize) + .5;
a -= progress * (1. + blend) - blend * .5;
a += blend / 2.;
a /= blend;
a = clamp(a, 0., 1.);
a = smoothstep(0., 1., a);
a = smoothstep(0., 1., a);
return a;
}
float ShapeBlend(float y, float progress) {
float shapeProgress = clamp(progress * 2. - .5, 0., 1.);
float shapeBlend = blend(y, .8, shapeProgress);
return shapeBlend;
}
float SpinBlend(float y, float progress) {
return blend(y, 1.5, progress);
}
float Flip() {
return round(mod(time, 1.));
}
float Progress() {
float progress = mod(time*2., 1.);
//progress = smoothstep(0., 1., progress);
//progress = sin(progress * PI - PI/2.) * .5 + .5;
return progress;
}
Model mainModel(vec3 p) {
Model model = newModel();
float progress = Progress();
float flip = Flip();
float spinBlend = SpinBlend(p.y, progress);
pR(p.xz, spinBlend * PI / 2.);
pR(p.xz, PI * -.5 * flip);
float part1 = fDodecahedron(p, modelSize * .5);
pR(p.xz, PI/2.);
float part2 = fIcosahedron(p, modelSize * .5);
float shapeBlend = ShapeBlend(p.y, progress);
shapeBlend = mix(shapeBlend, 1. - shapeBlend, flip);
float d = mix(part1, part2, shapeBlend);
model.dist = d;
model.material.albedo = mix(vec3(.03), vec3(.8), 1. - shapeBlend);
return model;
}
Model glitchModel(vec3 p) {
Model model = newModel();
float progress = Progress();
float band = ShapeBlend(p.y, progress);
band = sin(band * PI);
float fadeBottom = clamp(1. - dot(p, vec3(0,1,0)), 0., 1.);
band *= fadeBottom;
float radius = modelSize / 2. + band * .2;
model.dist = length(p) - radius;
model.material.albedo = vec3(band);
return model;
}
Model map( vec3 p , bool glitchMask){
mat3 m = modelRotation();
p *= m;
pR(p.xz, -time*PI);
if (glitchMask) {
return glitchModel(p);
}
Model model = mainModel(p);
return model;
}
// --------------------------------------------------------
// LIGHTING
// https://www.shadertoy.com/view/Xds3zN
// --------------------------------------------------------
float softshadow( in vec3 ro, in vec3 rd, in float mint, in float tmax )
{
float res = 1.0;
float t = mint;
for( int i=0; i<16; i++ )
{
float h = map( ro + rd*t, false ).dist;
res = min( res, 8.0*h/t );
t += clamp( h, 0.02, 0.10 );
if( h<0.00001 || t>tmax ) break;
}
return clamp( res, 0.0, 1.0 );
}
float calcAO( in vec3 pos, in vec3 nor )
{
float occ = 0.0;
float sca = 1.0;
for( int i=0; i<5; i++ )
{
float hr = 0.01 + 0.12*float(i)/4.0;
vec3 aopos = nor * hr + pos;
float dd = map( aopos, false ).dist;
occ += -(dd-hr)*sca;
sca *= 0.95;
}
return clamp( 1.0 - 3.0*occ, 0.0, 1.0 );
}
vec3 doLighting(Material material, vec3 pos, vec3 nor, vec3 ref, vec3 rd) {
vec3 lightPos = vec3(0,0,-1);
vec3 backLightPos = normalize(vec3(0,-.3,1));
vec3 ambientPos = vec3(0,1,0);
mat3 m = lightRotation();
lightPos *= m;
backLightPos *= m;
float occ = calcAO( pos, nor );
vec3 lig = lightPos;
float amb = clamp((dot(nor, ambientPos) + 1.) / 2., 0., 1.);
float dif = clamp((dot(nor, lig) + 1.) / 3., 0.0, 1.0 );
float bac = pow(clamp(dot(nor, backLightPos), 0., 1.), 1.5);
float fre = pow( clamp(1.0+dot(nor,rd),0.0,1.0), 2.0 );
dif *= softshadow( pos, lig, 0.01, 2.5 ) * .5 + .5;
vec3 lin = vec3(0.0);
lin += 1.20*dif*vec3(.95,0.80,0.60);
lin += 0.80*amb*vec3(0.50,0.70,.80)*occ;
lin += 0.30*bac*vec3(0.25,0.25,0.25)*occ;
lin += 0.20*fre*vec3(1.00,1.00,1.00)*occ;
vec3 col = material.albedo*lin;
float spe = clamp(dot(ref, lightPos), 0., 1.);
spe = pow(spe, 2.) * .1;
col += spe;
return col;
}
// --------------------------------------------------------
// Ray Marching
// Adapted from: https://www.shadertoy.com/view/Xl2XWt
// --------------------------------------------------------
const float MAX_TRACE_DISTANCE = 30.; // max trace distance
const float INTERSECTION_PRECISION = .001; // precision of the intersection
const int NUM_OF_TRACE_STEPS = 100;
const float FUDGE_FACTOR = .9; // Default is 1, reduce to fix overshoots
struct CastRay {
vec3 origin;
vec3 direction;
bool glitchMask;
};
struct Ray {
vec3 origin;
vec3 direction;
float len;
};
struct Hit {
Ray ray;
Model model;
vec3 pos;
bool isBackground;
vec3 normal;
vec3 color;
};
vec3 calcNormal( in vec3 pos ){
vec3 eps = vec3( 0.001, 0.0, 0.0 );
vec3 nor = vec3(
map(pos+eps.xyy, false).dist - map(pos-eps.xyy, false).dist,
map(pos+eps.yxy, false).dist - map(pos-eps.yxy, false).dist,
map(pos+eps.yyx, false).dist - map(pos-eps.yyx, false).dist );
return normalize(nor);
}
Hit raymarch(CastRay castRay){
float currentDist = INTERSECTION_PRECISION * 2.0;
Model model;
Ray ray = Ray(castRay.origin, castRay.direction, 0.);
for( int i=0; i< NUM_OF_TRACE_STEPS ; i++ ){
if (currentDist < INTERSECTION_PRECISION || ray.len > MAX_TRACE_DISTANCE) {
break;
}
model = map(ray.origin + ray.direction * ray.len, castRay.glitchMask);
currentDist = model.dist;
ray.len += currentDist * FUDGE_FACTOR;
}
bool isBackground = false;
vec3 pos = vec3(0);
vec3 normal = vec3(0);
vec3 color = vec3(0);
if (ray.len > MAX_TRACE_DISTANCE) {
isBackground = true;
} else {
pos = ray.origin + ray.direction * ray.len;
normal = calcNormal(pos);
}
return Hit(ray, model, pos, isBackground, normal, color);
}
// --------------------------------------------------------
// Rendering
// Refraction from https://www.shadertoy.com/view/lsXGzH
// --------------------------------------------------------
void shadeSurface(inout Hit hit){
vec3 color = vec3(.25);
if (hit.isBackground) {
hit.color = color;
return;
}
#ifdef NORMALS
color = hit.normal * 0.5 + 0.5;
#else
vec3 ref = reflect(hit.ray.direction, hit.normal);
color = doLighting(
hit.model.material,
hit.pos,
hit.normal,
ref,
hit.ray.direction
);
#endif
hit.color = color;
}
vec3 render(Hit hit){
shadeSurface(hit);
if (hit.isBackground) {
return hit.color;
}
return hit.color;
}
// --------------------------------------------------------
// Camera
// https://www.shadertoy.com/view/Xl2XWt
// --------------------------------------------------------
mat3 calcLookAtMatrix( in vec3 ro, in vec3 ta, in float roll )
{
vec3 ww = normalize( ta - ro );
vec3 uu = normalize( cross(ww,vec3(sin(roll),cos(roll),0.0) ) );
vec3 vv = normalize( cross(uu,ww));
return mat3( uu, vv, ww );
}
void doCamera(out vec3 camPos, out vec3 camTar, out float camRoll, in float time, in vec2 mouse) {
float dist = 3.;
camRoll = 0.;
camTar = vec3(0,0,0);
camPos = vec3(0,0,-dist);
camPos *= cameraRotation();
camPos += camTar;
}
Hit raymarchPixel(vec2 p, bool glitchPass) {
vec2 m = iMouse.xy / iResolution.xy;
vec3 camPos = vec3( 0., 0., 2.);
vec3 camTar = vec3( 0. , 0. , 0. );
float camRoll = 0.;
// camera movement
doCamera(camPos, camTar, camRoll, iTime, m);
// camera matrix
mat3 camMat = calcLookAtMatrix( camPos, camTar, camRoll ); // 0.0 is the camera roll
// create view ray
float focalLength = 3.;
vec3 rd = normalize( camMat * vec3(p.xy, focalLength) );
Hit hit = raymarch(CastRay(camPos, rd, glitchPass));
return hit;
}
// --------------------------------------------------------
// Gamma
// https://www.shadertoy.com/view/Xds3zN
// --------------------------------------------------------
const float GAMMA = 2.2;
vec3 gamma(vec3 color, float g) {
return pow(color, vec3(g));
}
vec3 linearToScreen(vec3 linearRGB) {
return gamma(linearRGB, 1.0 / GAMMA);
}
// --------------------------------------------------------
// Glitch core
// --------------------------------------------------------
float rand(vec2 co){
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
const float glitchScale = .5;
vec2 glitchCoord(vec2 p, vec2 gridSize) {
vec2 coord = floor(p / gridSize) * gridSize;;
coord += (gridSize / 2.);
return coord;
}
struct GlitchSeed {
vec2 seed;
float prob;
};
float fBox2d(vec2 p, vec2 b) {
vec2 d = abs(p) - b;
return min(max(d.x, d.y), 0.0) + length(max(d, 0.0));
}
GlitchSeed glitchSeed(vec2 p, float speed) {
float seedTime = floor(time * speed);
vec2 seed = vec2(
1. + mod(seedTime / 100., 100.),
1. + mod(seedTime, 100.)
) / 100.;
seed += p;
float prob = 0.;
Hit hit = raymarchPixel(p, true);
if ( ! hit.isBackground) {
prob = hit.model.material.albedo.x;
}
return GlitchSeed(seed, prob);
}
float shouldApply(GlitchSeed seed) {
return round(
mix(
mix(rand(seed.seed), 1., seed.prob - .5),
0.,
(1. - seed.prob) * .5
)
);
}
// --------------------------------------------------------
// Glitch effects
// --------------------------------------------------------
// Swap
vec4 swapCoords(vec2 seed, vec2 groupSize, vec2 subGrid, vec2 blockSize) {
vec2 rand2 = vec2(rand(seed), rand(seed+.1));
vec2 range = subGrid - (blockSize - 1.);
vec2 coord = floor(rand2 * range) / subGrid;
vec2 bottomLeft = coord * groupSize;
vec2 realBlockSize = (groupSize / subGrid) * blockSize;
vec2 topRight = bottomLeft + realBlockSize;
topRight -= groupSize / 2.;
bottomLeft -= groupSize / 2.;
return vec4(bottomLeft, topRight);
}
float isInBlock(vec2 pos, vec4 block) {
vec2 a = sign(pos - block.xy);
vec2 b = sign(block.zw - pos);
return min(sign(a.x + a.y + b.x + b.y - 3.), 0.);
}
vec2 moveDiff(vec2 pos, vec4 swapA, vec4 swapB) {
vec2 diff = swapB.xy - swapA.xy;
return diff * isInBlock(pos, swapA);
}
void swapBlocks(inout vec2 xy, vec2 groupSize, vec2 subGrid, vec2 blockSize, vec2 seed, float apply) {
vec2 groupOffset = glitchCoord(xy, groupSize);
vec2 pos = xy - groupOffset;
vec2 seedA = seed * groupOffset;
vec2 seedB = seed * (groupOffset + .1);
vec4 swapA = swapCoords(seedA, groupSize, subGrid, blockSize);
vec4 swapB = swapCoords(seedB, groupSize, subGrid, blockSize);
vec2 newPos = pos;
newPos += moveDiff(pos, swapA, swapB) * apply;
newPos += moveDiff(pos, swapB, swapA) * apply;
pos = newPos;
xy = pos + groupOffset;
}
// Static
void staticNoise(inout vec2 p, vec2 groupSize, float grainSize, float contrast) {
GlitchSeed seedA = glitchSeed(glitchCoord(p, groupSize), 5.);
seedA.prob *= .5;
if (shouldApply(seedA) == 1.) {
GlitchSeed seedB = glitchSeed(glitchCoord(p, vec2(grainSize)), 5.);
vec2 offset = vec2(rand(seedB.seed), rand(seedB.seed + .1));
offset = round(offset * 2. - 1.);
offset *= contrast;
p += offset;
}
}
// Freeze time
void freezeTime(vec2 p, inout float time, vec2 groupSize, float speed) {
GlitchSeed seed = glitchSeed(glitchCoord(p, groupSize), speed);
//seed.prob *= .5;
if (shouldApply(seed) == 1.) {
float frozenTime = floor(time * speed) / speed;
time = frozenTime;
}
}
// --------------------------------------------------------
// Glitch compositions
// --------------------------------------------------------
void glitchSwap(inout vec2 p) {
vec2 pp = p;
float scale = glitchScale;
float speed = 5.;
vec2 groupSize;
vec2 subGrid;
vec2 blockSize;
GlitchSeed seed;
float apply;
groupSize = vec2(.6) * scale;
subGrid = vec2(2);
blockSize = vec2(1);
seed = glitchSeed(glitchCoord(p, groupSize), speed);
apply = shouldApply(seed);
swapBlocks(p, groupSize, subGrid, blockSize, seed.seed, apply);
groupSize = vec2(.8) * scale;
subGrid = vec2(3);
blockSize = vec2(1);
seed = glitchSeed(glitchCoord(p, groupSize), speed);
apply = shouldApply(seed);
swapBlocks(p, groupSize, subGrid, blockSize, seed.seed, apply);
groupSize = vec2(.2) * scale;
subGrid = vec2(6);
blockSize = vec2(1);
seed = glitchSeed(glitchCoord(p, groupSize), speed);
float apply2 = shouldApply(seed);
swapBlocks(p, groupSize, subGrid, blockSize, (seed.seed + 1.), apply * apply2);
swapBlocks(p, groupSize, subGrid, blockSize, (seed.seed + 2.), apply * apply2);
swapBlocks(p, groupSize, subGrid, blockSize, (seed.seed + 3.), apply * apply2);
swapBlocks(p, groupSize, subGrid, blockSize, (seed.seed + 4.), apply * apply2);
swapBlocks(p, groupSize, subGrid, blockSize, (seed.seed + 5.), apply * apply2);
groupSize = vec2(1.2, .2) * scale;
subGrid = vec2(9,2);
blockSize = vec2(3,1);
seed = glitchSeed(glitchCoord(p, groupSize), speed);
apply = shouldApply(seed);
swapBlocks(p, groupSize, subGrid, blockSize, seed.seed, apply);
}
void glitchStatic(inout vec2 p) {
// Static
//staticNoise(p, vec2(.25, .25/2.) * glitchScale, .005, 5.);
// 8-bit
staticNoise(p, vec2(.5, .25/2.) * glitchScale, .2 * glitchScale, 2.);
}
void glitchTime(vec2 p, inout float time) {
freezeTime(p, time, vec2(.5) * glitchScale, 2.);
}
void glitchColor(vec2 p, inout vec3 color) {
vec2 groupSize = vec2(.75,.125) * glitchScale;
vec2 subGrid = vec2(0,6);
float speed = 5.;
GlitchSeed seed = glitchSeed(glitchCoord(p, groupSize), speed);
seed.prob *= .3;
if (shouldApply(seed) == 1.) {
vec2 co = mod(p, groupSize) / groupSize;
co *= subGrid;
float a = max(co.x, co.y);
//color.rgb *= vec3(
// min(floor(mod(a - 0., 3.)), 1.),
// min(floor(mod(a - 1., 3.)), 1.),
// min(floor(mod(a - 2., 3.)), 1.)
//);
color *= min(floor(mod(a, 2.)), 1.) * 10.;
}
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
time = iTime;
time /= 3.;
time = mod(time, 1.);
vec2 p = (-iResolution.xy + 2.0*fragCoord.xy)/iResolution.y;
vec3 color;
#ifdef GLITCH_MASK
float prob = glitchSeed(p, 10.).prob;
color = vec3(prob);
#else
#ifndef NO_GLITCH
glitchSwap(p);
glitchTime(p, time);
glitchStatic(p);
#endif
Hit hit = raymarchPixel(p, false);
color = render(hit);
#ifndef NO_GLITCH
glitchColor(p, color);
#endif
#ifndef NORMALS
color = linearToScreen(color);
#endif
#endif
fragColor = vec4(color,1.0);
}
vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords)
{
vec4 c;
mainImage ( c, screen_coords );
return c;
}
]]
local t = 0
function love.load ( )
shader = love.graphics.newShader ( shader )
end
function love.update ( dt )
t = t + dt
end
function love.draw ( )
love.graphics.setShader ( shader )
shader:send ( "iTime", t )
shader:send ( "iMouse", { love.mouse.getX ( ), love.mouse.getY ( ), love.mouse.isDown ( 1 ) and 1 or 0, love.mouse.isDown ( 2 ) and 1 or 0 } )
shader:send ( "iResolution", { 800, 600, 0 } )
love.graphics.rectangle ( "fill", 0, 0, 800, 600 )
love.graphics.setShader ( )
love.graphics.print ( love.timer.getFPS ( ), 10, 10 )
end
Re: Glitch shader?
With original's author's help I was able to make this shader, that can be applied do any graphic element. You have to feed it time every frame for it to change, I used this:
And here's the shader itself.
The speed of glitching is determined in void glitchSwap, where you can tweak float speed.
The decay of glitching is determined in GlitchSeed glitchSeed, where you can change float prob. Default is 1, which should land it approximately in a middle of a processed texture. You can move intensity center elsewhere, for example 1-p.y moves it to top, p.x moves it to right.
Code: Select all
shader:send("iTime",os.clock())
Code: Select all
uniform float iTime;
float time;
float round(float n) {
return floor(n + .5);
}
vec2 round(vec2 n) {
return floor(n + .5);
}
float rand(vec2 co){
return fract(dot(co.xy,vec2(12.9898,78.233)) * 43758.5453);
}
const float glitchScale = .2;
vec2 glitchCoord(vec2 p, vec2 gridSize) {
vec2 coord = floor(p / gridSize) * gridSize;
coord += (gridSize / 2.);
return coord;
}
struct GlitchSeed {
vec2 seed;
float prob;
};
GlitchSeed glitchSeed(vec2 p, float speed) {
float seedTime = floor(time * speed);
vec2 seed = vec2(
1. + mod(seedTime / 100., 100.),
1. + mod(seedTime, 100.)
) / 100.;
seed += p;
float prob = 1;
return GlitchSeed(seed, prob);
}
float shouldApply(GlitchSeed seed) {
return round(
mix(
mix(rand(seed.seed), 1., seed.prob - .5),
0.,
(1. - seed.prob) * .5
)
);
}
vec4 swapCoords(vec2 seed, vec2 groupSize, vec2 subGrid, vec2 blockSize) {
vec2 rand2 = vec2(rand(seed), rand(seed+.1));
vec2 range = subGrid - (blockSize - 1.);
vec2 coord = floor(rand2 * range) / subGrid;
vec2 bottomLeft = coord * groupSize;
vec2 realBlockSize = (groupSize / subGrid) * blockSize;
vec2 topRight = bottomLeft + realBlockSize;
topRight -= groupSize / 2.;
bottomLeft -= groupSize / 2.;
return vec4(bottomLeft, topRight);
}
float isInBlock(vec2 pos, vec4 block) {
vec2 a = sign(pos - block.xy);
vec2 b = sign(block.zw - pos);
return min(sign(a.x + a.y + b.x + b.y - 3.), 0.);
}
vec2 moveDiff(vec2 pos, vec4 swapA, vec4 swapB) {
vec2 diff = swapB.xy - swapA.xy;
return diff * isInBlock(pos, swapA);
}
void swapBlocks(inout vec2 xy, vec2 groupSize, vec2 subGrid, vec2 blockSize, vec2 seed, float apply) {
vec2 groupOffset = glitchCoord(xy, groupSize);
vec2 pos = xy - groupOffset;
vec2 seedA = seed * groupOffset;
vec2 seedB = seed * (groupOffset + .1);
vec4 swapA = swapCoords(seedA, groupSize, subGrid, blockSize);
vec4 swapB = swapCoords(seedB, groupSize, subGrid, blockSize);
vec2 newPos = pos;
newPos += moveDiff(pos, swapA, swapB) * apply;
newPos += moveDiff(pos, swapB, swapA) * apply;
pos = newPos;
xy = pos + groupOffset;
}
void staticNoise(inout vec2 p, vec2 groupSize, float grainSize, float contrast) {
GlitchSeed seedA = glitchSeed(glitchCoord(p, groupSize), 5.);
seedA.prob *= .5;
if (shouldApply(seedA) == 1.) {
GlitchSeed seedB = glitchSeed(glitchCoord(p, vec2(grainSize)), 5.);
vec2 offset = vec2(rand(seedB.seed), rand(seedB.seed + .1));
offset = round(offset * 2. - 1.);
offset *= contrast;
p += offset;
}
}
void freezeTime(vec2 p, inout float time, vec2 groupSize, float speed) {
GlitchSeed seed = glitchSeed(glitchCoord(p, groupSize), speed);
if (shouldApply(seed) == 1.) {
float frozenTime = floor(time * speed) / speed;
time = frozenTime;
}
}
void glitchSwap(inout vec2 p) {
vec2 pp = p;
float scale = glitchScale;
float speed = 25.;
vec2 groupSize;
vec2 subGrid;
vec2 blockSize;
GlitchSeed seed;
float apply;
groupSize = vec2(.6) * scale;
subGrid = vec2(2);
blockSize = vec2(1);
seed = glitchSeed(glitchCoord(p, groupSize), speed);
apply = shouldApply(seed);
swapBlocks(p, groupSize, subGrid, blockSize, seed.seed, apply);
groupSize = vec2(.8) * scale;
subGrid = vec2(3);
blockSize = vec2(1);
seed = glitchSeed(glitchCoord(p, groupSize), speed);
apply = shouldApply(seed);
swapBlocks(p, groupSize, subGrid, blockSize, seed.seed, apply);
groupSize = vec2(.2) * scale;
subGrid = vec2(6);
blockSize = vec2(1);
seed = glitchSeed(glitchCoord(p, groupSize), speed);
float apply2 = shouldApply(seed);
swapBlocks(p, groupSize, subGrid, blockSize, (seed.seed + 1.), apply * apply2);
swapBlocks(p, groupSize, subGrid, blockSize, (seed.seed + 2.), apply * apply2);
swapBlocks(p, groupSize, subGrid, blockSize, (seed.seed + 3.), apply * apply2);
swapBlocks(p, groupSize, subGrid, blockSize, (seed.seed + 4.), apply * apply2);
swapBlocks(p, groupSize, subGrid, blockSize, (seed.seed + 5.), apply * apply2);
groupSize = vec2(1.2, .2) * scale;
subGrid = vec2(9,2);
blockSize = vec2(3,1);
seed = glitchSeed(glitchCoord(p, groupSize), speed);
apply = shouldApply(seed);
swapBlocks(p, groupSize, subGrid, blockSize, seed.seed, apply);
}
void glitchStatic(inout vec2 p) {
staticNoise(p, vec2(.5, .25/2.) * glitchScale, .2 * glitchScale, 2.);
}
void glitchTime(vec2 p, inout float time) {
freezeTime(p, time, vec2(.5) * glitchScale, 2.);
}
vec4 effect (vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) {
time = iTime;
time /= 3.;
time = mod(time, 1.);
glitchSwap(texture_coords);
glitchTime(texture_coords, time);
glitchStatic(texture_coords);
return Texel(tex,texture_coords);
}
The decay of glitching is determined in GlitchSeed glitchSeed, where you can change float prob. Default is 1, which should land it approximately in a middle of a processed texture. You can move intensity center elsewhere, for example 1-p.y moves it to top, p.x moves it to right.
Who is online
Users browsing this forum: Ahrefs [Bot], Bing [Bot], Google [Bot] and 12 guests