I am trying to emulate this effect on Godot. What I have until now is something that looks like this
shader_type canvas_item;
const float DELTA = 0.00001;
const float TAU = 6.28318530718;
const float NOISE_TEXTURE_SIZE = 256.0;
const float NOISE_TEXTURE_PIXEL_COUNT = (NOISE_TEXTURE_SIZE * NOISE_TEXTURE_SIZE);
//uniform vec4 vColor: color_white;
// MAIN CONTROLLER UNIFORMS
uniform float intensity = 1.; // overall effect intensity, 0-1 (no upper limit)
uniform float rngSeed = .0; // seed offset (changes configuration around)
uniform sampler2D noiseTexture; // noise texture sampler
//TUNING
uniform float lineSpeed = .01; // line speed
uniform float lineDrift = .1; // horizontal line drifting
uniform float lineResolution = 1.; // line resolution
uniform float lineVertShift = .0; // wave phase offset of horizontal lines
uniform float lineShift = .004; // horizontal shift
uniform float jumbleness = .2; // amount of "block" glitchiness
uniform float jumbleResolution = .2; // resolution of blocks
uniform float jumbleShift = .15; // texture shift by blocks
uniform float jumbleSpeed = 1.; // speed of block variation
uniform float dispersion = .0025; // color channel horizontal dispersion
uniform float channelShift = .004; // horizontal RGB shift
uniform float noiseLevel = .5; // level of noise
uniform float shakiness = .5; // horizontal shakiness
//
float rand(vec2 co){
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
vec4 extractRed(vec4 col){
return vec4(col.r, 0., 0., col.a);
}
vec4 extractGreen(vec4 col){
return vec4(0., col.g, 0., col.a);
}
vec4 extractBlue(vec4 col){
return vec4(0., 0., col.b, col.a);
}
// Replacement for the mirror address mode, hopefully nobody needs filtering.
vec2 mirror(vec2 v) {
return abs((fract((v * 0.5) + 0.5) * 2.0) - 1.0);
}
vec2 downsample(vec2 v, vec2 res) {
// Division by zero protected by uniform getters.
return floor(v * res) / res;
}
// Fetches four random values from an RGBA noise texture
vec4 whiteNoise(vec2 coord, vec2 texelOffset, vec2 resolution) {
vec2 offset = downsample(vec2(rngSeed * NOISE_TEXTURE_SIZE, rngSeed) + texelOffset, vec2(NOISE_TEXTURE_SIZE));
vec2 ratio = resolution / vec2(NOISE_TEXTURE_SIZE);
return texture(noiseTexture, (coord * ratio) + offset);
}
// Fetch noise texture texel based on single offset in the [0-1] range
vec4 random(float dataOffset) {
vec2 halfTexelSize = vec2((0.5 / NOISE_TEXTURE_SIZE));
float offset = rngSeed + dataOffset;
return texture(noiseTexture, vec2(offset * NOISE_TEXTURE_SIZE, offset) + halfTexelSize);
}
// Jumble coord generation
vec2 jumble(vec2 coord, float time, vec2 resolution){
// Static branch.
if ((jumbleShift * jumbleness * jumbleResolution) < DELTA) {
return vec2(0.0);
}
vec2 gridCoords = (coord * jumbleResolution) / (NOISE_TEXTURE_SIZE * 0.0245);
float jumbleTime = mod(floor(time * 0.02 * jumbleSpeed), NOISE_TEXTURE_PIXEL_COUNT);
vec2 offset = random(jumbleTime / NOISE_TEXTURE_PIXEL_COUNT).ga * jumbleResolution;
vec4 cellRandomValues = whiteNoise(gridCoords, vec2(jumbleResolution * -10.0) + offset, resolution);
return (cellRandomValues.ra - 0.5) * jumbleShift * floor(min(0.99999, cellRandomValues.b) + jumbleness);
}
// Horizontal line offset generation
float lineOffset(vec2 coord, vec2 uv, float time, vec2 resolution) {
// Static branch.
if (lineShift < DELTA) {
return 0.0;
}
// Wave offsets
vec2 waveHeights = vec2(50.0 * lineResolution, 25.0 * lineResolution);
vec4 lineRandom = whiteNoise(downsample(uv.yy, waveHeights), vec2(0.0), resolution);
float driftTime = uv.y * resolution.y * 2.778;
// XY: big waves, ZW: drift waves
vec4 waveTimes = (vec4(downsample(lineRandom.ra * TAU, waveHeights) * 80.0, driftTime + 2.0, (driftTime * 0.1) + 1.0) + (time * lineSpeed)) + (lineVertShift * TAU);
vec4 waveLineOffsets = vec4(sin(waveTimes.x), cos(waveTimes.y), sin(waveTimes.z), cos(waveTimes.w));
waveLineOffsets.xy *= ((whiteNoise(waveTimes.xy, vec2(0.0), resolution).gb - 0.5) * shakiness) + 1.0;
waveLineOffsets.zw *= lineDrift;
return dot(waveLineOffsets, vec4(1.0));
}
void fragment()
{
vec3 randomValues = vec3(rand(vec2(TIME, 0.0)), rand(vec2(TIME, 0.0)), rand(vec2(TIME, 0.0)));
vec2 resolution = 1.0 / SCREEN_PIXEL_SIZE;
vec2 uv = FRAGCOORD.xy / (1.0 / SCREEN_PIXEL_SIZE).xy;
// Sample random high-frequency noise
vec4 randomHiFreq = whiteNoise(uv, randomValues.xy, resolution);
// Apply line offsets
vec2 offsetCoords = uv;
offsetCoords.x += ((((2.0 * randomValues.z) - 1.0) * shakiness * lineSpeed) + lineOffset(offsetCoords, uv, TIME, resolution)) * lineShift * intensity;
// Apply jumbles
offsetCoords += jumble(offsetCoords, TIME, resolution) * intensity * intensity * 0.25;
// Channel split
vec2 shiftFactors = (channelShift + (randomHiFreq.rg * dispersion)) * intensity;
vec4 outColour;
// Static branch.
if (((channelShift + dispersion) * intensity) < DELTA) {
outColour = texture(SCREEN_TEXTURE, mirror(offsetCoords));
} else {
outColour = extractRed(texture(SCREEN_TEXTURE, mirror(offsetCoords + vec2(shiftFactors.r, 0.0)))) + extractBlue(texture(SCREEN_TEXTURE, mirror(offsetCoords + vec2(-shiftFactors.g, 0.0)))) + extractGreen(texture(SCREEN_TEXTURE, mirror(offsetCoords)));
}
// Add noise
outColour.rgb *= (vec3(.55, .5, .4) * randomHiFreq.gab * intensity * noiseLevel) + 1.0;
// COLOR = vColor * outColour;
COLOR = outColour;
}
The result looks something like this:
Can someone identify what is wrong with this Shader?