I need help fixing this Shader

greenleafone7greenleafone7 Posts: 4Member

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?

Answers

  • MegalomaniakMegalomaniak Posts: 3,566Admin

    I can't be certain but, colors out of gamut maybe? Don't forget that you are working within godots color management and the HDR pipeline.

  • greenleafone7greenleafone7 Posts: 4Member

    I will have a look at that. But colour is the least of this shader's problems. The original version has a nice organic feel and every uniform has a clear and pleasant effect. My version seems to be static over time for some reason.

Leave a Comment

BoldItalicStrikethroughOrdered listUnordered list
Emoji
Image
Align leftAlign centerAlign rightToggle HTML viewToggle full pageToggle lights
Drop image/file