Cashgen - (kinda) Infinite Procedural World Generator

As a LAM user i can say that it is important to have the option to assign different themes for a landscape. In LAM i extended the existing material with additional layers, but it was always a very time consuming task, because of shader compilation and then updating the existing landscape parts.

Different biomes is part of the design, although obviously needs to be all procedurally generated which makes things trickier. I think the approach I will take is :

2 different biomes
Each biome has a unique:

  • Terrain heighmap noise generator
  • Material
  • HISM mesh spawn parameters

The two biomes will be blended using a noise generator mask.

Anyway, the V10_REFACTOR branch is up to 4.14 and very nearly finished. It’s a side-by-side refactor so the original WorldManager with foliage spawning etc is all still in place.

To use the all new, much faster and more efficient terrain, you’ll want to place a CGTerrainManager in the world. Call the SetupTiles method as you would have the old SpawnZones.

I think there’s still some edge case bugs in the LOD system I need to work out before I merge into .

V10_REFACTOR branch in action.

It’s on 4.14 now and I’ve included the 4.14 compatible OceanPlugin.

Some ease of use improvements this morning, most parameters are now set in the defaults panel. Noise modules still need to be built in the blueprint.

Still not quite ready to merge to . I’m still to make the LOD levels fully configurable.

2eb9644758e648a0976c9c6164d297fd.png

Fully configurage LODs added :slight_smile:

Now you can define how many LODs, collision enabling, distance and the resolution divisor per LOD.

If your standard tile width is 32 units, a LOD divisor or 8 will only use 4…and so on.

Hey @Mid_Gen this looks awesome so far.

I got to ask tho what is the Biome Blend Module?

What are your plans for Biome generation?

Well I’ve been mulling over what to do about biomes. To create a decent looking terrain you need several different noise types and blend between them with a mask from another noise generator. The idea was to use that mask as a weighting for biomes. I’m not sure that’s going to be much use though.

I’m going to keep the terrain with the fairly basic material as is, shoreline, grass, snow/rock, with slope blending for a bit of variation.

The foliage spawning I’m splitting off into a standalone plugin. It’ll track the player pawn and position instanced foliage meshes around the player as required, and use it’s own noise generator to add variation.

In the meantime, I’ve put together a better sample scene and got a decent capture finally. :

I’d really like to make the heightmap for Oceanplugin work but I wasn’t having much luck last time I tried. I’ll have another look.

Interesting - Cannot wait to see the results of the biome plugin :slight_smile:

That video looks really good so far :slight_smile:

Thanks :slight_smile:

Small push to branch, tesselation is now working.

Just working on some heightmap supersampling to clean up the jaggies on ridges.

Changed the material and tesselation settings to be per LOD now. Little demo of tesselation in action.

Refactoring work has been merged back into now, 4.14 ready!

Getting back to work on the foliage system.

Thought I’d have a go at some erosion…didn’t think it would work well with the tiling but to my surprise it looks pretty good!

http://image.prntscr.com/image/efcf2bf3419645d6938fb377a3bca96b.png

The erosion is looking better! I’ve been tracking the progress on this for a couple months now. Great work!

UE4 could really use something like this.

Curious, and not sure if this has been answered already.
Is this a plane based system? for example, is it all one giant plane? It does seem to appear that way; or does this plugin possess the capabilities to create a game where the it can generate a procedural world, but on a spherical-like planet, capable of views this distance and relationship from afar, for example the moon?

I would suspect not but it would be interesting to see something like I described.

Either way, great work!

The erosion looks really good so far :smiley:

erosion looks great!

Sorry thought I’d already replied!

It’s just plane based so no good for a planet in it’s current state…although my analysis of No Man’s Sky leads me to believe it is the same system they use when on-planet…and then change to a sphere-based planet during the atmospheric transition .

Been super ill all week, but have tinkered with erosion settings a bit.

Video of the hydraulic erosion :

Code is on this branch that has become a staging branch of sorts :

Erosion on the mountains I’m pretty happy with, but I want it to behave better on the flatter sections…it’s very crude at the moment. In fact, here it is…in it’s totally unoptimised state. That’s running 200,000 times per tile in the demo IIRC


