Applied Math for Creative Coders
  1. Math Models for Creative Coders
  2. Media
  3. Making Noise Predictably
  • Math Models for Creative Coders
    • Maths Basics
      • Vectors
      • Matrix Algebra Whirlwind Tour
      • Things at Right Angles
      • content/courses/MathModelsDesign/Modules/05-Maths/70-MultiDimensionGeometry/index.qmd
    • Tech
      • Tools and Installation
      • Adding Libraries to p5.js
      • Using Constructor Objects in p5.js
      • The Open Sound Protocol
    • Geometry
      • Circles
      • Complex Numbers
      • Fractals
      • Affine Transformation Fractals
      • L-Systems
      • Kolams and Lusona
    • Media
      • Fourier Series
      • Additive Sound Synthesis
      • Making Noise Predictably
      • The Karplus-Strong Guitar Algorithm
    • AI
      • Working with Neural Nets
      • The Perceptron
      • The Multilayer Perceptron
      • MLPs and Backpropagation
      • Gradient Descent
    • Projects
      • Projects

On this page

  • What noise based outcomes will we see today?
  • Inspiration
  • What is Perlin Noise?
  • Creating Textures and Waveforms with Perlin Noise
  • Videos
  • Wait, But Why?
  • References
  1. Math Models for Creative Coders
  2. Media
  3. Making Noise Predictably

Making Noise Predictably

Meeting Ken Perlin

Noise Generation
Perlin Noise
Simplex Noise
Published

November 7, 2024

Modified

July 22, 2025

Abstract
Can you make the same random noise again?

TRON the movie

TRON the movie

What noise based outcomes will we see today?

We will understand the basics of procedural noise generation: generating random noise-like numbers that allow us to model and create very realistic-looking textures, such as wood, fire, marble, terrain, mountains, and clouds.

Let us quickly see this intro to Perlin Noise:

Inspiration

Arch

Cat Fur Up Close
Figure 1: Perlin Noise based Textures

What is Perlin Noise?

Ok, this is going to be a long explanation!!!

A. Inner Product Computation

Let us start by dividing up 2D space ( for now!!) into square-shaped cells. At each vertex we randomly place a unit gradient vector labelled \(r_{i}\) that points in a random direction. See the figure below:

Note

A perhaps more evocative picture may be this representation of an event from the Mahabharata:

We wish to calculate the Perlin Noise amount at any point of interest inside the cell.

  • We draw difference vectors to the point from each of the 4 vertices.
  • We compute the vector dot product with each of the \(r_{i}\) and the above difference vectors. ( 4 dot products )
  • These are shown in the text print at the side of the figure.
NoteDot Products are Scalars with Polarity

Note how the 4 dot products change as you move the mouse/touchpad. This changes the 4 gradient vectors and hence the scalar dot products change in amplitude and polarity.

In a typical Perlin Noise implementation, the gradient vectors are fixed after an initial setup. So each gradient vector generates a range of dot-product values as the point of interest moves within the cell.

B. Interpolation of Dot Product values

With the 4 scalar dot products, we are now ready to compute the Perlin Noise value at the point of interest. There are several ways of doing this:

  • Simply take the average
  • Take a weighted average, with fixed weights.
  • Use a weighting/interpolating function: The closer a point of interest is to one or other of the cell vertices, the higher is the contribution of the corresponding dot-product.

The third approach is the one embedded within (all?) Perlin Noise implementations. The interpolating function is:

\[ f(t) = 6t^5-15t^4+10t^3 \tag{1}\]

and looks like this:

NoteInterpolation Function \(f(t)\) has smooth ends

Both \(\frac{df(t)}{dt}\) and \(\frac{d^2f(t)}{dt^2}\) are continuous at the ends of the range of the function (t = 0 and t = 1).

