Source browser

examples/shaders/dft_columns.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// The second separable DFT stage transforms columns of a complex vec2 buffer.
2// direction=-1, normalization=1 is forward, +1, 1/height is normalized inverse.
3// Combined rows/columns cost O(width * height * (width + height)).
4#ifdef __cplusplus // Expose host declarations only when a C++ compiler reads this shader.
5#include "shdr.h" // Include shdr.h declarations.
6#endif // Finish this conditional compilation branch.
7layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; // Cover a 8 by 8 group of output coordinates.
8layout(std430, binding = 0) readonly buffer Input { // Read the preceding stage's input elements through buffer binding 0.
9    vec2 input_values[]; // Store the preceding stage's input elements.
10}; // Finish this declaration.
11layout(std430, binding = 1) writeonly buffer Output { // Write this stage's output elements through buffer binding 1.
12    vec2 output_values[]; // Store this stage's output elements.
13}; // Finish this declaration.
14uniform uvec2 dimensions; // Set the image or volume extent in x, y and optional z order.
15uniform float direction; // Choose a negative Fourier phase for forward transforms or a positive phase for inverse transforms.
16uniform float normalization; // Scale the transform result, usually by the reciprocal axis length for an inverse transform.
17
18void main() { // Compute one complex frequency bin along this column.
19    uvec2 p = gl_GlobalInvocationID.xy; // Select the output pixel or voxel assigned to this invocation.
20    if (any(greaterThanEqual(p, dimensions))) // Guard every coordinate against the output image or volume extent.
21        return; // Stop this invocation before performing another resource access.
22    const float tau = 6.28318530717958647692; // Use a complete turn in radians for the complex Fourier phase.
23    vec2 total = vec2(0.0); // Accumulate the real and imaginary components independently.
24    for (uint n = 0u; n < dimensions.y; ++n) { // Visit every sample along the transformed axis.
25        float angle = direction * tau * float(p.y) * float(n) / float(dimensions.y); // Form this frequency bin's signed phase at the current sample.
26        vec2 phase = vec2(cos(angle), sin(angle)); // Represent the unit complex phase as cosine and sine.
27        vec2 value = input_values[p.x + dimensions.x * n]; // Read the original complex sample along this axis.
28        total += vec2(value.x * phase.x - value.y * phase.y, value.x * phase.y + value.y * phase.x); // Multiply the sample by the unit complex phase and accumulate.
29    } // End this block.
30    output_values[p.x + dimensions.x * p.y] = total * normalization; // Apply the configured forward or inverse normalization to the completed bin.
31} // End this block.