How can i create perlin noise with areas that are completely flat?

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    To create perlin noise that is flat in some places and still has water and mountains

  2. What is the issue? Include screenshots / videos if possible!
    I am quite bad at math and need help. I have already written a script:


local Map = workspace:WaitForChild(“Map”)

local FogSize = 200
local Resolution = 80
local Frequency = 1
local Amplitude = 10

for X = 1, FogSize do
for Z = 1, FogSize do

	local Part = Instance.new("Part")
	Part.Anchored = true
	Part.Size = Vector3.new(1, 0.5, 1)
	Part.Parent = Map
	
	local Height = (math.clamp(math.noise(X / Resolution * Frequency, Z / Resolution * Frequency, math.random(-math.huge, math.huge)), -0.5, 0.5) + 0.5) * Amplitude
	
	Part.Position = Vector3.new(X, Height, Z)

end

task.wait()

end

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I tried to look for solutions on youtube and dev hub

(And sorry for my bad english :sweat_smile:)

Unrelated to your initial question (I get to that later in my reply), but math.random(-math.huge, math.huge) is always -2147483648 because it can only handle 32 bit integers which math.huge exceeds.

-- Assuming it's the map's seed it should also be moved outside the loops.
local SeedAbsLimit = 2 ^ 32 / 2 - 1
local Seed = math.random(-SeedAbsLimit, SeedAbsLimit)

Now about your question, I happen to have a SmoothStep function for this exact purpose! It’s a mess of equations but you can play with a visualizer on desmos to see what it does.

This SmoothStep has properties to modify your map’s shape:

  • Smoothness coefficient (s) - how “steep” the transitions are between low and high spots.
  • Fulcrum position (p) – bias for either more low or more high spots.

I took the liberty to make an adjusted version of your script with my changes. Make sure to change the SmoothStep input to get the shape you’re looking for!

Adjusted script
--[[
	Smoothly interpolates between a & b
	Visual graph: https://www.desmos.com/calculator/3zhzwbfrxd
	x -- interpolation (0 - 1)
	s -- smoothing coefficient (0: linear, 0.5: bilinear 1: instant)
	p -- fulcrum position, i.e. controls the bias between a and b
--]]
local function smoothStep(a: number, b: number, x: number, s: number, p: number): number
	if s > 0.995 then -- s near 1 causes overflows, assume instant change at p
		return x < p and a or b
	end
	
	local c = 2 / (1 - s) - 1
	
	if x < p then
		return x ^ c / (p ^ (c - 1)) * (b - a) + a
	else
		return (1 - (1 - x) ^ c / (1 - p) ^ (c - 1)) * (b - a) + a
	end
end

local Map = workspace:WaitForChild("Map")

local FogSize = 200
local Resolution = 80
local Frequency = 1
local Amplitude = 100

local SeedAbsLimit = 2 ^ 32 / 2 - 1
local Seed = math.random(-SeedAbsLimit, SeedAbsLimit)

for X = 1, FogSize do
	for Z = 1, FogSize do
		
		local Part = Instance.new("Part")
		Part.Anchored = true
		Part.Size = Vector3.new(1, 0.5, 1)
		Part.Parent = Map
		
		local HeightPercentile = math.clamp(math.noise(
			-- Arbitrary decimals prevents getting all integers (in this case noise would result as 0)
			(X + 0.5238) / Resolution * Frequency,
			(Z - 0.8734) / Resolution * Frequency,
			Seed
		) * 0.5 + 0.5, 0, 1)
		
		local Height = smoothStep(0, Amplitude, HeightPercentile, 0.85, 0.5)
		
		Part.Position = Vector3.new(X, Height, Z)
	end
end
2 Likes

You’re not going to want a new value from math.random for the 3rd parameter of each call to math.noise because you won’t get Perlin noise, you’ll just be sampling Perlin Noise randomly, which is going to just get you regular (non-Perlin) noise.

Normal usage is to either pass a constant value for Y if you want to sample a plane from the Perlin Noise (e.g. you want a 2D height map), or to use the actual Y position if you want true 3D perlin noise (to get caves and such).

1 Like

Thank you so much for taking your time to help me!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.