float rand(float seed) {
    return fract(sin(seed) * 43758.5453123);
}

float rand(vec2 seed){
    return fract(sin(dot(seed.xy, vec2(12.9898, 78.233))) * 43758.5453123);
}

float rand(vec3 seed) {
    return fract(sin(dot(seed, vec3(12.9898, 78.233, 45.164))) * 43758.5453123);
}

vec2 rand2(vec3 seed) {
    vec3 dot_product = vec3(dot(seed, vec3(12.9898,78.233,45.164)),
                            dot(seed, vec3(39.346,11.135,83.157)),
                            dot(seed, vec3(73.156,52.235,12.365)));
    return fract(sin(dot_product) * 43758.5453).xy;
}

vec3 rand3(float seed) {
    float scaledSeed = seed / 1000000.0;
    float x = rand(scaledSeed);
    float y = rand(scaledSeed + 1.0);
    float z = rand(scaledSeed + 2.0);
    return vec3(x, y, z);
}

vec4 rand4(float seed) {
    float scaledSeed = seed / 1000000.0;
    float x = rand(scaledSeed);
    float y = rand(scaledSeed + 1.0);
    float z = rand(scaledSeed + 2.0);
    float w = rand(scaledSeed + 3.0);
    return vec4(x, y, z, w);
}

vec3 rand3(vec2 seed) {
    // Generate pseudorandom numbers for x, y, z using slightly varied dot products
    float x = fract(sin(dot(seed, vec2(12.9898, 78.233))) * 43758.5453);
    float y = fract(sin(dot(seed, vec2(39.346, 11.135))) * 43758.5453);
    float z = fract(sin(dot(seed, vec2(73.156, 52.235))) * 43758.5453);

    // Return the random 3D vector
    return vec3(x, y, z);
}

vec3 rand3(int seed) {
    float s = float(seed);
    return vec3(
        fract(sin(s * 12.9898) * 43758.5453),
        fract(sin(s * 78.233) * 43758.5453),
        fract(sin(s * 39.346) * 43758.5453)
    );
}


vec3 rand3(vec3 seed) {
    float j = fract(sin(dot(seed, vec3(17.0, 59.4, 15.0))) * 43758.5453);
    return fract(vec3(1.0, 57.0, 113.0) * j);
}

vec4 rand4(vec4 seed) {
    float j = fract(sin(dot(seed, vec4(17.0, 59.4, 15.0, 33.1))) * 43758.5453);
    return fract(vec4(1.0, 57.0, 113.0, 209.0) * j);
}







uint hash(uint x) {
    x ^= x >> 16;
    x *= 0x7feb352d;
    x ^= x >> 15;
    x *= 0x846ca68b;
    x ^= x >> 16;
    return x;
}

float hashf(uint x) {
    return float(hash(x)) / float(0xffffffffU);
}

float irand(int id) {
    uint uid = uint(id);
    float x = hashf(uid);
    return x;
}

vec2 irand2(int id) {
    uint uid = uint(id);
    float x = hashf(uid);
    float y = hashf(uid + 1u);
    return vec2(x, y);
}

vec3 irand3(int id) {
    uint uid = uint(id);
    float x = hashf(uid);
    float y = hashf(uid + 1u);
    float z = hashf(uid + 2u);
    return vec3(x, y, z);
}

vec4 irand4(int id) {
    uint uid = uint(id);
    float x = hashf(uid);
    float y = hashf(uid + 1u);
    float z = hashf(uid + 2u);
    float w = hashf(uid + 3u);
    return vec4(x, y, z, w);
}