//============================================================================//
// 🌟 SCREEN-SPACE VOLUMETRIC GLOW
// Для твоего кастомного шейдера (без VXGI)
// Чистый screen-space подход как в SDV
//============================================================================//

#ifndef VOLUMETRIC_GLOW_GLSL
#define VOLUMETRIC_GLOW_GLSL

//============================================================================//
// НАСТРОЙКИ
//============================================================================//

#define GLOW_ENABLED 1              // [0 1] Включить эффект
#define GLOW_SAMPLES 16             // [8 12 16 24 32] Количество сэмплов
#define GLOW_RADIUS 0.12            // [0.05 0.08 0.12 0.15 0.2] Радиус в screen-space
#define GLOW_INTENSITY 2.5          // [1.0 1.5 2.0 2.5 3.0 4.0] Яркость
#define GLOW_FALLOFF 2.0            // [1.0 1.5 2.0 2.5 3.0] Скорость затухания
#define GLOW_BLOOM 1.5              // [0.5 1.0 1.5 2.0 2.5] Сила bloom
#define GLOW_NOISE 0.15             // [0.0 0.1 0.15 0.2 0.3] Grain overlay

//============================================================================//
// UTILITY FUNCTIONS
//============================================================================//

// Vogel disk sampling (равномерное распределение точек)
vec2 VogelDiskSample(int sampleIndex, int samplesCount, float phi) {
    const float goldenAngle = 2.4;
    
    float r = sqrt(float(sampleIndex) + 0.5) / sqrt(float(samplesCount));
    float theta = float(sampleIndex) * goldenAngle + phi;
    
    return vec2(r * cos(theta), r * sin(theta));
}

// 2D noise для volumetric эффекта
float Noise2D(vec2 p) {
    vec2 i = floor(p);
    vec2 f = fract(p);
    f = curve(f); // Используем твою curve функцию из Common.inc
    
    float a = fract(sin(dot(i, vec2(12.9898, 78.233))) * 43758.5453);
    float b = fract(sin(dot(i + vec2(1.0, 0.0), vec2(12.9898, 78.233))) * 43758.5453);
    float c = fract(sin(dot(i + vec2(0.0, 1.0), vec2(12.9898, 78.233))) * 43758.5453);
    float d = fract(sin(dot(i + vec2(1.0, 1.0), vec2(12.9898, 78.233))) * 43758.5453);
    
    return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
}

// Volumetric noise с анимацией
float VolumetricNoise(vec3 pos, float time) {
    pos.x += time * 0.05;
    pos.z += time * 0.03;
    
    float n = 0.0;
    float amplitude = 1.0;
    float frequency = 1.0;
    
    for(int i = 0; i < 3; i++) {
        n += Noise2D(pos.xy * frequency + pos.z) * amplitude;
        frequency *= 2.0;
        amplitude *= 0.5;
    }
    
    return n;
}

//============================================================================//
// EMISSIVE BLOCK DETECTION
//============================================================================//

// Проверяет, является ли блок светящимся
bool IsEmissiveBlock(vec3 color) {
    float brightness = maxOf(color);
    float saturation = brightness - minOf(color);
    
    // Светящиеся блоки: яркие (>0.5) и насыщенные
    return brightness > 0.5 && (saturation > 0.2 || brightness > 0.8);
}

// Получает emission цвет с усилением
vec3 GetEmissionColor(vec3 blockColor) {
    float brightness = maxOf(blockColor);
    vec3 emission = blockColor;
    
    // Redstone (красный)
    if(blockColor.r > 0.7 && blockColor.g < 0.3 && blockColor.b < 0.3) {
        emission = vec3(1.0, 0.1, 0.0) * 1.5;
    }
    // Glowstone/Lantern (тёплый жёлтый)
    else if(blockColor.r > 0.7 && blockColor.g > 0.6 && blockColor.b < 0.5) {
        emission = vec3(1.0, 0.85, 0.5) * 1.3;
    }
    // Sea Lantern (холодный бирюзовый)
    else if(blockColor.g > 0.7 && blockColor.b > 0.6 && blockColor.r < 0.5) {
        emission = vec3(0.3, 1.0, 0.9) * 1.3;
    }
    // Soul (синий)
    else if(blockColor.b > 0.7 && blockColor.r < 0.4 && blockColor.g < 0.5) {
        emission = vec3(0.2, 0.4, 1.0) * 1.4;
    }
    // End Rod / яркие блоки
    else if(brightness > 0.8) {
        emission = blockColor * 1.5;
    }
    else {
        emission = blockColor * 1.2;
    }
    
    return emission;
}

