Sunday, 10 June 2012

So a while back I was checking out different noise methods for procedural and art generation, and I decided to look into Simplex Noise.

Simplex Noise is basically Ken Perlin’s replacement for classic Perlin Noise. It produces better results, and is a bit faster, too.

I found a really good paper called “Simplex noise demystified”, by Stefan Gustavson, Link√∂ping University (2005).

In it was an algorithm written in Java for 2d, 3d and 4d noise. I ported it to C# for 2d and 3d noise. I didn’t bother porting the 4d noise over, because I’d never use it.

The method signature is as follows:
public static float GetNoise(double pX, double pY, double pZ)

So, you’d call it like this (note that I’ve encapsulated it in a static class called Noise):
float noiseValue = Noise.GetNoise(x, y, z);

It takes doubles for input, as the extra accuracy over floats is needed (floats suck for positional data!), and it returns a single float (between 0 and 1) for the value of the noise at the specified point.

This method is extra handy because you can use it in the following ways…

* Simple 2d noise
Noise.GetNoise(x, y, 0);
and you can replace the z value of 0 with any number you want, giving you a different 2d noise pattern each time (just be sure to use the same Z value for the entire “block” of noise!)
or you could keep z as 0 and modify the x and/or y values to get a different noise pattern, eg. Noise.GetNoise(x + 100, y + 100, 0);

* Animated 2d noise
Noise.GetNoise(x, y, timer);
where timer is a value that changes over time, and you can modify the x, y and/or timer values as above to produce different patterns

* Simple 3d noise
Noise.GetNoise(x, y, z);
full 3d noise, and if you want a different pattern, all you need to do is modify any/all of the values, eg. Noise.GetNoise(x + 100, y + 100, z + 100);

Hope you enjoy the code! :)

-UPDATE-

Have added in a more up to date version of the code, yay! Modified the link for the new code…
Download

Categories: Dev — NightCabbage @ 10:53 pm
Cabbynode Games

