// bloom_frag.msl.h - Metal Shading Language del fragment shader del bloom
// © 2026 JailDesigner
//
// IMPORTANT: mantenir sincronitzat a mà amb shaders/bloom.frag.glsl. SDL3 GPU
// compila aquest string MSL en runtime; qualsevol canvi al GLSL o al struct
// BloomUniforms (gpu_bloom_pipeline.hpp) cal replicar-lo aquí al mateix commit.
//
// Pass 1D del bloom separable: high-pass + gaussiana en una direcció.
// Recursos:
//   - texture2d<float> src [[texture(0)]] + sampler [[sampler(0)]]
//   - constant BloomUBO& ubo [[buffer(0)]]

#pragma once
#ifdef __APPLE__

namespace Rendering::GPU::Msl {

    inline constexpr const char* BLOOM_FRAG_MSL = R"(
#include <metal_stdlib>
using namespace metal;

struct PostVOut {
    float4 pos [[position]];
    float2 uv;
};

struct BloomUBO {
    float2 texel_size;
    float2 direction;
    float threshold;
    float extract;
    float sigma;
    float pad_a;
};

fragment float4 bloom_fs(PostVOut in [[stage_in]],
                         texture2d<float> src [[texture(0)]],
                         sampler          samp [[sampler(0)]],
                         constant BloomUBO& ubo [[buffer(0)]]) {
    float3 sum = float3(0.0);
    float total_weight = 0.0;

    constexpr int RADIUS = 7;
    constexpr float TWO_SIGMA_SQ_FACTOR = 2.0;

    for (int i = -RADIUS; i <= RADIUS; ++i) {
        float2 offset = ubo.direction * float(i) * ubo.texel_size;
        float3 c = src.sample(samp, in.uv + offset).rgb;

        if (ubo.extract > 0.5) {
            float luma = max(c.r, max(c.g, c.b));
            float high_pass = max(0.0, luma - ubo.threshold);
            c *= high_pass;
        }

        float fi = float(i);
        float w = exp(-(fi * fi) / (TWO_SIGMA_SQ_FACTOR * ubo.sigma * ubo.sigma));
        sum += c * w;
        total_weight += w;
    }

    if (total_weight > 0.0) {
        sum /= total_weight;
    }

    return float4(sum, 1.0);
}
)";

}  // namespace Rendering::GPU::Msl

#endif  // __APPLE__
