#version 330 core
layout (points) in; // Input vertices are points
layout (points, max_vertices = 3) out; // Output 3 points (R, G, B bin index)

in VS_OUT {
    vec3 linearColor;
} gs_in[]; // Input from Vertex Shader (array size 1 for points)

// Output variable captured by Transform Feedback
// MUST match the name used in glTransformFeedbackVaryings
out float tf_BinIndex; // Using float for simplicity, will cast later

// Helper to convert linear float to 0-255 bin index (gamma corrected)
uint linearToVisualBin(float linearVal) {
    float clampedVal = clamp(linearVal, 0.0, 1.0);
    float displayApprox = pow(clampedVal, 1.0/2.2);
    return uint(displayApprox * 255.999);
}

void main() {
    // Check if the input vertex is valid (from VS boundary check)
    if (gs_in[0].linearColor.r < 0.0) {
        return; // Skip invalid pixels
    }

    vec3 color = gs_in[0].linearColor;

    // Calculate bins
    uint rBin = linearToVisualBin(color.r);
    uint gBin = linearToVisualBin(color.g);
    uint bBin = linearToVisualBin(color.b);

    // Emit vertex for Red channel bin
    tf_BinIndex = float(rBin); // Output bin index (0-255)
    EmitVertex();
    EndPrimitive(); // End point primitive

    // Emit vertex for Green channel bin
    tf_BinIndex = float(gBin + 256u); // Output bin index (256-511)
    EmitVertex();
    EndPrimitive();

    // Emit vertex for Blue channel bin
    tf_BinIndex = float(bBin + 512u); // Output bin index (512-767)
    EmitVertex();
    EndPrimitive();
}