Skip to content

Commit

Permalink
Working analog glitch effect. (#40)
Browse files Browse the repository at this point in the history
  • Loading branch information
FiniteSingularity authored Jun 20, 2024
1 parent 55929d7 commit 03190c1
Show file tree
Hide file tree
Showing 8 changed files with 780 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ target_sources(${PROJECT_NAME} PRIVATE
src/blur/blur.h
src/blur/gaussian-kernel.c
src/blur/gaussian-kernel.h
src/filters/analog-glitch.c
src/filters/analog-glitch.h
src/filters/bloom-f.c
src/filters/bloom-f.h
src/filters/cathode-boot.c
Expand Down
19 changes: 19 additions & 0 deletions data/locale/en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,22 @@ RetroEffects.DigitalGlitch.MinRGBHeight="Min Height"
RetroEffects.DigitalGlitch.MaxRGBHeight="Max Height"
RetroEffects.DigitalGlitch.MinRGBInterval="Min Interval"
RetroEffects.DigitalGlitch.MaxRGBInterval="Max Interval"
RetroEffects.AnalogGlitch="Analog Glitch"
RetroEffects.AnalogGlitch.Primary="Primary Wave"
RetroEffects.AnalogGlitch.Primary.Speed="Speed"
RetroEffects.AnalogGlitch.Primary.Scale="Scale"
RetroEffects.AnalogGlitch.Primary.Threshold="Threshold"
RetroEffects.AnalogGlitch.Secondary="Secondary Wave"
RetroEffects.AnalogGlitch.Secondary.Speed="Speed"
RetroEffects.AnalogGlitch.Secondary.Scale="Scale"
RetroEffects.AnalogGlitch.Secondary.Threshold="Threshold"
RetroEffects.AnalogGlitch.Secondary.Influence="Influence"
RetroEffects.AnalogGlitch.MaximumDisplacement="Max Displacement"
RetroEffects.AnalogGlitch.Interference="Interference"
RetroEffects.AnalogGlitch.Interference.Magnitude="Interference Magnitude"
RetroEffects.AnalogGlitch.Interference.AffectsAlpha="Alpha Channel?"
RetroEffects.AnalogGlitch.Line.Magnitude="Line Magnitude"
RetroEffects.AnalogGlitch.CA="Color Drift"
RetroEffects.AnalogGlitch.CA.MaxDisp="Maximum Distance"
RetroEffects.AnalogGlitch.DeSat="Desaturation"
RetroEffects.AnalogGlitch.DeSat.Amount="Amount"
104 changes: 104 additions & 0 deletions data/shaders/analog-glitch.effect
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Based off of ShaderToy "Video Glitch" by dyvoid.
// https://www.shadertoy.com/view/XtK3W3
// Converted to HLSL, added user changable parameters,
// And added CA effect by Finite Singularity.

uniform float4x4 ViewProj;
uniform texture2d image;
uniform float2 uv_size;
uniform float time;

uniform float speed_primary; //= 2.0;
uniform float speed_secondary; // = 5.0;
uniform float scale_primary; // = 800.0;
uniform float scale_secondary; // = 128.0;

uniform float threshold_primary; // = 0.3;
uniform float threshold_secondary; // = 0.7;
uniform float secondary_influence; // = 0.15;

uniform float max_disp; // = 250.0;
uniform float interference_mag; // = 0.3;
uniform float line_mag; // = 0.15;
uniform float interference_alpha;

uniform float desaturation_amount;
uniform float color_drift;

#include "noise-functions.effect"

sampler_state textureSampler{
Filter = Linear;
AddressU = Clamp;
AddressV = Clamp;
MinLOD = 0;
MaxLOD = 0;
};

struct VertData
{
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};

VertData mainTransform(VertData v_in)
{
v_in.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj);
return v_in;
}

// Sample with desaturation
float4 sampleDesaturatedTexture(float2 xy, float desat)
{
// Desaturation Distortion
float4 col = image.Sample(textureSampler, xy / uv_size);
float lum = dot(col.rgb, float3(0.299, 0.587, 0.114));
col.rgb = lerp(col.rgb, float3(lum, lum, lum), float3(desat, desat, desat));
return col;
}

float4 mainImage(VertData v_in) : TARGET
{
float2 coord = v_in.uv * uv_size;

float n_primary = open_simplex_1d(float2(time * speed_primary, coord.y), 0.0, float2(1.0, scale_primary));
float n_secondary = open_simplex_1d(float2(time * speed_secondary, coord.y), 0.0, float2(1.0, scale_secondary));

n_primary = max(0.0, (n_primary - threshold_primary)) / (1.0 - threshold_primary);
n_primary += n_secondary * secondary_influence;
n_primary /= (1.0 + secondary_influence);

coord.x = coord.x - max_disp * n_primary * n_primary;

// CA Distortion and Desaturation
float desat = n_primary * desaturation_amount;
float4 col_g = sampleDesaturatedTexture(coord, desat);
float4 col_r = sampleDesaturatedTexture(coord - float2(n_primary * color_drift, 0.0), desat);
float4 col_b = sampleDesaturatedTexture(coord + float2(n_primary * color_drift, 0.0), desat);

float4 col = float4(col_r.r, col_g.g, col_b.b, (col_r.a + col_g.a + col_b.a)*0.33334);

// Interference noise (lightening/darkening)
float n_interference = hash11(coord.y * time*5.0);
float inter = n_primary * interference_mag;
col.rgb = lerp(col.rgb, float3(n_interference, n_interference, n_interference), float3(inter, inter, inter));

// Static lines (correlated to primary displacement)
if (floor(fmod(coord.y * 0.25, 2.0)) < 0.001)
{
float intf = 1.0 - (line_mag * n_primary);
col.rgb *= intf;
col.a = col.a - (interference_alpha * (1.0 - intf));
}

return col;
}

technique Draw
{
pass
{
vertex_shader = mainTransform(v_in);
pixel_shader = mainImage(v_in);
}
}
161 changes: 161 additions & 0 deletions data/shaders/noise-functions.effect
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,164 @@ float2 whiteNoise2D(float2 pos, uint seed)
);
#endif
}