//============================================================================//
// MAIN VOLUMETRIC GLOW FUNCTION
//============================================================================//

vec3 GetVolumetricGlow(
    vec2 texCoord,
    float depth,
    vec3 viewPos,
    sampler2D colorTex,     // colortex2 или другой albedo buffer
    sampler2D depthTex,     // depthtex0
    int frameCount          // frameCounter для анимации и dithering
) {
    #if GLOW_ENABLED == 0
        return vec3(0.0);
    #endif
    
    // Пропускаем небо
    if(depth >= 1.0) return vec3(0.0);
    
    vec3 glowAccum = vec3(0.0);
    float weightSum = 0.0;
    
    // Temporal rotation для устранения banding
    float temporalRotation = InterleavedGradientNoise(texCoord * vec2(viewWidth, viewHeight));
    temporalRotation = fract(temporalRotation + float(frameCount) * 0.618);
    
    // Depth-aware radius
    float linearDepth = length(viewPos);
    float radiusScale = mix(0.5, 2.0, saturate(linearDepth / 64.0));
    float glowRadius = GLOW_RADIUS * radiusScale;
    
    //========================================================================//
    // SCREEN-SPACE RAY MARCHING
    //========================================================================//
    
    for(int i = 0; i < GLOW_SAMPLES; i++) {
        // Vogel disk sampling
        vec2 offset = VogelDiskSample(i, GLOW_SAMPLES, temporalRotation * TAU);
        offset *= glowRadius;
        
        vec2 sampleCoord = texCoord + offset;
        
        // Bounds check
        if(sampleCoord != saturate(sampleCoord)) continue;
        
        // Sample depth
        float sampleDepth = texture(depthTex, sampleCoord).x;
        if(sampleDepth >= 1.0) continue;
        
        // Sample color
        vec3 sampleColor = texture(colorTex, sampleCoord).rgb;
        
        // Check if emissive
        if(!IsEmissiveBlock(sampleColor)) continue;
        
        // Get emission
        vec3 emissionColor = GetEmissionColor(sampleColor);
        
        //====================================================================//
        // VOLUMETRIC SCATTERING
        //====================================================================//
        
        // Screen-space distance
        float distance = length(offset);
        
        // Depth-aware weight
        float depthDiff = abs(sampleDepth - depth);
        float depthWeight = exp(-depthDiff * 10.0);
        
        // Основное затухание
        float falloff = 1.0 / (1.0 + pow(distance / glowRadius, GLOW_FALLOFF));
        
        // Volumetric noise (создаёт "лучи" света)
        vec3 worldOffset = vec3(offset * 100.0, linearDepth);
        float volumeNoise = VolumetricNoise(worldOffset, float(frameCount) * 0.05);
        float noiseMod = mix(0.5, 1.0, volumeNoise);
        
        // Bloom factor
        float bloomFactor = pow(maxOf(emissionColor), GLOW_BLOOM);
        
        // Итоговый вес
        float weight = falloff * depthWeight * noiseMod * bloomFactor;
        
        // Accumulate
        glowAccum += emissionColor * weight;
        weightSum += weight;
    }
    
    //========================================================================//
    // FINALIZATION
    //========================================================================//
    
    // Normalize
    if(weightSum > 0.001) {
        glowAccum /= weightSum;
    }
    
    // Grain overlay (PTGI signature)
    float grain = InterleavedGradientNoise(texCoord * vec2(viewWidth, viewHeight) * 1.5);
    grain = fract(grain + float(frameCount) * 0.754);
    grain = mix(1.0, grain, GLOW_NOISE);
    glowAccum *= grain;
    
    // Apply intensity
    glowAccum *= GLOW_INTENSITY;
    
    // Soft clamp
    glowAccum = glowAccum / (1.0 + glowAccum * 0.2);
    
    return max(glowAccum, vec3(0.0));
}

//============================================================================//
// SIMPLIFIED VERSION (для быстрого теста)
//============================================================================//

vec3 GetVolumetricGlowSimple(
    vec2 texCoord,
    sampler2D colorTex,
    int frameCount
) {
    vec3 glow = vec3(0.0);
    
    const int samples = 8;
    float radius = 0.05;
    
    for(int i = 0; i < samples; i++) {
        float angle = float(i) / float(samples) * TAU;
        vec2 offset = vec2(cos(angle), sin(angle)) * radius;
        
        vec3 sampleColor = texture(colorTex, texCoord + offset).rgb;
        
        if(IsEmissiveBlock(sampleColor)) {
            glow += GetEmissionColor(sampleColor) / float(samples);
        }
    }
    
    return glow * GLOW_INTENSITY;
}

#endif // VOLUMETRIC_GLOW_GLSL
