#define MOD3 vec3(443.8975, 397.2973, 491.1871)

float hash12(vec2 p)
{
    vec3 p3 = fract(vec3(p.xyx) * MOD3);
    p3 += dot(p3, p3.yzx + 19.19);
    // p3 += frameCounter;

    return fract((p3.x + p3.y) * p3.z);
}
float blueNoise(vec2 coord)
{
    return fract(texelFetch2D(noisetex, ivec2(coord.xy) % 512, 0).a + 1.0 / 1.6180339887 * frameCounter);
}
float blueNoise3(vec2 coord)
{
    return fract(texelFetch2D(noisetex, ivec2(coord.xy) % 512, 0).a + 1.0 / 1.6180339887 * frameCounter * 0.05);
}

float R2_dither_slow(vec2 coord)
{
    vec2 alpha = vec2(0.75487765, 0.56984026);
    return fract(alpha.x * coord.x + alpha.y * coord.y + 1.0 / 1.6180339887 * frameCounter * 0.001);
}
float R2_dither_slow2(vec2 coord)
{
    vec2 alpha = vec2(0.75487765, 0.56984026);
    return fract(alpha.x * coord.x + alpha.y * coord.y + 1.0 / 1.6180339887 * frameCounter * 0.1);
}
float R2_dither(vec2 coord)
{
    vec2 alpha = vec2(0.75487765, 0.56984026);
    return fract(alpha.x * coord.x + alpha.y * coord.y + 1.0 / 1.6180339887 * frameCounter);
}

float R2_dither(int iteration, vec2 coord)
{
    return fract(0.75487765 * coord.x + 0.56984026 * coord.y +
                 1.0 / 1.6180339887 * (float(iteration * 0.5) + (frameCounter)));
}

float InterleavedGradientNoise(vec2 uv)
{
    const vec3 magic = vec3(0.06711056, 0.00583715, 52.9829189);
    return fract(magic.z * fract(dot(uv, magic.xy)));
}
float InterleavedGradientNoise2(vec2 uv)
{
    uv += frameCounter;
    const vec3 magic = vec3(0.06711056, 0.00583715, 52.9829189);
    return fract(magic.z * fract(dot(uv, magic.xy)));
}

vec2 R2_samples3(int n)
{
    vec2 alpha = vec2(0.75487765, 0.56984026);
    return fract(alpha * n);
}
vec4 blueNoise4(vec2 coord)
{
    return fract(texelFetch2D(noisetex, ivec2(coord) % 512, 0) + 1.0 / 1.6180339887 * frameCounter);
}

float noise_standard(vec2 coord)
{
#ifdef HQ_NOISE
    return blueNoise(coord);
#else
    return R2_dither(coord);
#endif
}
float noise_standard_alt(vec2 coord)
{
#ifdef HQ_NOISE
    return blueNoise(coord);
#else
    return R2_dither_slow(coord);
#endif
}
vec3 Dither_Vlachos(vec3 rgba, float levels, vec2 pos)
{
    // Vlachos 2016, "Advanced VR Rendering"
    vec3 noise = vec3(dot(vec2(171.0, 231.0), pos));
    noise = fract(noise / vec3(103.0, 71.0, 97.0));
    noise = noise - 0.5;
    return vec3(rgba.rgb + (noise / (levels - 1.0)));
}