////////////////// K.jpg's Smooth Re-oriented 8-Point BCC Noise //////////////////
//////////////////// Output: float4(dF/dx, dF/dy, dF/dz, value) ////////////////////

// Borrowed from Stefan Gustavson's noise code

float4 permute(float4 t)
{
return t * (t * 34.0 + 133.0);
}

#ifndef OPENGL
float mod(float x, float y)
{
return x - y * floor(x / y);
}

float2 mod(float2 x, float2 y)
{
return x - y * floor(x / y);
}

float3 mod(float3 x, float3 y)
{
return x - y * floor(x / y);
}

float4 mod4(float4 x, float4 y)
{
return x - y * floor(x / y);
}
#endif

// Gradient set is a normalized expanded rhombic dodecahedron
float3 grad(float hash)
{
// Random vertex of a cube, +/- 1 each
float3 cube = mod(floor(hash / float3(1.0, 2.0, 4.0)), 2.0) * 2.0 - 1.0;

// Random edge of the three edges connected to that vertex
// Also a cuboctahedral vertex
// And corresponds to the face of its dual, the rhombic dodecahedron
float3 cuboct = cube;

int index = int(hash / 16.0);
if (index == 0)
cuboct.x = 0.0;
else if (index == 1)
cuboct.y = 0.0;
else
cuboct.z = 0.0;

// In a funky way, pick one of the four points on the rhombic face
float type = mod(floor(hash / 8.0), 2.0);
float3 rhomb = (1.0 - type) * cube + type * (cuboct + cross(cube, cuboct));

// Expand it so that the new edges are the same length
// as the existing ones
float3 grad = cuboct * 1.22474487139 + rhomb;

// To make all gradients the same length, we only need to shorten the
// second type of vector. We also put in the whole noise scale constant.
// The compiler should reduce it into the existing floats. I think.
grad *= (1.0 - 0.042942436724648037 * type) * 3.5946317686139184;

return grad;
}

