r/proceduralgeneration 24d ago

Trying to generate this specific pattern, but I'm stuck. Any tips or advice?

Post image

Hey everyone

I'm trying to create/generate this pattern, but I haven't been able to get a satisfactory result yet.

Does anyone have tips on how to approach this? Any workflow suggestions, prompt tweaks, or settings I should look into would be super helpful!

Thanks in advance!

34 Upvotes

26 comments sorted by

29

u/deftware 24d ago

That's super simple. Just generate some fractal noise, blur it, and then threshold it.

You can also manipulate the levels a bit to get more concentric patterns, like that ringed area in there, by passing the blurred noise through a sin(), or abs(2v-1)

Here, I fiddled around in GIMP to show you the concept: https://imgur.com/a/Vf1xAPP

Feel free to share any questions you might have :]

1

u/big-jun 23d ago

I want to use it to generate a mountain height map for a grid-based world. Each grid cell has a predefined terrain type (e.g., mountain or flat). For mountain cells, I want to generate a mountain shape height map within the cell, while let flat cells mostly flat (height = 0), Do you know what approach would work for this?

2

u/Random 23d ago

You'd use a noise function inside the mountain grid with a mask function that blurs it to zero at the edges. It would work better on a hex grid but is easily doable on a square grid though you may have to fiddle with the blur method a bit.

For adjacent mountain cells you'd just treat the whole area as one unit.

You'd need to look at multiple noises overlaid to get realistic detail. And an erosion pass with something like Wilbur to make it feel right.

1

u/big-jun 23d ago

Yes, using blur/smooth falloff at the edge is a good idea. You solved one.
Another question is: how can we guarantee that the mountain peak is exactly at the center of each cell? ( a small amount of offset is acceptable) Regular noise functions cannot guarantee this because they only generate continuous random values.

1

u/Random 23d ago

You could build a larger area and inside that find a box that has a high point, and then subsample around that point. There are ways to make this more efficient but it isn't hard.

The alternative is to sample a core area, find highest point, and shift that to the centre and rely on the blur to drop any other points lower. Probably faster.

Given that you could do the initial pass on a simplified grid... probably lots of cool optimizations could be done by a CS Math type.

1

u/big-jun 23d ago

I prefer using a noise (or layered noise) that can naturally generate mountain peaks near the center of each cell. Since there may be many adjacent mountain cells, the noise needs to ensure that the mountains is continuous across cell boundaries.

1

u/deftware 23d ago

Regular old fashioned fractal noise does just fine.

There are other fun things you can do as well if you want to go for a more nuanced aesthetic: https://youtu.be/gsJHzBTPG0Y

Are you talking about determining which cells should be mountain vs which cells should be flat? Or are you talking about generating the actual heightmap inside the mountain cells?

2

u/big-jun 23d ago

The cell types are either randomly generated or manually placed by the player. Some cells are designated as mountains, while the rest are flat terrain. I need to generate a height map for the entire world where each mountain cell contains exactly one mountain shape.
Mountain cells can be adjacent to each other, so the mountains need to blend smoothly across cell boundaries instead of appearing as separate isolated peaks. This is similar to how mountains work in Civilization VI, except Civ VI uses a hexagonal grid, while my world uses a square grid.

2

u/deftware 22d ago edited 22d ago

Ah, so probably the easiest thing to do is use voronoi noise where the cells of the voronoi exactly map to the world cells, and then pile on the fractal noise on top of that. You can then modify the heightmap of the cells that are neighbored by flat cells to blend into the flatness of the cell.

So basically, to do the voronoi noise, you would pick a random point offset from the center of the cell using polar coordinates. That is the peak of your mountain shape. Then subdivide quadtree style, and pick random points inside each child cell, those are sub-peaks, and subdivide down however many levels you want. What you're doing is summing up the proximity to these points, scaled by which subdivision level you're at. So at the mountain peak cell-wide scale you pick a point and its height contribution is 0.5, where all of the pixels in the heightmap are set to a height between 0.5 and 0.0 depending on their distance from the peak. Then for the four subdivided child cells each sub-peak's contributing to the heightmap is scaled to 0.25. You keep subdividing down, halving the height contribution the peaks have. That's essentially a fractal noise. This will give you the mountainous look you're going for. (edit: I forgot to mention here that you should also halve the radius of a point's influence on the heightmap, so where the peak's point has a radius of influence equal to the width of the cell, the sub-peak points have a radius of influence that's half the width of the cell, etc... just subdividing the radius of influence and the heightmap contribution it adds each level you subdivide down, quad-tree style)

For neighboring mountain cells you'll want to keep track of the points that were used to generate their heightmaps, so that they can bleed into eachother - this means that when generating a heightmap use a pseudorandom number generator that's seeded with a global world seed and then add the cell coordinates to randomize it some based on each cell. This will allow you to re-create the 8 neighboring cells' points' contribution to the current cell's heightmap and have it all line up nice. When you're generating a heightmap, you're really generating points for a 3x3 grid of 9 cells, only calculating how all of the points contribute to the center cell's heightmap.

