3D Perlin Noise Tutorial

Hello Everyone! My name is paswa!

Today I’m going to be showing you step-by-step on how 3D Perlin Noise can be created and used.



Firstly, we need to understand Perlin Noise! I explained it in a post before this one, you can find it here.

:warning:Highly recommended reviewing the Perlin Noise section of the post before progressing this post :warning:



Alrighty, assuming you have read up on Perlin noise were gonna start talking about 3D Perlin Noise.

What is 3D Perlin?

3D Perlin Noise is a series/collection of noises along different axis’s. One for each of the x, y, and z axis.

What are the terms your gonna be using?

Density. Density is a number assigned to each pixel within your 3D Perlin noise. Its essentially the equivalent to what color the noise is, but we call it Density since its the collection of multiple noise values.

Here is a small picture resembling 3D Perlin and its colors/densities.

How do we apply this all?

local block_size = 5

local height, width = 30, 100

local blocks = game.Workspace.Blocks

local xOffset = math.random(-100000, 100000)
local yOffset = math.random(-100000, 100000)
local zOffset = math.random(-100000, 100000)

local freq = 2
local ampltiude = 10

local scale = 200

local maxDensity = 0

for x=0, width do
	task.wait()
	for y=0, width do
		if y % 10 == 0 then
			task.wait()
		end
		for z=0, width do
			local xP = math.noise(((y + yOffset) / scale) * freq , ((z + zOffset) / scale) * freq) * ampltiude
			local yP = math.noise(((x + xOffset) / scale) * freq , ((z + zOffset) / scale) * freq) * ampltiude
			local zP = math.noise(((x + xOffset) / scale) * freq , ((y + yOffset) / scale) * freq) * ampltiude
			
			local density = xP + yP + zP
			if density >= maxDensity then
				local part = Instance.new("Part")
				part.Anchored = true
				part.Position = Vector3.new(x * block_size, y * block_size, z * block_size)
				part.Size = Vector3.new(block_size, block_size, block_size)
				part.Parent = blocks
			end
			
		end
	end
end

This looks like gibberish?
Unless your fluent in Lua you would understand this, I completely don’t expect many of you to fully understand this snippet. Therefore I’ll be explaining portions of this code, mainly ones relating to the topic.

Snippet 1: 3D Perlin Noise

local xP = math.noise(((y + yOffset) / scale) * freq , ((z + zOffset) / scale) * freq) * ampltiude
local yP = math.noise(((x + xOffset) / scale) * freq , ((z + zOffset) / scale) * freq) * ampltiude
local zP = math.noise(((x + xOffset) / scale) * freq , ((y + yOffset) / scale) * freq) * ampltiude

local density = xP + yP + zP

Don’t let the tons of parentheses and math equations get to you, all we need is a basic understanding of how this functions to understand it. First off, please read the past post before progressing as I will not be re-explaining it! Upon finishing it, you will fully grasp this snippet.

Essentially we are combining multiple noise maps (one per axis) into a variable called density, which as we stated earlier is the collection of multiple noise values. This variable is used to alter certain aspects of the noise above, below, or between certain ranges.

if density >= maxDensity then
	local part = Instance.new("Part")
	part.Anchored = true
	part.Position = Vector3.new(x * block_size, y * block_size, z * block_size)
	part.Size = Vector3.new(block_size, block_size, block_size)
	part.Parent = blocks
end

As said above we just select portions of the noise by limiting/picking certain densities. We then simply place a “block” in that location.

Misc. Snippet

if y % 10 == 0 then
	task.wait()
end

I’m sure many of you absolutely do not know what this is or what this does.

Essentially this checks every time the loop runs 10 times and runs the code inside. Which is task.wait(). We use this to yield our generation to allow for more performance on all/lower devices.

% -- Modulo is a math symbol used within lua along with it’s counter partner / -- Division
Modulo is used to return the remainder of divisible value.

For more information on what this does you can visit this website



Thanks for reading! If you don’t fully understand something feel free to ask in the comments!

22 Likes