// BCC lattice split up into 2 cube lattices
float4 openSimplex2SDerivativesPart(float3 X)
{
float3 b = floor(X);
float4 i4 = float4(X - b, 2.5);

// Pick between each pair of oppposite corners in the cube.
float3 v1 = b + floor(dot(i4, float4(.25, .25, .25, .25)));
float3 v2 = b + float3(1, 0, 0) + float3(-1, 1, 1) * floor(dot(i4, float4(-.25, .25, .25, .35)));
float3 v3 = b + float3(0, 1, 0) + float3(1, -1, 1) * floor(dot(i4, float4(.25, -.25, .25, .35)));
float3 v4 = b + float3(0, 0, 1) + float3(1, 1, -1) * floor(dot(i4, float4(.25, .25, -.25, .35)));

// Gradient hashes for the four vertices in this half-lattice.
float4 hashes = float4(
hash33(v1).x, hash33(v2).x, hash33(v3).x, hash33(v4).x
) * 47.0;


// Gradient extrapolations & kernel function
float3 d1 = X - v1;
float3 d2 = X - v2;
float3 d3 = X - v3;
float3 d4 = X - v4;
float4 a = max(float4(0.75, 0.75, 0.75, 0.75) - float4(dot(d1, d1), dot(d2, d2), dot(d3, d3), dot(d4, d4)), float4(0.0, 0.0, 0.0, 0.0));
float4 aa = a * a;
float4 aaaa = aa * aa;
float3 g1 = grad(hashes.x);
float3 g2 = grad(hashes.y);
float3 g3 = grad(hashes.z);
float3 g4 = grad(hashes.w);
float4 extrapolations = float4(dot(d1, g1), dot(d2, g2), dot(d3, g3), dot(d4, g4));

#ifndef OPENGL
float4x3 derivativeMatrix = { d1, d2, d3, d4 };
float4x3 gradientMatrix = { g1, g2, g3, g4 };

// Derivatives of the noise
float3 derivative = -8.0 * mul(aa * a * extrapolations, derivativeMatrix)
+ mul(aaaa, gradientMatrix);

#else
vec3 derivative = -8.0 * mat4x3(d1, d2, d3, d4) * (aa * a * extrapolations) + mat4x3(g1, g2, g3, g4) * aaaa;
#endif

// Return it all as a float4
return float4(derivative, dot(aaaa, extrapolations));
}

// Use this if you don't want Z to look different from X and Y
float4 openSimplex2SDerivatives_Conventional(float3 X)
{
X = dot(X, float3(2.0 / 3.0, 2.0 / 3.0, 2.0 / 3.0)) - X;

float4 result = openSimplex2SDerivativesPart(X) + openSimplex2SDerivativesPart(X + 144.5);

return float4(dot(result.xyz, float3(2.0 / 3.0, 2.0 / 3.0, 2.0 / 3.0)) - result.xyz, result.w);
}

// Use this if you want to show X and Y in a plane, then use Z for time, vertical, etc.
float4 openSimplex2SDerivatives_ImproveXY(float3 X)
{
#ifndef OPENGL
// Not a skew transform.
float3x3 orthonormalMap =
{
0.788675134594813, -0.211324865405187, -0.577350269189626,
-0.211324865405187, 0.788675134594813, -0.577350269189626,
0.577350269189626, 0.577350269189626, 0.577350269189626
};

X = mul(X, orthonormalMap);
float4 result = openSimplex2SDerivativesPart(X) + openSimplex2SDerivativesPart(X + 144.5);
return float4(mul(orthonormalMap, result.xyz), result.w);
#else
mat3 orthonormalMap = mat3(
0.788675134594813, -0.211324865405187, -0.577350269189626,
-0.211324865405187, 0.788675134594813, -0.577350269189626,
0.577350269189626, 0.577350269189626, 0.577350269189626);

X = orthonormalMap * X;
float4 result = openSimplex2SDerivativesPart(X) + openSimplex2SDerivativesPart(X + 144.5);

return vec4(result.xyz * orthonormalMap, result.w);
#endif
}

float open_simplex_1d(float2 coord, float t, float2 scale)
{
coord *= 1.0 / (scale);
float4 noise = openSimplex2SDerivatives_Conventional(float3(coord, t));
return noise.w;
//return noise.w * 0.5 + 0.5;
}
Loading

0 comments on commit 03190c1

Please sign in to comment.