I recently published an article in which I talked about the Ursina Engine library and showed how to create your own 3D game in Python. Between sections, I mentioned Perlin’s noise in passing. This is one of the basic procedural generation algorithms that can be used to create beautiful game worlds. I want to tell you more about it and show you how to work with the perlinnoise module.
If you’re wondering how easy it is to generate realistic 3D landscapes in Python, welcome to the cut!
Explanations inside code inserts are an integral part of the article. Contact them if you don’t understand something. I can answer more complex questions about working with the module in the comments.
Failed Terrain Generation Attempt
First, the background. Before using Perlin noises in my project, I wanted to write a custom terrain generation algorithm.
The idea behind the algorithm was simple: a program randomly selects coordinates and assigns them a value y
Height. After that, it randomly generates new points with the value y
or y1
around these hills. This was supposed to be a smooth mountain landscape. But in practice, there were a couple of nuances:
 Sometimes the program generated not mountains, but curved pyramids and endless Chinese walls.
 The algorithm was not suitable for generating large worlds. It was not possible to efficiently record and read the generation from the computer’s memory.
The latter was especially an obstacle to the creation of the game: in order to preserve peace, it was necessary to record the coordinates of each block. This method can only be used to save individual small chunks. The rest should be described numerically, so that after reentering the game, everything is generated quickly from one special number, and not from a huge amount of data. This is exactly the problem that Perlin’s noise solves.
What is Perlin Noise
Perlin noise is a pseudorandom procedural generation algorithm. The mechanics are as follows: you feed a number to the input
seed
, on the basis of which the landscape structure is generated.
Now, a bit of theory. Unlike regular white noise, Perlin has smooth “transitions” between random local highs and lows. See for yourself:
White noise  Perlin’s Noise 


