Help with blocky terrain generation (3D Perlin noise)

Hey developers! I recently got into blocky terrain generation and decided to write up a simple script which gets called when an event fires after the player puts in the world generation settings. Now, I use “density” to determine which color and material a block should be. This, however gave me strange results and I am wondering how to make it accurate, because sometimes, the blocks somewhere in a hole are grass, which I do not want. What would be a better way to determine if a block is grass/stone/dirt? Screenshots and code attached below, as well as my “reference image”, of how I want it to look like:

local replicatedStorage = game:GetService("ReplicatedStorage")
local generate = replicatedStorage.Generate

local function GenerateNoiseMap(seed, mapSize, noiseScale, amplitude)
	math.randomseed(tick())
	print(seed)
	for x = mapSize, 0, -1 do
		for z = mapSize, 0, -1 do
			for y = mapSize, 0, -1 do
				local xNoise = math.noise(y/noiseScale, z/noiseScale, seed) * amplitude
				local yNoise = math.noise(x/noiseScale, z/noiseScale, seed) * amplitude
				local zNoise = math.noise(x/noiseScale, y/noiseScale, seed) * amplitude
				
				local density = xNoise + yNoise	+ zNoise + y
								
				if density < 18 and density > 10 then	
					local part = Instance.new("Part", workspace.World) 
					part.Anchored = true
					part.Size = Vector3.new(2,2,2)
					part.Material = Enum.Material.SmoothPlastic	
					part.CFrame = CFrame.new(x*2, y*2, z*2)
					if density <= 18 and density > 15 then
						part.BrickColor = BrickColor.new("Shamrock")
						part.Material = Enum.Material.Grass
					elseif density <= 15 and density > 14 then
						part.BrickColor = BrickColor.new("Brown")
						part.Material = Enum.Material.Slate
					elseif density <= 14 and density > 0 then
						part.BrickColor = BrickColor.new("Medium stone grey")
						part.Material = Enum.Material.Slate
					end
				end

			end
		end
	end
	wait()
end


generate.OnServerEvent:Connect(function(player, seed, mapSize, noiseScale, amplitude)
	print("received!")
	seed = tonumber(seed)
	mapSize = tonumber(mapSize)
	noiseScale = tonumber(noiseScale)
	amplitude = tonumber(amplitude)
	print(seed, mapSize, noiseScale, amplitude)
	if seed ~= nil and mapSize ~= nil and noiseScale ~= nil and amplitude ~= nil then
		if mapSize <= 512 then
			print("started generating!")
			workspace.World:ClearAllChildren()
			GenerateNoiseMap(seed, mapSize, noiseScale, amplitude)
		else
			print("map is too big!")
		end
	else
	print("one of these is not a number!")
		end
end)

My problem: The walls of the hole/cave thing are grass, but it should be stone image

What I am trying to make it look like:

Any help would be appreciated! :smiley:

1 Like

id reccomend checking for CFrame.Y
i did this and as you can see here it is.

however this is not 3d perlin but 2d perlin but you get the idea

First off if you wanna make something like that you shouldn’t be checking the density but rather the perlin y. To add on to this you really should be using fm1 or what we call “octaves” instead of 3d perlin noise all together.

Is it possible to achieve overhangs using 2d perlin noise tho?

I mean i guess you could make octaves for certain sections of overhangs but no you cant

That’s why I was using 3d perlin noise in the first place, to achieve minecraft-like terrain with overhangs.

1 Like

Use 2d noise to Cut through 3D noise