Procedural Generation using Noise

So for my final year of Uni I decided upon writing my dissertation on the merits of procedural generation, with the practical side being that I generate a fairly basic solar system with orbital paths and procedurally generated textures. However, I’ve hit a snag as I have absolutely no idea what I’m doing. The noise function in the UE4 Material Editor is depressingly basic, with no real levels of customisation or fine tuning that could allow me to generate reasonably earth-like looking planets. I know I’ll probably have to delve into C++ using libnoise, but is it possible to do the following using purely blueprints:

Generate and texture earth-like planets, rocky moons, and reasonable looking star surfaces?

I’ve maybe about 10 hours experience using the engine now, looking up reference guides for blueprints, but there is still a lot I don’t understand. I understand the blueprint system is very powerful, but I imagine it does have limitations, and I notice that there aren’t other noise functions that might be useful (like Voronoi noise for rocky planets)

Have you looked at Substance Designer? This will help you generate textures that can be tweaked at runtime.

It depends on how detailed you need these planets to be. For instance, if you want to actually shape the mesh, you are going to want to delve into C++ as their procedural mesh sculpting in blueprint isn’t quite there yet.

If you just want to have procedurally textured spheres and properly populated solar systems, then blueprint and the material editor can accomplish what you are after. But, you are going to have to figure out the noise functions you need and create them in blueprint/material editor. I use voronoi for my map generation, but it is all built from scratch.

Yeah, I was looking at your map generator which is really impressive, but its just trying to figure out to what extent the blueprint/material editor can do this stuff. I imagine you can create custom noise functions but only in the blueprint editor using math expressions. When I look at procedural texture generation in the UE4 wiki its only in C++ and it requires the use of an already existing texture, which makes no sense to me since I thought the whole idea is to create a texture using only algorithms.

I haven’t use Substance Designer, but as far as I can see its an external tool, and the main idea is to be able to generate a texture from scratch using a custom made noise function, tweaked for earth-like planets to make it look realistic.

So I talked with my supervisor and he suggested that I use something like Java to generate a heightmap with whatever noise function I create, and I can pass it into UE4 which would automatically load it when the editor starts up. Would this be a more viable option? My project is mainly more about the concept behind the generation rather than rendering it in Unreal Engine.

If you are doing your thesis shouldn’t you have a pretty decent understanding of programming anyway? Generating a complex texture within unreal is not really it’s intended function so you are definitely going to have to work with some code to get it done. Having said that there are plenty of other ways of generating procedural items that don’t rely on using a heightmap/texture map to create them.

Well I kinda do, but only with Java. C++ feels like a completely different animal given the manual memory allocation, destructors and generally different structure, not to mention the use of header files. Can UE4 automatically detect any textures that are created by external programs and then apply them to objects?

Maybe off-topic suggestion: If you don’t want to learn c++ and don’t care about visuals so much, there are a lot of simpler engines out there that can draw textured objects.

What your professor suggested sounds good (making your own basic noise function and sampling that).

For what it is worth, you can do all of that inside of the Custom node in materials. I’d suggest first starting with some simple Value noise. That is a style of noise that is often confused with perlin noise. First make a simple psuedorandom number code (ie… frac(x * SomeLargePrimeNumber * (x + some largeprimenumber)) as a super basic example). The idea is it needs to return the same value for a given input.

Then make some code to sample it at intervals… which is basically like taking floor of current value and then using frac of that number to lerp between random(x) and random(x+1).

Then you just need a line that adds octaves of the noise, where the scale gets doubled and the intensity multiplied by persistence at each step.

Should be possible to get a basic version of that with only a few lines of code.

The difference between Perlin noise and this simple value noise is that perlin noise uses a bunch of random vectors to generate gradient maps instead of using raw pseudo random numbers but the code is way longer for perlin.

fwiw a simple value noise in the custom node is something I want to do soon as well but I keep getting assigned other tasks. I wanted to do it for experimenting with clouds.

Oh, cool. So when you say starting with some simple value noise, do you mean creating a math expression to do so? I haven’t started looking into the algorithms yet for generating noise, but I will do in the coming days. I’ve just been starting with the basics and trying to get a feel for how I want the flow of the program. In reply to the suggestion of using another engine, I picked UE4 mainly because I’d like to have some experience in using it for when I graduate, maybe to help with applying for game development careers.

Yes I am talking about the custom node in materials. It is a place to write hlsl script. It is a very simple language compared to c++.

Just to throw my input in there, you’re most definitely going to want to make your own custom noise node. The noise node that is built into UE4 can do some neat things but as soon as you want to do anything really outside the box with it, you start to see the limitations it has.

f0d9ce81a2e0a5843fd25c4ab4fd6037c5abef46.jpeg

I worked on this little planet shader for about half a day before I realized what I wanted to do wasn’t really possible with the tools at hand.
It has clouds, a basic atmosphere, landmasses, city lights, and normals…that are all generated from scratch. However, it was hell getting all that to work and in reality it only looks like that in the material editor. It basically broke when I brought it into world space.

The main issue I had is that the noise node does not play well with being colorized, like…at all. I had to do some serious workarounds to get the clouds and city lights working (couldn’t overlay the clouds or lights, so had to combine them and then plug them into the emissive channel), so yeah, you’re going to want to make your own noise node. Also, look at that instruction count; it’s enormous. The noise node is pretty expensive to use, so you have to consider that as well.

