Source browser

examples/shaders/debayer.cpp

Read the complete file below or download its original bytes. Line numbers provide stable links to a declaration or processing step.

File fingerprint
1// Bilinear demosaicing of all four Bayer phases, with clamp-to-edge sampling.
2#ifdef __cplusplus // Expose host declarations only when a C++ compiler reads this shader.
3#include "shdr.h" // Include shdr.h declarations.
4#endif // Finish this conditional compilation branch.
5layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; // Cover a 8 by 8 group of output coordinates.
6layout(std430, binding = 0) readonly buffer Samples { // Read one unpacked unsigned sensor value per pixel through buffer binding 0.
7    uint samples[]; // Store one unpacked unsigned sensor value per pixel.
8}; // Finish this declaration.
9layout(std430, binding = 1) writeonly buffer Colors { // Write normalized linear RGBA colors through buffer binding 1.
10    vec4 colors[]; // Store normalized linear RGBA colors.
11}; // Finish this declaration.
12uniform uint width; // Set the row width of the flattened image buffer.
13uniform uint height; // Set the number of rows in the image buffer.
14uniform uint pattern; // Select the RGGB, BGGR, GRBG or GBRG Bayer phase.
15uniform uint bit_depth; // Set the number of valid bits in each unpacked sensor sample.
16uint color_at(uint x, uint y) { // Determine which sensor color the two-by-two Bayer phase records here.
17    uint phase = (y % 2u) * 2u + x % 2u; // Locate this pixel inside its repeating two-by-two Bayer cell.
18    uint red = pattern == 0u ? 0u : pattern == 1u ? 3u : pattern == 2u ? 1u : 2u; // Select the red cell position for the configured Bayer pattern.
19    uint blue = 3u - red; // Place blue diagonally opposite red within that Bayer cell.
20    return phase == red ? 0u : phase == blue ? 2u : 1u; // Return red, green or blue as channel index zero, one or two.
21} // End this block.
22void main() { // Reconstruct the missing color channels at one Bayer sensor pixel.
23    uvec2 p = gl_GlobalInvocationID.xy; // Select the output pixel or voxel assigned to this invocation.
24    if (p.x >= width || p.y >= height) // Ignore workgroup padding outside the sensor image.
25        return; // Stop this invocation before performing another resource access.
26    vec3 result = vec3(0.0); // Start the reconstructed RGB pixel at zero.
27    uint center_color = color_at(p.x, p.y); // Identify the sensor channel already recorded at the center pixel.
28    for (uint channel = 0u; channel < 3u; ++channel) { // Reconstruct each of the three output color channels.
29        float value = 0.0; // Start the neighboring sample sum for this channel.
30        float weight = 0.0; // Count how many matching-color samples enter the average.
31        if (center_color == channel) // Preserve the channel that was measured directly at this pixel.
32            value = float(samples[p.y * width + p.x]); // Read the measured center sample for its recorded color channel.
33        else { // Interpolate the channel from neighboring same-color samples.
34            for (int dy = -1; dy <= 1; ++dy) // Visit the three nearby sensor rows.
35                for (int dx = -1; dx <= 1; ++dx) { // Visit the three nearby sensor columns.
36                    uint x = uint(clamp(int(p.x) + dx, 0, int(width) - 1)); // Clamp the neighboring column at the sensor boundary.
37                    uint y = uint(clamp(int(p.y) + dy, 0, int(height) - 1)); // Clamp the neighboring row at the sensor boundary.
38                    if (color_at(x, y) == channel) { // Use only neighboring samples that measure this channel.
39                        value += float(samples[y * width + x]); // Accumulate one neighboring sensor measurement of this channel.
40                        weight += 1.0; // Count that measurement toward the interpolation average.
41                    } // End this block.
42                } // End this block.
43            if (weight > 0.0) // Average the channel when at least one matching neighbor contributes.
44                value /= weight; // Average the selected same-color neighbor measurements.
45        } // End this block.
46        result[channel] = value / float((1u << bit_depth) - 1u); // Normalize the reconstructed channel by the maximum valid sensor value.
47    } // End this block.
48    colors[p.y * width + p.x] = vec4(result, 1.0); // Store the reconstructed linear RGB pixel with opaque alpha.
49} // End this block.