19 Comments »

  1. Hi, thanks for sharing this! However when I am using it, a lot of the time it just returns 0.5, I am using it like so:

    for (int MapX = 0; MapX < 10; MapX++)
    {
    for (int MapY = 0; MapY < 10; MapY++)
    {
    for (int MapChunksX = 0; MapChunksX < Game1.MapChunkSize; MapChunksX++)
    {
    for (int MapChunksY = 0; MapChunksY < Game1.MapChunkSize; MapChunksY++)
    {
    Game1.Map[MapX, MapY, MapChunksX, MapChunksY] = PerlinNoise.Noise.GetNoise(MapChunksX * (MapX * 16), MapChunksY * (MapY * 16), 10);
    }
    }
    }
    }
    Is there anyway I can fix it?

    Comment by J4xer05 — August 14, 2012 @ 7:19 pm

  2. Never mind, I fixed it. It was on my end. How could I use this to create islands? Atm I have water and grass, however they look way too fake, you normally only see 3 tiles in a group, then 1 or 2 scattered around. Would using something like multiple layers of noise fix this? If so, how could I control the strength of the noise? e.g Really dark then a tiny amount of grouped white to simulate sea and small land?

    Comment by J4xer05 — August 14, 2012 @ 7:30 pm

  3. Hey, glad you fixed your earlier problem :)

    So, after you get the noise function up and running, there are many ways you can use it.

    To create islands, first you need to “scale” the noise to a level that suits your needs. You can do this by simply passing in values that are closer together. For example, instead of passing it 0, 1, 2, 3, 4, 5… you might pass it 0.0, 0.1, 0.2, 0.3, 0.4, etc. then it will be changed by a scale of 10.

    After you do this, you can apply different functions to get the end result you desire. Simplest method is to check if output > 0.5, and if so, it’s land, if not, it’s sea. By changing this value you can make more land, or more sea (eg. if output > 0.2 would give you a lot more land).

    And after that, you can look up other functions to apply to the output, to give you all sorts of interesting patterns! Gradients are a good way to get noisy edges, etc.

    Happy coding ^_^

    Comment by NightCabbage — August 14, 2012 @ 8:03 pm

  4. Thanks so much for your help! I’ll be sure to show you the game when I have it up to a reasonable level :)

    Comment by J4xer05 — August 15, 2012 @ 9:12 am

  5. Hehe no probs!

    I’ll be looking forward to seeing what you do with it!

    (this reminds me that I really should update my blog more often, haha…)

    Comment by NightCabbage — August 15, 2012 @ 12:57 pm

  6. I thought I should post an update. I have the system up and running now :D

    So here are a few screenshots of it running, the first is of what the game currently looks like, rendering to a few 64×64 textures (Chunks). I have a cosine filter thing that I was messing around with so it looks a bit psychedelic for now. The last two are of what the game looked like when I first got the system working. Using chunks made from 16*16 squares that are 8×8;

    The system runs really slow at the moment as I am recreating the texture every frame. I plan on making it create it, cache it, then just display the results. Replacing the cache as the player gets further away from the tiles.

    Also the colouring of the map is not to my taste. I just threw it up in a hurry lol. There is snow, grass, sand, shallow water, and then ocean. The plan for the texturing will be to create a visually pleasing image of noise that simulates grass, sand, snow etc. Although I am not sure if I can do that lol.

    Enough of the mindless rambling, I don’t want to bore you any longer so here are the screenshots :)

    http://www.mediafire.com/?2j90pr3byv2aara,eptvi35o6u76wdn,4q6rtvhcwqp1tmq

    Oh and updating your blog more would be awesome! The projects you are working on are really cool, and I’d love to see how you make them :)

    Comment by J4xer05 — August 16, 2012 @ 9:16 pm

  7. The implementation may has a bug.

    return (x > 0) ? (int)x : (int)x – 1;

    In my opinion, it should be

    return (x >= 0) ? (int)x : (int)x – 1;

    Comment by Do Hong Ngoc — February 23, 2013 @ 6:44 pm

  8. Thank you for this!
    I’m using this as a basis for heightmap generation.
    I like that there is no visual weirdness as with regular Perlin Noise but I would like a little more of a jagged effect.
    Do you have any suggestions for generating more of a Plasma effect as with regular Perlin Noise?
    This would translate to a more “rocky” looking terrain, which is what I’m after.
    Thanks again! :)

    Comment by TVW — April 6, 2013 @ 4:53 am

  9. Glad you’re making use of it :)

    You can do all sorts of things with noise patterns, it’s quite fun actually!

    If I get a free moment I’ll post a little example for you.

    Also, as a heads-up, I will be posting a newer version of the noise code soon (better code and slightly faster).

    Comment by NightCabbage — April 6, 2013 @ 11:43 am

  10. Thank you SO much for this! I was looking for a straight forward perlin noise sample :)!

    Comment by Remmie — April 15, 2013 @ 4:20 pm

  11. Yup, looks good. Can’t wait to get home tonight to try it! I’m going to use this as part of a procedural planet generator, I’ll be sure to cite you in it if I get it up and running. You saved me from having to decipher that Stefan Gustavson pdf…

    Comment by TravisM — May 29, 2013 @ 3:12 am

  12. I am getting ALOT of 0.5 for some reason. Implementation example is:

    for(int x = 0; x < width; x++)
    for (int y = 0; y < height; y++)
    Console.WriteLine(Noise.GetNoise(x, y, 0));

    Comment by Jay — August 13, 2013 @ 1:01 am

  13. Try using Noise.GetNoise(x *0.1, y *0.1, 0)

    If you’re using integer values you’ll get pure grainy noise, as opposed to nice, soft patterns :)

    Comment by NightCabbage — August 13, 2013 @ 2:09 am

  14. Thanks! Changed it to this:

    Random r = new Random();
    double seed = r.NextDouble;

    for(int x = 0; x < width; x++)
    for (int y = 0; y < height; y++)
    Console.WriteLine(Noise.GetNoise((double)x / 100, (double)y / 100, seed));

    Incredibly smooth now. Thanks so much.

    Comment by Jay — August 13, 2013 @ 2:15 am

  15. Sorry for the double post, your way looks quite a bit better lol. More Terraria looking.

    I was thinking though, I wanted to do a 1D noise to create the terrain level. So anything above a certain value is sky, anything below is ground. Then use the 2D noise to create the cave system, ores, etc.

    That should provide a nice start to a procedurally generated map.

    Comment by Jay — August 13, 2013 @ 2:18 am

  16. Yeah, my original idea was the use 1d noise for the terrain height – and after I implemented it, I just felt like it lacked interest. So I changed it to use 2d noise for the whole thing. Now it has cool features, like caves, overhanging cliffs, and I’ve even got mine doing little floating islands and stuff, because I love using them in game :D

    Let me know if you need a hand with getting this concept set up – basically you use a gradient at the point where you want the land/sky to meet, and then you get a nice noisy surface :)

    Comment by NightCabbage — August 25, 2013 @ 2:41 pm

  17. Hey NightCabbage, Would you mind explaining in more detail(possibly some code snippets?) of how you have the noise functions set up to do that(the 2d noise for terrain generation with a gradient etc..)? Thanks!

    Comment by Brassx — August 28, 2013 @ 6:04 am

  18. @NightCabbage I am interested in learning more as well. Please if you could, explain about the gradient, etc.

    Comment by Jay — October 28, 2013 @ 11:38 am

  19. Ok, so due to popular demand, I have decided to write a tutorial on how to use the noise to generate different terrain types.

    I’ll start with the very basics – using the noise methods to generate multiple octave noise (rendered to a black and white image for the purposes of the tutorial). I’ll then move on to what’s generally known as using a gradient to “fade out” the noise, thus creating nice terrain patterns.

    This goes nicely with the game that I’m about to start making, so perfect timing really.

    Stay tuned :)

    Comment by NightCabbage — November 4, 2013 @ 5:16 pm

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by WordPress