void FCGTerrainGeneratorWorker::ProcessSingleDropletErosion()
{
	int32 XUnits = GetNumberOfNoiseSamplePoints();
	int32 YUnits = XUnits;

	// Pick a random start point that isn't on an edge
	int32 cX = FMath::RandRange(1, XUnits - 1);
	int32 cY = FMath::RandRange(1, YUnits - 1);

	float sedimentAmount = 0.0f;
	float waterAmount	 = 1.0f;
	FVector velocity = FVector(0.0f, 0.0f, 1.0f);
	

	while (waterAmount > 0.0f && cX > 0 && cX < XUnits - 1 && cY > 0 && cY < YUnits - 1)
	{
		FVector origin = (*pHeightMap)[cX + (XUnits * cY)];
		FVector up = ((*pHeightMap)[cX + (XUnits * (cY + 1))] - origin).GetSafeNormal();
		FVector down = ((*pHeightMap)[cX + (XUnits * (cY - 1))] - origin).GetSafeNormal();
		FVector left = ((*pHeightMap)[cX + 1 + (XUnits * (cY))] - origin).GetSafeNormal();
		FVector right = ((*pHeightMap)[cX - 1 + (XUnits * (cY))] - origin).GetSafeNormal();
		
		FVector upleft = ((*pHeightMap)[cX + 1 + (XUnits * (cY + 1))] - origin).GetSafeNormal();
		FVector downleft = ((*pHeightMap)[cX + 1 + (XUnits * (cY - 1))] - origin).GetSafeNormal();
		FVector upright = ((*pHeightMap)[cX - 1 + (XUnits * (cY + 1))] - origin).GetSafeNormal();
		FVector downright = ((*pHeightMap)[cX - 1 + (XUnits * (cY - 1))] - origin).GetSafeNormal();

		FVector lowestRoute = FVector(0.0f);

		int32 newCx = cX;
		int32 newCy = cY;

		if (up.Z < lowestRoute.Z) { lowestRoute = up; newCy++; }
		if (down.Z < lowestRoute.Z) { lowestRoute = down; newCy--; }
		if (left.Z < lowestRoute.Z) { lowestRoute = left; newCx++; }
		if (right.Z < lowestRoute.Z) { lowestRoute = right; newCx--; }
		if (upleft.Z < lowestRoute.Z) { lowestRoute = upleft; newCy++; newCx++; }
		if (upright.Z < lowestRoute.Z) { lowestRoute = upright; newCy++; newCx--; }
		if (downleft.Z < lowestRoute.Z) { lowestRoute = downleft; newCy--; newCx++; }
		if (downright.Z < lowestRoute.Z) { lowestRoute = downright; newCy--; newCx--; }

		// The amount of sediment to pick up depends on if we are hitting an obstacle
		float sedimentUptake = pTerrainConfig->DropletErosionMultiplier * FVector::DotProduct(velocity, lowestRoute);
		if (sedimentUptake < 0.0f) { sedimentUptake = 0.0f; }

		sedimentAmount += sedimentUptake;

		float sedimentDeposit = 0.0f;
		// Deposit sediment if we are carrying too much
		if (sedimentAmount > pTerrainConfig->DropletSedimentCapacity)
		{
			sedimentDeposit = (sedimentAmount - pTerrainConfig->DropletSedimentCapacity) * pTerrainConfig->DropletDespositionMultiplier;
		}

		// Deposit based on slope
		sedimentDeposit += sedimentAmount * FMath::Clamp(1.0f + lowestRoute.Z, 0.0f, 1.0f);

		sedimentAmount -= sedimentDeposit;
		

		velocity = lowestRoute;

		//(*pHeightMap)[cX + (XUnits * cY)].Z -= sedimentUptake + (sedimentDeposit * -1.0f);
		erodeHeightMapAtIndex(cX,cY, (sedimentUptake + (sedimentDeposit * -1.0f)));
		
		waterAmount -= pTerrainConfig->DropletEvaporationRate;

		cX = newCx;
		cY = newCy;

	}

}

Man I really need to get rid of that OceanPlugin water for something that works with this project properly!

Great asset but I need something that I can integrate with the heightmap to smooth out the displacement on shorelines.

AFAIK there’s some stuff for that either in the thread for the OceanPlugin, or in another thread related to it. Not sure how it worked, though, but for the needs of this project specifically I’m not sure what would work best since you need some sort of data about the terrain elevation to do it - distance fields, height map in the material, etc., which of course is an when the terrain is created at runtime.