test new histogram

This commit is contained in:
2025-04-08 18:00:07 -04:00
parent 7e7207a87e
commit a8155a2d85
5 changed files with 306 additions and 147 deletions

View File

@ -15,6 +15,19 @@ layout(std430, binding = 1) buffer HistogramBuffer {
// Workgroup size (adjust based on GPU architecture for performance, 16x16 is often reasonable)
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
// Helper to convert linear float (potentially HDR 0.0+) to 0-255 bin index
// Applies an approximate gamma curve for perceptual binning.
uint linearToVisualBin(float linearVal) {
// Clamp linear value to 0.0-1.0 range before gamma/binning
// This histograms the displayable range after processing.
float clampedVal = clamp(linearVal, 0.0, 1.0);
// Apply approximate sRGB gamma for perceptual brightness mapping
float displayApprox = pow(clampedVal, 1.0/2.2);
// Convert 0.0-1.0 display value to 0-255 bin index
return uint(displayApprox * 255.999); // Use 255.999 to ensure 1.0 maps to 255
}
void main() {
// Get the global invocation ID (like pixel coordinates)
ivec2 pixelCoord = ivec2(gl_GlobalInvocationID.xy);
@ -30,10 +43,9 @@ void main() {
// Calculate bin indices (0-255)
// We clamp just in case, although imageLoad from rgba8 should be in range.
uint rBin = uint(clamp(pixelColor.r, 0.0, 1.0) * 255.0);
uint gBin = uint(clamp(pixelColor.g, 0.0, 1.0) * 255.0);
uint bBin = uint(clamp(pixelColor.b, 0.0, 1.0) * 255.0);
uint rBin = linearToVisualBin(pixelColor.r);
uint gBin = linearToVisualBin(pixelColor.g);
uint bBin = linearToVisualBin(pixelColor.b);
// Atomically increment the counters in the SSBO
// Offset Green bins by 256, Blue bins by 512
atomicAdd(histogram.bins[rBin], 1u);

47
shaders/histogram_tf.geom Normal file
View File

@ -0,0 +1,47 @@
#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();
}

25
shaders/histogram_tf.vert Normal file
View File

@ -0,0 +1,25 @@
#version 330 core // Transform Feedback available in 330+
layout (location = 0) in vec2 aPos; // Dummy input vertex position (we don't use it)
uniform sampler2D InputTexture; // Linear Float texture (e.g., RGBA16F)
// Output to Geometry Shader
out VS_OUT {
vec3 linearColor;
} vs_out;
void main() {
// We use gl_VertexID to figure out which texel to read
ivec2 textureSize = textureSize(InputTexture, 0);
ivec2 texelCoord = ivec2(gl_VertexID % textureSize.x, gl_VertexID / textureSize.x);
// Boundary check (important if drawing more vertices than pixels)
if (texelCoord.x >= textureSize.x || texelCoord.y >= textureSize.y) {
vs_out.linearColor = vec3(-1.0); // Indicate invalid pixel
} else {
vs_out.linearColor = texture(InputTexture, vec2(texelCoord) / vec2(textureSize)).rgb;
}
// We don't output gl_Position as rasterization is disabled
}