\[ \begin{array}{lcl}f'(t) & = & \ \frac{d}{dt}[6*t^5 - 15*t^4 + 10*t^3]\\ & = & 30 * (t^4 - 2 * t^3 + t^2)\\ & = & 0 \ \text{@ t = 0 and t = 1} \end{array} \]

\[ \begin{array}{lcl}f''(t) & = & \ \frac{d^2}{dt^2}[6*t^5 - 15*t^4 + 10*t^3]\\ & = &60 * (2 * t^3 - 3 * t^2 + t)\\ & = & 0 \ \text{@ t = 0 and t = 1} \end{array} \] This ensures that there are not sudden changes in the noise function near about the vertices.

D. Fractal Overlay and Combining

Now that we have one grid full of a layer of noise generated by weighted dot-products, we can appreciate one more thing: we can overlay the space with several layers of such noise values. Why would this be a good idea?

This multiple layer overlay creates a very natural-looking fractal-ness in the resulting noise function. Most natural looking shapes like landscapes, mountains, vegetables, flames…all have this self-similar structure where when one zooms in, the magnified function looks pretty much like the un-zoomed version!!

So how we create and merge overlays? We create several more-closely-spaced grids overlaid on the first one, and generate noise in the same way. These layers of noise-s are scaled by a factor (Usually \(\Large{\frac{1}{2^n}}\)), where \(n\) is the “order” of the layer. Each new finely-spaced layer generates similar-looking noise functions, which are combined with smaller and smaller weights to achieve that final polished fractal look of Perlin Noise.

We will explore this fractality with code. For now, here is Ken Perlin’s own explanation from 1999:

“The outline of my algorithm to create noise is very simple. Given an input point P, look at each of the surrounding grid points. In two dimensions there will be four surrounding grid points; in three dimensions there will be eight. In n dimensions, a point will have 2n surrounding grid points.
For each surrounding grid point Q, choose a pseudo-random gradient vector G. It is very important that for any particular grid point you always choose the same gradient vector.
Compute the inner product G . (P-Q). This will give the value at P of the linear function with gradient G which is zero at grid point Q.
Now you have 2n of these values. Interpolate between them down to your point, using an S-shaped cross-fade curve (eg: 3t2-2t3) to weight the interpolant in each dimension. This step will require computing n S-curves, followed by 2n-1 linear interpolations.”

— Ken Perlin

Creating Textures and Waveforms with Perlin Noise

  • Using p5.js
  • Using R

Here is a landscape generated using Perlin Noise:

The ambient package allows us to create a variety of noise patterns, including Perlin Noise. The commands are: gen_perlin() and noise_perlin(), whose arguments are:

  • dim: The dimensions (height, width, (and depth)) of the noise to be generated. The length determines the dimensionality of the noise.
  • frequency: Determines the granularity of the features in the noise.
  • interpolator:How should values between sampled points be calculated? Either ‘linear’, ‘hermite’, or ‘quintic’ (default), ranging from lowest to highest quality.
  • fractal: The fractal type to use. Either ‘none’, ‘fbm’ (default), ‘billow’, or ‘rigid-multi’. It is suggested that you experiment with the different types to get a feel for how they behaves.
  • octaves: The number of noise layers used to create the fractal noise. Ignored if fractal = ‘none’. Defaults to 3.
  • lacunarity: The frequency multiplier between successive noise layers when building fractal noise. Ignored if fractal = ‘none’. Defaults to 2.
  • gain: The relative strength between successive noise layers when building fractal noise. Ignored if fractal = ‘none’. Defaults to 0.5.
  • pertubation: The perturbation to use. Either ‘none’ (default), ‘normal’, or ‘fractal’. Defines the displacement (warping) of the noise, with ‘normal’ giving a smooth warping and ‘fractal’ giving a more erratic warping.
  • pertubation_amplitude: The maximal perturbation distance from the origin. Ignored if pertubation = ‘none’. Defaults to 1.
  • x, y, z: Coordinates to get noise value from
  • seed: The seed to use for the noise. If NULL a random seed will be used:
noise2 <- noise_perlin(
  dim = c(400, 400), # height/width
  frequency = 0.01, # Lower = less granular, more organic
  interpolator = "quintic", #' linear', 'hermite', or 'quintic'
  fractal = "fbm", # Try "billow" , "rigid-multi"
  octaves = 5,
  lacunarity = 2,
  gain = 0.8, # Default = 0.5 giving 1/2^n scaling
  pertubation = "none", # Note the incorrect spelling
  pertubation_amplitude = 1 # Note the incorrect spelling
)
## generates a matrix
noise2 %>% as_tibble()
# Plot the matrix
plot(as.raster(normalise(noise2)))

# Using the generator
grid <- long_grid(seq(1, 10, length.out = 1000), seq(1, 10, length.out = 1000))
grid$noise <- gen_perlin(grid$x, grid$y,
  octaves = 5,
  frequency = 1.2
)
plot(grid, noise)
##
grid %>%
  gf_point(y ~ x,
    colour = ~noise,
    size = 0.01, show.legend = F
  ) %>%
  gf_refine(
    scale_color_gradient(
      low = "orangered",
      high = "black"
    ),
    coord_fixed()
  ) %>%
  gf_theme(theme_void())

It seems the ambient package cannot generate 1D-Perlin noise, so we cannot generate say time waveforms based on this idea. p5.js of course can do 1D.

Videos

Of course there are videos by Dan Shiffman on the topic of Perlin Noise:

  1. Perlin Noise in p5.js. https://www.youtube.com/watch?v=Qf4dIN99e2w&list=PLRqwX-V7Uu6ZV4yEcW3uDwOgGXKUUsPOM&index=3&pp=iAQB
  2. Perlin Noise in 2D. https://www.youtube.com/watch?v=ikwNrFvnL3g&list=PLRqwX-V7Uu6ZV4yEcW3uDwOgGXKUUsPOM&index=6&pp=iAQB
  3. Perlin Noise in Detail. https://www.youtube.com/watch?v=D1BBj2VaBl4&list=PLRqwX-V7Uu6ZV4yEcW3uDwOgGXKUUsPOM&index=7&pp=iAQB
  4. Graphing Perlin Noise. https://www.youtube.com/watch?v=y7sgcFhk6ZM&list=PLRqwX-V7Uu6ZV4yEcW3uDwOgGXKUUsPOM&index=5&pp=iAQB

Wait, But Why?

  • Generating random waveforms and textures is an important part of Creative Computational projects.
  • These ideas are used in landscape, texture and sound generation.
  • “Normal” random noise is too jagged to have the natural look that we would like
  • Perlin Noise creates both a smoothness and a fine-grain random structure in an arbitrary number of dimensions.
  • This ends up looking more “organic” and “natural”. Think cats.

References

  1. Ken Perlin.(1999). Making Noise. https://web.archive.org/web/20151221035155/http://www.noisemachine.com/talk1/index.html. Based on a talk presented at GDCHardCore on Dec 9, 1999.
  2. https://www.scratchapixel.com/lessons/procedural-generation-virtual-worlds/perlin-noise-part-2/perlin-noise.html
  3. https://www.khanacademy.org/computing/computer-programming/programming-natural-simulations/programming-noise/a/perlin-noise
  4. https://adrianb.io/2014/08/09/perlinnoise.html
  5. https://www.arendpeter.com/Perlin_Noise.html
  6. https://mzucker.github.io/html/perlin-noise-math-faq.html
  7. https://betterexplained.com/articles/vector-calculus-understanding-the-dot-product/
  8. Gorilla Sun Blog. Perlin Noise. https://www.gorillasun.de/tag/perlin-noise/
  9. The ambient package in R: https://ambient.data-imaginist.com/

Textbooks

  1. Patricio Gonzalez Vivo & Jen Lowe. The Book of Shaders. https://thebookofshaders.com/11/
R Package Citations

Resources

  1. https://opengameart.org/content/700-noise-textures
  2. https://github.com/sighack/perlin-noise-fields
Package Version Citation
ambient 1.0.2 Pedersen and Peck (2022)
mosaicCalc 0.6.4 Kaplan, Pruim, and Horton (2024)
plot3D 1.4.1 Soetaert (2024)
Kaplan, Daniel T., Randall Pruim, and Nicholas J. Horton. 2024. mosaicCalc: R-Language Based Calculus Operations for Teaching. https://doi.org/10.32614/CRAN.package.mosaicCalc.
Pedersen, Thomas Lin, and Jordan Peck. 2022. ambient: A Generator of Multidimensional Noise. https://doi.org/10.32614/CRAN.package.ambient.
Soetaert, Karline. 2024. plot3D: Plotting Multi-Dimensional Data. https://doi.org/10.32614/CRAN.package.plot3D.
Back to top

Citation

BibTeX citation:
@online{2024,
  author = {},
  title = {\textless Iconify-Icon Icon=“arcticons:noise-Reducer”
    Width=“1.2em”
    Height=“1.2em”\textgreater\textless/Iconify-Icon\textgreater{}
    {Making} {Noise} {Predictably}},
  date = {2024-11-07},
  url = {https://mathforcoders.netlify.app/content/courses/MathModelsDesign/Modules/35-Media/20-MakingNoise/},
  langid = {en},
  abstract = {Can you make the same random noise again?}
}
For attribution, please cite this work as:
“<Iconify-Icon Icon=‘arcticons:noise-Reducer’ Width=‘1.2em’ Height=‘1.2em’></Iconify-Icon> Making Noise Predictably.” 2024. November 7, 2024. https://mathforcoders.netlify.app/content/courses/MathModelsDesign/Modules/35-Media/20-MakingNoise/.
Additive Sound Synthesis
The Karplus-Strong Guitar Algorithm

License: CC BY-SA 2.0

Website made with ❤️ and Quarto, by Arvind V.

Hosted by Netlify .