/*
====================================================================
  SXGG: Realis — Shader ultra-realistica per Minecraft
  Autore : Samax.GG
  File   : lib/noise.glsl
  Scopo  : Rumore procedurale 2D/3D (hash, value noise, FBM).
           Usato da: vento (M6), onde acqua (M3), nuvole/nebbia (M4).
====================================================================
*/

#ifndef NOISE_GLSL
#define NOISE_GLSL

// --- Hash veloci e stabili (senza texture) ---
float hash11(float p) {
    p = fract(p * 0.1031);
    p *= p + 33.33;
    return fract(p * (p + p));
}

float hash12(vec2 p) {
    vec3 p3 = fract(vec3(p.xyx) * 0.1031);
    p3 += dot(p3, p3.yzx + 33.33);
    return fract((p3.x + p3.y) * p3.z);
}

float hash13(vec3 p3) {
    p3 = fract(p3 * 0.1031);
    p3 += dot(p3, p3.zyx + 31.32);
    return fract((p3.x + p3.y) * p3.z);
}

// --- Value noise 2D ---
float valueNoise2D(vec2 p) {
    vec2 i = floor(p);
    vec2 f = fract(p);
    f = f * f * (3.0 - 2.0 * f);

    float a = hash12(i);
    float b = hash12(i + vec2(1.0, 0.0));
    float c = hash12(i + vec2(0.0, 1.0));
    float d = hash12(i + vec2(1.0, 1.0));

    return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
}

// --- Value noise 3D (nuvole volumetriche) ---
float valueNoise3D(vec3 p) {
    vec3 i = floor(p);
    vec3 f = fract(p);
    f = f * f * (3.0 - 2.0 * f);

    float n000 = hash13(i);
    float n100 = hash13(i + vec3(1.0, 0.0, 0.0));
    float n010 = hash13(i + vec3(0.0, 1.0, 0.0));
    float n110 = hash13(i + vec3(1.0, 1.0, 0.0));
    float n001 = hash13(i + vec3(0.0, 0.0, 1.0));
    float n101 = hash13(i + vec3(1.0, 0.0, 1.0));
    float n011 = hash13(i + vec3(0.0, 1.0, 1.0));
    float n111 = hash13(i + vec3(1.0, 1.0, 1.0));

    return mix(mix(mix(n000, n100, f.x), mix(n010, n110, f.x), f.y),
               mix(mix(n001, n101, f.x), mix(n011, n111, f.x), f.y), f.z);
}

// --- FBM 2D: 3 ottave ---
float fbm2D(vec2 p) {
    float value = 0.0;
    float amp   = 0.5;
    for (int i = 0; i < 3; i++) {
        value += amp * valueNoise2D(p);
        p     *= 2.03;
        amp   *= 0.5;
    }
    return value;
}

// --- FBM 2D esteso: 5 ottave (onde acqua, nuvole 2D) ---
float fbm2D5(vec2 p) {
    float value = 0.0;
    float amp   = 0.5;
    for (int i = 0; i < 5; i++) {
        value += amp * valueNoise2D(p);
        p     *= 2.07;
        amp   *= 0.5;
    }
    return value;
}

// --- FBM 3D: 4 ottave (nuvole volumetriche) ---
float fbm3D(vec3 p) {
    float value = 0.0;
    float amp   = 0.5;
    for (int i = 0; i < 4; i++) {
        value += amp * valueNoise3D(p);
        p     *= 2.02;
        amp   *= 0.5;
    }
    return value;
}

#endif // NOISE_GLSL
