Source browser
examples/shaders/sobel.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#ifdef __cplusplus // Expose host declarations only when a C++ compiler reads this shader.
2#include "shdr.h" // Include shdr.h declarations.
3#endif // Finish this conditional compilation branch.
4
5// Normalized Sobel gradients, stored as (dx,dy) in one std430 vec2 element.
6layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; // Group 64 independent invocations along x.
7layout(std430, binding = 0) readonly buffer Inputs { // Read the preceding stage's input elements through buffer binding 0.
8 float input_values[]; // Store the preceding stage's input elements.
9}; // Finish this declaration.
10layout(std430, binding = 1) writeonly buffer Outputs { // Write this stage's output elements through buffer binding 1.
11 vec2 output_values[]; // Store this stage's output elements.
12}; // Finish this declaration.
13uniform uint width; // Set the row width of the flattened image buffer.
14uniform uint height; // Set the number of rows in the image buffer.
15
16// Neighborhood reads address the immutable blurred input, with clamped borders.
17float sample_value(int x, int y) { // Read a grayscale neighbor with the shared clamp-to-edge border rule.
18 x = clamp(x, 0, int(width) - 1); // Clamp the neighboring column to the closest valid image pixel.
19 y = clamp(y, 0, int(height) - 1); // Clamp the neighboring row to the closest valid image pixel.
20 return input_values[uint(y) * width + uint(x)]; // Read this clamped coordinate from the row-major input buffer.
21} // End this block.
22
23void main() { // Compute the horizontal and vertical Sobel derivatives at one pixel.
24 uint i = gl_GlobalInvocationID.x; // Select this invocation's global x coordinate.
25 if (i >= width * height) // Guard the flattened image against padding invocations.
26 return; // Stop this invocation before performing another resource access.
27 int x = int(i % width), y = int(i / width); // Recover the column and row from the flattened pixel index.
28 float dx = // Begin the horizontal derivative with the right-minus-left Sobel stencil.
29 (sample_value(x + 1, y - 1) + 2.0 * sample_value(x + 1, y) + sample_value(x + 1, y + 1) - // Weight the right neighboring column by one, two and one.
30 sample_value(x - 1, y - 1) - 2.0 * sample_value(x - 1, y) - sample_value(x - 1, y + 1)) / // Subtract the matching weighted left neighboring column.
31 8.0; // Normalize the stencil by its total absolute weight.
32 float dy = // Begin the vertical derivative with the bottom-minus-top Sobel stencil.
33 (sample_value(x - 1, y + 1) + 2.0 * sample_value(x, y + 1) + sample_value(x + 1, y + 1) - // Weight the bottom neighboring row by one, two and one.
34 sample_value(x - 1, y - 1) - 2.0 * sample_value(x, y - 1) - sample_value(x + 1, y - 1)) / // Subtract the matching weighted top neighboring row.
35 8.0; // Normalize the stencil by its total absolute weight.
36 output_values[i] = vec2(dx, dy); // Store the horizontal and vertical derivatives together for the tensor stage.
37} // End this block.