Source browser
examples/shaders/harris_response.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// Smooth the structure tensor with a 3x3 [1,2,1] outer product, then evaluate Harris.
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 vec4 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 float 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.
15uniform float harris_k; // Control the trace penalty in the Harris corner response.
16
17// Clamp the tensor neighborhood independently of the output response storage.
18vec4 sample_tensor(int x, int y) { // Read a tensor neighbor with the shared clamp-to-edge border rule.
19 x = clamp(x, 0, int(width) - 1); // Clamp the neighboring column to the closest valid image pixel.
20 y = clamp(y, 0, int(height) - 1); // Clamp the neighboring row to the closest valid image pixel.
21 return input_values[uint(y) * width + uint(x)]; // Read this clamped coordinate from the row-major input buffer.
22} // End this block.
23
24void main() { // Smooth one structure tensor and compute its Harris corner response.
25 uint i = gl_GlobalInvocationID.x; // Select this invocation's global x coordinate.
26 if (i >= width * height) // Guard the flattened image against padding invocations.
27 return; // Stop this invocation before performing another resource access.
28 int x = int(i % width), y = int(i / width); // Recover the column and row from the flattened pixel index.
29 vec4 tensor = vec4(0.0); // Start the weighted neighborhood tensor at zero.
30 for (int dy = -1; dy <= 1; ++dy) { // Visit each neighboring tensor row.
31 for (int dx = -1; dx <= 1; ++dx) { // Visit each neighboring tensor column.
32 float weight_x = dx == 0 ? 2.0 : 1.0; // Give the center column twice the weight of either side column.
33 float weight_y = dy == 0 ? 2.0 : 1.0; // Give the center row twice the weight of either side row.
34 tensor += sample_tensor(x + dx, y + dy) * (weight_x * weight_y / 16.0); // Accumulate the normalized separable three-by-three tensor smoothing weight.
35 } // End this block.
36 } // End this block.
37 float determinant_value = tensor.x * tensor.z - tensor.y * tensor.y; // Measure the product of the tensor eigenvalues through its determinant.
38 float trace_value = tensor.x + tensor.z; // Measure the sum of the tensor eigenvalues through its trace.
39 output_values[i] = determinant_value - harris_k * trace_value * trace_value; // Penalize a large trace relative to the determinant to distinguish corners from edges.
40} // End this block.