Perlin Noise for Fractal Brownian Motion in C++
The choice of random number or noise is affected by the application we run. There are several implementations of random generators in C++. For my purposes, I use often the Marsenne-Twister engine. Generally, we are looking for such an engine (method) that gives always an unreachable number, chosen totally independently. There are many approaches but the process is rather complex. It is almost not possible to generate “pure” random numbers (in computer science) since computers are deterministic machines and it exists generation patterns (algorithms). Please read this article to capture more information.
For now, we can assume that using the Marsenne-Twister engine we can generate a “real” random number. In this way, one number we generated in time to does not have any influence on the number generated in time t1 (t1 > t0).
Using the Marsenne-Twister engine I generated the Matrix (500 x 500 pixels) where the intensity of the grey color was chosen randomly (see below figure — C++ ImGui).
As expected the figure depicts no relation between pixels (color in this particular case). Noise signal (a signal produced by a stochastic process) can be generated by random generators. We can consider the white noise which is considered as a random signal having equal intensity at different frequencies.
On the other hand, there are applications that do not look for another type of randomness. We can need the pattern where the numbers have some relations so we will be able to simulate nature which can be perceived as sometimes chaotic but form a long perspective or narrow span that has some common features. Thank to that pattern (in this article I am going to discuss Perlin noise pioneered by Ken Perlin we will be able to simulate the process randomly rather smoothly. The approach we are taking is applied often in computer graphics, simulators, or other applications where the real effect (from the human perspective ) is decisive.
We can simplify the above discussion and depict both patterns random and Perlin as follows,
Now I will display a general approach to generate the Perlin noise. The implementation of the algorithm I made in C++ with the visualization in ImGui. The introduction to the C++ ImGui and information on how to compile and build programs you will find in one of my previous articles.
The original algorithm is displayed here (by Ken Perlin).
The source for this article you will find on my GitHub.
The general feature of Perlin noise was given in the previous paragraph. We can expect the behavior of the noise in the particular case to be more comprehensive and besides randomly generated values, the output is smooth. The numbers are more dependent on each other.
My implementation is based on the discussion presented in the following article and here.
Perlin noise (gradient noise) is created by an established gradient in regular space points (coordinates — in our case XY — 2D), and a smooth function is then interpolated between those points. We can also create Perlin noise in one dimension by setting the function value at each integer coordinate to zero and associating a pseudo-random gradient (or slope) for the noise function with each integer coordinate (see below).
This interpolation is not linear with distance since doing so would violate the requirement that the noise function’s derivative also is continuous at integer places. Instead, a blending function is utilized, which has endpoints with zero derivatives.
For the 2D noise, we take simply the grid. In the application I made there is a matrix of 1000 x 1000 pixels and each pixel has a certain position in XY space. In this case, the noise value is calculated from the four nearest grid points for every position on the matrix.
The value of each gradient pixel (or cell if we computed gradient for the square for example 5x5) is computed by means of a scalar product (dot product) between the gradient vectors of each input point and the vectors from the position of the vertex on matrix grid (1000 x 1000), in our case.
The result of gradient computation for the given number in 2D space is a noise value, which is the simulation (see below) I used to generate the RGB color. For the input (values in XY space), I applied Fractal Brownian Motion (FBM). The principles of Brownian Motion I included in my article here. The Brownian motion is a motion, where the position of a given object (particle) changes in random increments.
For the details please consider my implementation which I assume is self-explainable.
In the article where I discussed the BM, I displayed information that the iterative process of motion is constructed by adding white noise. Contrary to the discussed previously approach the fractional Brownian Motion implements relations between “particle” motions. We can think that there exists some internal memory (inertia) in the system, which affects other particles. This behavior exactly resembles nature, which stores some information over time (evolution, adaptation, climate changes, etc).
The parameter which controls the behavior (self-similarity) is called a fractal dimension. We use the H abbreviation and consider it as the power spectrum of the fractal dimension.
As I mentioned above the Perlin noise is often used in computer graphics to simulate clouds, mountains, or fire smoke. Besides we evaluate relatively huge “objects” — randomly created, and we understand that these objects are composed in an incremental way. Simply adding small “components”.
I follow the impressive article about fractional Brownian Motion. How to generate this motion you will find here.
Mapping the Brownian Motion into the Perlin noise affects the generation of impressive natural shapes. Now the matrix 1000x1000 pixel looks a bit different. It is not only about the color which I add but the shapes, and features. We can imagine the shape resembles the terrain or other natural (for a human being) phenomena. You can play with the frequency (top bar in the simulation).
Frequency = 0.006
Frequency = 0.36
Frequency = 0.62
Thank you for reading.