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.