#version 450

layout(set = 0, binding = 0) uniform sampler2D tex;

layout(location = 0) in vec2  frag_uv;
layout(location = 1) in vec4  frag_col;
layout(location = 2) in vec2  frag_rect_min;
layout(location = 3) in vec2  frag_rect_max;
layout(location = 4) in vec4  frag_corner_radii;
layout(location = 5) in float frag_border_thickness;
layout(location = 6) in float frag_softness;
layout(location = 7) in float frag_mode;
layout(location = 8) in vec2  frag_pixel_pos;

layout(location = 0) out vec4 out_color;

float rounded_rect_sdf(vec2 sample_pos, vec2 rect_center, vec2 rect_half_size, float radius) {
    vec2 d = abs(sample_pos - rect_center) - rect_half_size + vec2(radius, radius);
    return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0) - radius;
}

void main() {
    vec4 col = frag_col;

    if (frag_mode > 1.5) {
        // RGBA textured mode: sample all channels, multiply by vertex color
        vec4 tex_sample = texture(tex, frag_uv);
        col *= tex_sample;
    } else if (frag_mode > 0.5) {
        // Alpha-only textured mode: sample R channel as alpha (font atlas)
        float alpha = texture(tex, frag_uv).r;
        col.a *= alpha;
    } else {
        // SDF rounded rect mode
        vec2 pixel_pos = frag_pixel_pos;
        vec2 rect_center = (frag_rect_min + frag_rect_max) * 0.5;
        vec2 rect_half_size = (frag_rect_max - frag_rect_min) * 0.5;
        // corner_radii = (TL, TR, BR, BL) - select radius by quadrant
        float radius = (pixel_pos.x < rect_center.x)
            ? ((pixel_pos.y < rect_center.y) ? frag_corner_radii.x : frag_corner_radii.w)
            : ((pixel_pos.y < rect_center.y) ? frag_corner_radii.y : frag_corner_radii.z);
        float softness = max(frag_softness, 0.5);
        float dist = rounded_rect_sdf(pixel_pos, rect_center, rect_half_size, radius);

        if (frag_border_thickness > 0) {
            float inner_dist = dist + frag_border_thickness;
            float outer_alpha = 1.0 - smoothstep(-softness, softness, dist);
            float inner_alpha = smoothstep(-softness, softness, inner_dist);
            col.a *= outer_alpha * inner_alpha;
        } else {
            col.a *= 1.0 - smoothstep(-softness, softness, dist);
        }
    }

    // Dither to reduce gradient banding (interleaved gradient noise)
    float dither = fract(52.9829189 * fract(dot(frag_pixel_pos, vec2(0.06711056, 0.00583715)))) - 0.5;
    col.rgb += dither / 255.0;

    if (col.a < 0.002) discard;
    out_color = col;
}