On a larger scale, Perlin’s noise can also resemble white noise.
The algorithm randomly generates inclined lines (they form elevations, peaks), linearly interpolates and additionally smooths out the kinks in their vicinity.
The process of obtaining onedimensional simple Perlin noise. Blue straight lines are oblique; the red curve is the result of linear interpolation, the Bézier curve; The black point is the smoothing of “corners” after linear interpolation.
The Perlin function itself generates fairly simple noises (curves), as can be seen from the graph above. In order to obtain more “inhomogeneous” curves, which in threedimensional space more resemble mountains, several noises are usually summed up. The main condition is that they have different resolutions and, accordingly, periods, for example, x
and 2x
. Usually, the values are multiples of two and the curves are called octaves: the more of them, the more heterogeneous and realistic the resulting surface.
A onedimensional representation of Perlin noise based on 4 octaves.
Ken Perlin’s mathematical apparatus is described in detail in Article Lexi Monroe. If you want to fully understand the implementation of the algorithm, I recommend reading it.
Perlin Noise Generation and Introduction to the Perlinnoise Module
It’s not easy to find a working version of Perlin’s noise algorithm in Python on the web. In most cases, you can find modified transcribed C algorithms.
import numpy as np
import matplotlib.pyplot as plot
def perlin(x, y, seed=0):
# создание матрицы для шума и генерация случайного значения seed
np.random.seed(seed)
ptable = np.arange(256, dtype=int)
# разброс пиков по случайным ячейкам матрицы
np.random.shuffle(ptable)
# получение свертки матрицы для линейной интерполяции
ptable = np.stack([ptable, ptable]).flatten()
# задание координат сетки
xi, yi = x.astype(int), y.astype(int)
# вычисление координат расстояний
xg, yg = x  xi, y  yi
# применение функции затухания к координатам расстояний
xf, yf = fade(xg), fade(yg)
# вычисление градиентов в заданных интервалах
n00 = gradient(ptable[ptable[xi] + yi], xg, yg)
n01 = gradient(ptable[ptable[xi] + yi + 1], xg, yg  1)
n11 = gradient(ptable[ptable[xi + 1] + yi + 1], xg  1, yg  1)
n10 = gradient(ptable[ptable[xi + 1] + yi], xg  1, yg)
# линейная интерполяция градиентов n00, n01, n11, n10
x1 = lerp(n00, n10, xf)
x2 = lerp(n01, n11, xf)
return lerp(x1, x2, yf)
def lerp(a, b, x):
"функция линейной интерполяции"
return a + x * (b  a)
# функция сглаживания
def fade(f):
return 6 * f ** 5  15 * f ** 4 + 10 * f ** 3
# вычисление векторов градиента
def gradient(c, x, y):
vectors = np.array([[0, 1], [0, 1], [1, 0], [1, 0]])
gradient_co = vectors[c % 4]
return gradient_co[:, :, 0] * x + gradient_co[:, :, 1] * y
# генерация равномерно распределенных координат для функции perlin
lin_array = np.linspace(1, 10, 500, endpoint=False)
x, y = np.meshgrid(lin_array, lin_array)
# вывод графика pyplot
plot.imshow(perlin(x, y, seed=2), origin='upper')
plot.show()
Implementation of Perlin noise according to the version OpenGenus.
In order not to deal with the components of Perlin noise and smoothing them, calculating gradients and linear interpolations, it is easier to use the perlinnoise. It consolidates complex mathematics: the developer just needs to import the module and “shake” with the terrain parameters:
from numpy import floor
from perlin_noise import PerlinNoise
import matplotlib.pyplot as plt
# генерация основного шума и параметризация
noise = PerlinNoise(octaves=2, seed=4522)
amp = 6
period = 24
terrain_width = 300
#генерация матрицы для представления ландшафта
landscale = [[0 for i in range(terrain_width)] for i in range(terrain_width)]
for position in range(terrain_width**2):
# вычисление высоты y в координатах (x, z)
x = floor(position / terrain_width)
z = floor(position % terrain_width)
y = floor(noise([x/period, z/period])*amp)
landscale[int(x)][int(z)] = int(y)
plt.imshow(landscale)
plt.show()
If you run this code and output the generated matrix with Perlin noise in Matplotlib, you’ll see something like this:
Done: A terrain heatmap has been generated and can be transferred to the game. Hills and mountains are bright yellow areas, the lower levels are indicated by cooler colors.
perlinnoise parameters
Now let’s take a closer look at the options that are available in perlinnoise. And let’s see how the landscape changes at different valuesIn 2014, the Netherlands announced that it
octaves is the number of Perlin curves that are responsible for the inhomogeneity of noise. The larger this parameter, the more “unusual” the landscape is in its shape.
octaves = 1  octaves = 3 


amp is the coefficient that is responsible for the final height of the ycoordinate.
amp = 6  amp = 10 


period is the periodicity of the peaks of the Perlin curve. As it increases, the surface becomes smoother.
period = 10  period = 24 


seed is a number that uniquely describes your generation. In games, this is the number that the user enters. The rest of the parameters — octaves, amp, and period — are consolidated and are not accessible “from the outside”.
Perlinnoise is an unpopular module that doesn’t even have documentation with practical examples. Therefore, working with this module can turn into a tambourine dance if you want to build your world from The Legend of Zelda.
The main thing is that the parameter values do not rest on the ceiling. For example, if the period value is small and the amp span is too large, you will get simple white noise. You can test it yourself, the project code available on GitHub. Fork and share your worlds in the comments!
You may also be interested in these texts:
→ Repair of a gaming laptop with burnout in the board without a circuit: bringing back to life the “buried” by CLEVO P970 service centers
→And then there was a knock from below: hard drive sales continue to collapse. Sales of PCs and laptops are also falling
→ How to connect a payment system from Payments to Telegram
———
Acknowledgment and Usage Notice
The editorial team at TechBurst Magazine acknowledges the invaluable contribution of Влад Ефименко the author of the original article that forms the foundation of our publication. We sincerely appreciate the author’s work. All images in this publication are sourced directly from the original article, where a reference to the author’s profile is provided as well. This publication respects the author’s rights and enhances the visibility of their original work. If there are any concerns or the author wishes to discuss this matter further, we welcome an open dialogue to address potential issues and find an amicable resolution. Feel free to contact us through the ‘Contact Us’ section; the link is available in the website footer.