Procedurally Generated Caves

Hello, currently, I am attempting to create an infinitely procedurally-generating world, which generates in chunks (16x16). I have already been able to create procedurally generated terrain in chunks, however, caves are a bit confusing to me. I know the idea of caves is to use “perlin worms” to generate caves in a snake-like pattern, and I have tried using this in this world generation. I did have a problem with this, however, since I am not too sure how I would carry over this perlin worm to other chunks efficiently from a chunk where a cave was created, that goes into another chunk that needs to generate as well.

Thank you for reading!

1 Like

I never got this to work, but seems like this guy knows how minecraft does it:

I think this is how it works in Minecraft. Each worm has a maximum length (let’s call it M ). The heads of each worm are calculated based on the chunk position. When you render each chunk, you have to check all chunks within an M radius, and follow all of their worms. It’s not ideal in terms of performance, but it does work.

Hope this helps!

2 Likes

I’ll try looking into this, perhaps it will help me with what I needed, thanks!

1 Like

Perlin worms definitely work, but there are other approaches that may be better suited. As you said there’s the problem of making the works continue across chunks, which adds quite a bit of complexity. If caves that are just as good can be achieved without this complexity, i.e. just by tweaking the noise functions, that might be preferable.

Anyway, as the bottom comment on the linked stackexchange post mentions, when you generate a chunk you need to know about all the works that go through the chunk, even from chunks that may not have been generated yet. If worms could theoretically go on forever, that would clearly be impossible, because every chunk to infinity would have to be considered. So there needs to be some guarantee that chunks can only have their worms affect other chunks up to a certain distance away.

In practice this means you need to generate your chunks in two passes - one that only generates the worms starting in said chunk, and another that generates the blocks / the chunk itself.

1 Like

I was recently able to accomplish this, and this is probably the best advice I could give: find the noise at each coordinate, and decide what the threshold for your noise should be to generate the caves.

Your code might look similar to this


local noise = math.noise(xVal, yVal, zVal) -- xVal, yVal, zVal represent the position

-- CaveThreshold is some arbitrary number. I use .475 in my code, but it's really up to you. 
-- There's a lot of cool variations you can get with a bit of math and changing up the numbers

if noise >= SETTINGS.CaveThreshold or noise <= -SETTINGS.CaveThreshold then
				-- place air at the coordinate
			else
				-- place block (this is not air)
			end

My caves: https://twitter.com/foshes1/status/1388164856717750278?s=20

If you have any questions, feel free to message me.

2 Likes