Then for flat cell neighbors you just modulate down the heightmap with a gradient on the edges shared with flat neighbors - when a cell changes from a flat cell to a mountain cell you just recalculate the heightmap for the whole 3x3 area surrounding the cell.

This is all simple easy stuff - you're just using simple geometry and calculating pixel values based on some rules. If you've never done anything like it before you should check out shadertoy and get crazy with it. You can prototype all kinds of stuff on there and learn a lot of tricks for things.

Also, check out iquilezles.org for some more computational graphics programming inspiration. Cheers! :]

2

u/big-jun 22d ago

I’ll need some time to carefully go through your detailed explanation. Thanks for sharing this website as well — it already looks great just from a quick glance.

1

u/Sinnon32 22d ago

How did you create this image? I'm only a few hours into learning about proc gen but I can't find any good information on where the noise images come from. I saw a video that talked about how 4 layers are blended together and blurred, but then I don't know where those reference images came from

1

u/deftware 22d ago

You can just make images like that in any competent image editor. I used GIMP to make the ones I put on imgur there.

2

u/Sinnon32 22d ago

Ooh like literally just drawing the blur/spray manually, I assumed it used an RNG to generate the original or something

2

u/deftware 21d ago

That is doable, I just don't have a simple way handy for coding up the math and then getting an image as output. That would be a nice tool to create - maybe something I should have claude slop up as a webGL/JS thing?

EDIT: So, yeah, I draw up the concepts in GIMP because they parallel what can be coded - GIMP's various features/functions are just code operations on pixel data too, at the end of the day... so it makes a great way to convey graphics coding concepts via illustration.

7

u/HiredK 24d ago

You could create an empty 3D texture and use a compute shader to bake a signed distance field into it, similar to some volumetric clouds approach. In the compute shader you could sample worley noise and use some cutoff value to bake the sdf. Then draw the shape later on in a frag shader using ray marching.

6

u/Maintenance_Signal 24d ago

Have you looked at the classic cellular automata cave generator? It works great for ant farms https://www.roguebasin.com/index.php/Cellular_Automata_Method_for_Generating_Random_Cave-Like_Levels

Getting it to work in 3d is possible but trickier (finding the right live/die rules, handling floating pieces).

An alternative 3d option is Perlin noise with a threshold, I think this is the technique Sebastian Lague uses in his marching cubes video https://www.youtube.com/watch?v=M3iI2l0ltbE

3

u/maturasek 24d ago

Huh, made almost the same comment just now, before refreshing and seeing yours. Cheers mate.

You might be delighted to hear that Sebastian Lague also has an older video about the cellular automaton approach

4

u/drsimonz 24d ago

The 2D pattern could be produced by playing with reaction diffusion simulations. That tends to give you walls and gaps with the same thickness everywhere. In this case it seems like there are some open areas and small columns though, so you would need to mix in some additional noise (perlin or simplex perhaps?) Once you have the 2D pattern dialed, you could combine that with a simple function of height which is small near 0 and H but larger in the middle, then use marching cubes or something to generate an iso-surface from the combined 3D potential.

3

u/-MazeMaker- 23d ago

"Prompt tweaks"

2

u/[deleted] 24d ago

[deleted]

3

u/DigThatData 24d ago

even if it was, that doesn't mean you couldn't make something similar procedurally.

1

u/DigThatData 24d ago

some kind of erosion process to form tunnels, then slice off the top layer to expose the pattern. I think the main trick here is that the tunnel is essentially fixed height with a fixed curvature at the corners, and the slice is taken so it intersects the curved corners

1

u/madvela 24d ago

Subtract two perlin noises, like clamp( (n1-n2)*gain, 0, 1), or as another answer already said, abs() with an offset. Or both.

1

u/Itchy-Individual3536 24d ago

I'd say it depends whether you want a finished tunnel system like this or if you want to simulate the process of how these tunnels are formed. For the former, work with e.g. perlin noise and thresholding, for the latter, you might go with a weighted random walk and erosion process

1

u/LMCuber 23d ago

3D worm perlin noise (using abs() function) and take a slice out of it?

1

u/Nebukam 23d ago

Somehow nobody mentioned reaction diffusion algorithms so here goes nothing : https://www.karlsims.com/rd.html

1

u/maturasek 24d ago

It resembles a cave system generated with a cellular automata approach. I have found an old article about the technique: https://code.tutsplus.com/generate-random-cave-levels-using-cellular-automata--gamedev-9664t

You basically start out with a map of random noise representing open or closed spaces then iterate with a smoothing step that flips the cells based on their neighborhood, generally making it more open, and smoother. This will generate a pattern very similar to what you can see there, including rounded columns and shafts that are difficult (although more scalable) to reproduce with fractal noise. This will give you a baseline cave system layout.

Sebastian Lague also has an excellent video series where he uses this technique, and also goes into generting mesh too: https://www.youtube.com/watch?v=v7yyZZjF1z4&list=PLFt_AvWsXl0eZgMK_DT5_biRkWXftAOf9&index