#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(); }