Experimenting with rendering in Fourier space
Constant magnitude, drawing sine waves into phase space, then running inverse DFT to generate image:
This is a record of a twitter thread, originally posted in 2019
Experimenting with rendering in Fourier space
Constant magnitude, drawing sine waves into phase space, then running inverse DFT to generate image:
Okay so I've been doing a bunch of experiments with 2D Fourier transforms at @LevelExGameDev for the past few days; gonna make a thread to document this stuff so I don't forget it lol
Not gonna do a full explanation of how to understand the Fourier images; they're not entirely human-readable except for a few specific properties
If you want to read up on it, best explanation I've found is here:
https://www.cs.unm.edu/~brayer/vision/fourier.html
Introduction to the Fourier Transform
Main takeaways:
- You can convert freely between real and Fourier representations without losing information
- Fourier space represents the image as a huge collection of cosine waves all added together. Waves can be described as frequency, amplitude, and phase offset
Every pixel coordinate in the Fourier image corresponds to a FREQUENCY, not a LOCATION. Amplitude and phase of the waves are related to the magnitude and phase values in the Fourier images
Lower frequencies are towards the center, but beyond that the pixel coordinates in Fourier space have NO positional relationship to the pixels in the real image
Thus, things like blurring or warping the Fourier image mostly result in uninteresting garbage, sadly
Literally just throwing out the high frequencies (i.e. sharp changes in brightness over small pixel distances) and keeping the low frequencies (big, smooth changes in brightness over large distances)
If you're familiar with audio this would be a low-pass filter
Turns out Guassian blur is literally a 2D low-pass filter. Audio is a 1D signal and images are 2D signals, but the math's the same
A huge amount of Photoshop is basically digital signal processing tools
Good note here
(I'm prob gonna get some things wrong here; DSP is very much not my area of expertise, which is why I was interested in messing around with it)
@AmazingThew Just to be precise: The basis vector of a Discrete Fourier Transform (DFT) is a complex exponential, which includes sinusoids in their real (cosine) and imag (sine) parts. There's another transform which includes only cosines, the Discrete Cosine Transform (DCT).
Everything I've shown so far is just multiplying the DFT with different masks
Multiplication in Fourier space is equivalent to convolution in real space (!), which is a HUGE topic that I'm not really equipped to discuss
but basically you can do all this with kernels if you want
Things get WAY more interesting when you start screwing with the magnitude and phase values independently; you can start getting some really wild effects that don't transfer readily to any other screenspace technique
The phase offsets create destructive and constructive interference across the whole image, so this is *somewhat* intuitive. Any individual oscillation (i.e. one pixel in the DFT) isn't going to contribute much to the overall image, unless its phase aligns with LOTS of other waves
...This is a bit demoralizing if you want to generate cool images though, bc the phase offsets are INCREDIBLY unintuitive to work with. Remember, they have no particular spatial relationship, they're just describing interference patterns between 512x512 different waves
Drawing procedural stuff into the magnitudes though?
HYPNOSLOTH
(twitter compression will probably ruin this sorry)
One REALLY neat application for all of this is noise generation. Recall that noise is often classified by its frequency distribution ("white noise" etc)
Noise is basically random waves in specific frequency ranges, which means you can construct pretty much any noise you want by drawing the appropriate frequency distribution and then just using random phases
You can also animate all of these trivially by just rotating the phases (and you can get some subtle effects by animating different frequency ranges at different speeds), and anything you make will tile just by nature of how DFT works
Anyway, none of this is particularly novel; the analog version of this stuff predates computers, and Fourier transforms (and/or the related discrete cosine transform) are a huge part of image and video compression
I just don't see it talked about a whole lot in tech-art spaces
The biggest downside is it's slow as hell. Naive DFT is separable but every fragment has to sample every other texel in its row+column, so if you're doing DFT->manipulate->Inverse DFT that's 4N samples per fragment
the "Fast" Fourier transform you've probably heard of is log(n), which rules, but it's a recursive algo that doesn't intuitively map to a parallel GPU approach
I'm sure someone much smarter than me has prob figured it out though
Also, credit: my DFT implementation was largely derived from @FabriceNEYRET 's work:
Go check out the rest of their shadertoy stuff; it's fantastic
https://www.shadertoy.com/view/4s3GDs