Edit: @RyanB Is it possible to look at the underlying code that the material nodes have? I’ve wanted to crack open the standard noise node for a really long time but have never known if it was possible or not.

Yes you can find all of the material nodes under:

Engine\Source\Runtime\Engine\Classes\Materials\

For example the noise header is:

Engine\Source\Runtime\Engine\Classes\Materials\MaterialExpressionNoise.h

The actual code for most of the nodes is under:

Engine\Source\Runtime\Engine\Private\Materials\MaterialExpressions.cpp

In the case of the Noise function though, the material node references a Noise function from elsewhere that is pretty hard to find.
Look at line 1164 of Engine\Shaders\Common.usf:

Looking at that function, we can see the bulk of the lifting is done by this function (which is conveniently right above the previous line):


float Noise3D_Multiplexer(int Function, float3 Position)
{
	// verified, HLSL compiled out the switch if Function is a constant
	switch(Function)
	{
		case 0:
			return SimplexNoise3D_TEX(Position);
		case 1:
			return GradientNoise3D_TEX(Position);
		case 2:
			return PerlinNoise3D_ALU(Position);
		case 3:
			return FastGradientPerlinNoise3D_TEX(Position);

		// currently not accessible through UI
		default:
			return ComputeRandomFrom3DPosition((int3)Position).x;
	}
	return 0;
}

That calling function loops over this Noise3D_Multiplexer for each level and accumulates the noise while reducing the strength at each iteration by the persistence (invlevelscale ):

Now you could easily follow those function names to research how each of the methods is implemented.


	LOOP for(uint i = 0; i < Levels; ++i)
	{
		// fade out noise level that are too high frequent (not done through dynamic branching as it usually requires gradient instructions)
		OutScale *= saturate(1.0 - FilterWidth);

		if(bTurbulence)
		{
			Out += abs(Noise3D_Multiplexer(Function, Position)) * OutScale;
		}
		else
		{
			Out += Noise3D_Multiplexer(Function, Position) * OutScale;
		}

		Position *= LevelScale;
		OutScale *= InvLevelScale;
		FilterWidth *= LevelScale;
	}

You could easily build a noise function out of these pieces and make your own version of the part that returns the random number.

I do not see how the noise node and your issues are related. You can do all that kind of overlay stuff. If you are having issues applying a color gradient in the way you want, using a different method to generate the gradient will make no difference to the problem. Hooking up the lights to the emissive channel is probably the right thing to do anyways so I don’t see how that is related to issues with the noise node. The only ‘issue’ I am aware of with the noise node is that it can be difficult to get the type of noise you might want.

Also if you are having trouble matching the material preview and a mesh in the world, I suggest you instead use “BoundingBoxBased_0-1_UVW” as the input to position of the noise node since that will use an entirely local coordinate basis. You can still scale it as needed by multiplying.

My main issue was that I was wanting to sample multiple black/white values to colorize and was not finding any efficient means to do so.

As far as the city lights go, yes, hooking those up to the emissive was right. But the deal was that the clouds could not be overlayed or added to the existing colored noise without destroying the colors. So I had to add the clouds and lights together into the emissive channel.

Ah I see. Clouds really shouldn’t need to be emissive though, those you should be able to do a Lerp and blend to the cloud color rather than try to overlay the clouds.

Just gonna ask: What is, in your opinion, a good way to colorize noise with multiple colors? For example, I would want near white values to maybe be snow peaks, whereas the middle areas could be green and sandy for the beach. I have tried this with some success but it’s always been really hacky in method. For the longest time I tried gaining access to the pure black value that the noise node puts off so I could color it as water but failed repeatedly. I’ve tried lerps, but the closest I’ve gotten to success is using a modified 3-Point Levels node.

Also, OP: I am sorry for hijacking your thread. I just have been wondering these things about noise in UE4 for a long time and have never had any replies from an engine dev before.

The easiest way is to use a 1d texture lookup defining the gradient. The other way is to use the Distance node to create a mask for each color band that you want. Then each color band is a Lerp node where the A input includes all previous band lerps, and B is the current band color. You can easily use math to evenly space the bands or specify each band location with a scalar.

Or you could go hardcore and encode the colors manually like I did for this shader complexity preview material. You could make each color an input to the custom node:


float3 colors[10];

colors[0]=float3(0,1,0.127);
colors[1]=float3(0,1,0);
colors[2]=float3(0.046,0.52,0);
colors[3]=float3(0.215,0.215,0);
colors[4]=float3(0.52,0.046,0);
colors[5]=float3(0.7,0,0);
colors[6]=float3(1,0,0);
colors[7]=float3(1,0,0.5);
colors[8]=float3(1,0.9,0.9);
colors[9]=float3(1,1,1);

float cindex = floor((x)*9);
float cphase = frac((x)*9);

return lerp(colors[cindex],colors[cindex+1],cphase);

obviously you need to add an input named x as well and make sure to replace the constant 9 in there with your number of colors minus 1.

Thank you for the reply. Is there any way you could post an example of what you mean with the distance-mask? Been trying that out for awhile and can’t really figure out what you mean by that.

Simple method with evenly spaced colors. Just multiply coordinate by number of bands (4 colors makes 3 ‘bands’ of blending) and then for each alpha, subtract current index as integer.

2610209641e8f0148b9739405439de349b03d9ab.jpeg