Tuesday, 5 November 2013

Hi guys! ^_^

Due to popular demand, I have decided to do a tutorial on how to use noise to create interesting terrain for games. This is Part A, and in Part B I will be covering how to use the noise for terrain.

Part 0: Preface

In this section, I’m just pointing out a few facts that may be interesting to note. You can skip it if you want :P

The most commonly used form of noise in computing is Perlin Noise. It was created by Ken Perlin, back in 1982 for use with the Tron movie. A very innovative use of technology that has now become the bread and butter for many effects ad textures. Perlin Noise is pretty good, but has a few flaws, and in 2001 Ken developed Simplex Noise. The two look extremely similar, and so for our purposes we can pretty much use them interchangeably. For example, one of the more annoying flaws of Perlin Noise is that it greys out at integer values, so you have to rotate your inputs in order to avoid this. I am using Simplex Noise, because it’s a bit nicer and also a bit faster. Also, it totally sounds cooler.

Thanks for a few games like Worms, Minecraft and Terraria, the concept of using noise to generate terrain for games has become quite popular. I love it – now let’s do it! :D

Part 1: Getting Set up!

Ok, so first thing’s first! Grab the code here!.

Now, I’ve set this library up in a really simple(x) way (lol, I’m terrible for puns). The only thing you need to care about is the object “NoiseGen”. It has 3 constructors…

  1. NoiseGen() – this will set it up with the default values.
  2. NoiseGen(double pScale, byte pOctaves) – this is the one you’ll probably use the most. It sets the X and Y scales to the specified value, and sets the number of octaves you want in your noise – I’ll cover what this means in a second.
  3. NoiseGen(double pXScale, double pYScale, byte pOctaves) – this is handy if you want separate X and Y scales… ie. terrain that is “taller”, for high mountains or some such…

So inside the object there are 4 values…

  1. double XScale = 0.02 – sets the scale for the X component of the noise pattern
  2. double YScale = 0.02 – sets the scale for the Y component of the noise pattern
  3. double ZScale = 1 – sets the scale for the Z component of the noise pattern, which is primarily used for animation or seed values (time / random)
  4. byte Octaves = 1 – sets the number of octaves you want the noise to show

That’s it! I kept it really simple so it would be less confusing, but it still does pretty much everything you would want. Now to set up some code to actually produce some noise! Woo!

So let’s start with a new XNA project (XNA Game Studio 4.0 – Windows Game 4.0). I’m calling mine NoiseTest, because I love creative and interesting names.

Alright, F6, F5 – nice blank CornflowerBlue screen. Nice. Ok, now let’s add in the Noise.cs file. And we’re ready to start using it! Oooooh yea!

Part 2: Let’s Make Some Noise! :D

Now, of course, in your actual game project you’ll want some infrastructure, but for the purposes of this tutorial, I’m going to do it with nothing but what we start with, as everyone will have different infrastructure. For demonstration purposes, we’re just going to display the noise on a texture.

So, right after the class declaration:
const int textureSize = 200; // the size of the texture we'll be playing with, I chose 200 at random, and 300 ran a bit slowly
Texture2D noiseTexture; // the actual texture we'll be using to display some noise
Noise.NoiseGen noiseGen = new Noise.NoiseGen(); // the magical noise generator, yay!

Somewhere in Initialize:
IsFixedTimeStep = false; // sadly Fixed Time Step is very buggy in XNA - I won't go into the reasons here

At the end of LoadContent:
noiseTexture = new Texture2D(GraphicsDevice, textureSize, textureSize); // create the texture

In Update:
GraphicsDevice.Textures[0] = null; // this is a nice trick to prevent XNA complaining that we're trying to edit a texture that's currently in use

Color[,] colors2D = new Color[textureSize, textureSize]; // a nice 2d array for our texture
for(int x = 0; x < textureSize; x++) {     for(int y = 0; y < textureSize; y++)     {         double noise = noiseGen.GetNoise(x, y, 0); // get the noise at the current position (a value from 0.0 - 1.0)         byte value = (byte)(255 * noise); // turn that value into a byte (0 - 255)         colors2D[x, y] = new Color(value, value, value); // turn that value into a color     } } Color[] colors1D = new Color[textureSize * textureSize]; // convert the 2d array into a 1d array - this code will normally be in your infrastructure for(int x = 0; x < textureSize; x++)     for(int y = 0; y < textureSize; y++)         colors1D[x + y * textureSize] = colors2D[x, y]; noiseTexture.SetData(colors1D); // update the texture with our new values

In Draw:
spriteBatch.Begin();
spriteBatch.Draw(noiseTexture, new Vector2(0, 0), Color.White); // render it!
spriteBatch.End();

And that will spit out this little sucker (picture at size 300):

So this is using the default scale and octave values in NoiseGen – namely a scale of 0.02 and a single octave. Now, don’t be surprised if it runs a little sluggishly, noise is relatively “computationally expensive” to generate! That’s why Minecraft and Terraria take so long to generate terrain, even though the blocks are so relatively large (compared to pixels).

Part 3: Octave Noise

So the scale values obviously affect the “size” or “zoom level” of the noise pattern, but what about the octave value? Well, the octave value controls how many levels of noise are layered on top of one another. For example, if set to 2 octaves, it will create one layer of noise at 100% scale just like normal, but then it will layer on another level of noise that’s twice as “fine grained”. An octave value of 3 will then add a 3rd layer of extra detail into the noise.

Feel free to have a play with these values. You can make some nice looking noise. For example, scale 0.01 and 5 octaves will produce this:

Nice smokey looking noise :)

Note that increasing the octaves up past 5 for this scale won’t really have any visible effect. Also it will be really slow and unresponsive :)

Part 4: Animated Noise

Just for fun, here is how you can animate the noise :)

Now I recommend setting your NoiseGen object to default values at first – mainly because you want to start with only 1 octave… or you’ll probably suffer form terrible performance.

After your initial declarations at the top of the class, add this in:
float timer = 0;

Somewhere at the start of Update, add this in:
timer += 0.01f;

And then find the line where you call noiseGen.GetNoise and add in the Z value of timer:
double noise = noiseGen.GetNoise(x, y, timer); // get the noise at the current position (a value from 0.0 - 1.0)

Run that and you’ll get some trippy animating noise, yay! Now, if your computer can handle it, add in some extra octaves, maybe set it to 3, and see how it goes :)

So as you can see, you can get an unlimited amount of 2d noise patterns, using different Z values – this is extremely useful, as not only can you animate noise, but you can also use the Z value as a seed to generate different worlds.

Alright, that concludes Part A of the noise tutorial! Within the next few days I’m hoping to create the second part, which will focus on actually using this noise to generate usable terrain in games! This will include how to separate the ground from the sky, etc. Stay tuned!

Categories: Dev — NightCabbage @ 4:15 pm
Cabbynode Games

3 Comments »

  1. This example has been very useful. Any idea how i would make it tilable?

    Comment by Jason — December 17, 2013 @ 1:49 pm

  2. You sure can! The way I would do it is by fading in from the edges. So choose a fade distance, and for example, make the right edge fade into the same as what’s on the left edge. If you do it right, you shouldn’t even be able to see a seam :)

    Also, this is something I should write about in part 2 of the guide… good idea!

    Comment by NightCabbage — December 17, 2013 @ 2:27 pm

  3. Oh yes, finally a terrain noise tutorial which doesn’t stab you in the brain and throw your body to the ocean, thank you! Part b coming soon ? ;)

    Comment by Temeez — December 27, 2013 @ 7:31 pm

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by WordPress