Java-Gaming.org
 Featured games (81) games approved by the League of Dukes Games in Showcase (492) Games in Android Showcase (112) games submitted by our members Games in WIP (556) games currently in development
 News: Read the Java Gaming Resources, or peek at the official Java tutorials
Pages: [1]
 ignore  |  Print
 How to generate Perlin Noise in Java?  (Read 3474 times) 0 Members and 1 Guest are viewing this topic.
trollwarrior1
 « Posted 2013-12-23 14:49:27 »

So, yesterday while I was in bed, I couldn't fall asleep. So I figured out the way that the S-curve works, and I played with it a little while today. I managed to make my perlin noise work! It would need some improvement though. I'm still using java.Random class. If I wasn't using it, maybe performance would improve. What I have done differently from my first attempt, is now I generate random direction values that are length of 1. Also, I swapped the interpolation values a little. First, I calculate interpolated value between SV and TU using xd00.y as my weight. Then I interpolate based on xd00.x weight. This magically worked, but I don't know why, but my noise looks kinda crappy. Not in sense of quality, but Simplex Noise looks a lot better for some reason. Anyway, here is the code. If there is some kind of expert here, please do tell if this is actually Perlin's Noise correct algorithm.

It is pretty long code.. Thought I better put in to pastebin, because it was pretty hard to read in post.
http://pastebin.java-gaming.org/3b0691d8474

I documented this code a little bit. I followed this tutorial to make it. Read it, because I think code is confusing for someone who doesn't know what is going on.

Here are some images generated using the code above.
Low frequency.

High frequency.

High frequency, high contrast.

I would really like for someone to explain to me how to generate random numbers from -1 to 1 for x, y based on some kind of random seed. I think it would speed up the algorithm even further.

RANDOM STUFF BELOW WHY DID I PUT IT THERE.

 1  2 `Random random = new Random();Link randomLink = random.nextLink();`

Lol I love to watch Notch coding. <3 that keyboard sound.
StumpyStrust
 « Reply #1 - Posted 2013-12-23 17:54:03 »

Well based on the title alone I would say you do it like you do in every other language. No special java'isms.

When resizing images for fake/pseudo Perlin noise, make sure to turn on bi-linear filtering.

tom_mai78101
 « Reply #2 - Posted 2013-12-24 02:59:30 »

Here's how you can implement your own Perlin Noise:

1. Go watch this Twitch livestream here.
2. Go to the time frame: 3:25:00. (Or seek the video to 3 hours 25 minutes in.)
3. Watch the developer create a Perlin Noise, with a little bit of commentary, IN ACTION!!
trollwarrior1
 « Reply #3 - Posted 2013-12-24 05:48:17 »

Here's how you can implement your own Perlin Noise:

1. Go watch this Twitch livestream here.
2. Go to the time frame: 3:25:00. (Or seek the video to 3 hours 25 minutes in.)
3. Watch the developer create a Perlin Noise, with a little bit of commentary, IN ACTION!!

Hey its Notch again! Thanks for the link.
Roquen
 « Reply #4 - Posted 2013-12-24 09:19:15 »

Attempt to search the forum now and then.  Look at the local wiki page.  (required yet again repeat:  this is not perlin noise)
trollwarrior1
 « Reply #5 - Posted 2013-12-24 09:26:16 »

Attempt to search the forum now and then.  Look at the local wiki page.  (required yet again repeat:  this is not perlin noise)

I guess this should be only called "height map".
What I'm thinking you're trying to imply, is that Perlin Noise is a height map, which is generated by a specific technique, which was developed by Perlin.
Then I will call this Chris Noise.
opiop65

JGO Kernel

Medals: 154
Projects: 7
Exp: 3 years

JumpButton Studios

 « Reply #6 - Posted 2013-12-24 14:44:40 »

No, this is just a heightmap generated using what seems to be some sort of averaged noise, although I can't tell very well. Its not Perlin Noise.

Also, any image can be used as a heightmap, it doesn't matter what kind of noise algorithm you use.

trollwarrior1
 « Reply #7 - Posted 2013-12-24 15:57:57 »

No, this is just a heightmap generated using what seems to be some sort of averaged noise, although I can't tell very well. Its not Perlin Noise.

Also, any image can be used as a heightmap, it doesn't matter what kind of noise algorithm you use.

So how is Perlin Noise different from this height map?
opiop65

JGO Kernel

Medals: 154
Projects: 7
Exp: 3 years

JumpButton Studios

 « Reply #8 - Posted 2013-12-24 16:20:28 »

First off, Perlin Noise is an algorithm, not a heightmap. You can generate other besides height maps with noise algorithms.

The difference? Perlin Noise would probably produce much 'cooler' height maps. Using Perlin Noise you can generate different types of images, including cloud like heightmaps, which makes for realistic terrain in games. The one you have right now would be very 'spiky', and not really realistic at all.

philfrei
 « Reply #9 - Posted 2013-12-24 21:25:02 »

Your noise effect has an odd grid pattern built in. But it does look nicely noisy and all that. And the implementation looks pretty fast, too, which could be a very useful tradeoff. My head-cold's a little too painful right now to look at your code more closely and try and figure out if the noise is "gradient" or "value" noise.

There is a GREAT article explaining the mathematics behind Ken Perlin's gradient noise:

http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf

Or you could check out the lecture by KP himself:
http://www.noisemachine.com/talk1/index.html

The wiki page Roquen was referring to on our site brings all this up and more and is well worth checking out.

The Perlin algorithm's are cool to a large degree because of the level of control they give the programmer to sculpt various textures. I'm not sure if "value" noise can be so easily sculpted. (The concept of octaves in Perlin noise is very useful. Can value noise bands be created at multiples of a given frequency as easily as with Perlin noise?)

I have a tool up (java applet) that will probably become unavailable at the end of the year thanks to new signing requirements. It has a gallery of various effects.

http://www.java-gaming.org/topics/sivi-2d-simplex-noise-visualizer-tool/30187/msg/278229/view.html#msg278229

Ah, there is a link that allows the download of the jar. That is probably a better way to run it, anyway.

Clicking on the gallery image (Menubar: View/Gallery) will set up the tool with the parameters for that image, and allows you to edit/tweak the settings and see what happens. There is also a demo-template to help explain how the settings in the app tie into the algorithm. But I don't go into explaining the algorithm itself. Gustavson is my favorite for that.

We had a code generator working, but I broke it when I 'improved' the way gradients are used as the subject of noise modulation, and it hasn't been rebuilt.

"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
tom_mai78101
 « Reply #10 - Posted 2013-12-25 05:59:12 »

Quote
Your noise effect has an odd grid pattern built in. But it does look nicely noisy and all that. And the implementation looks pretty fast, too, which could be a very useful tradeoff. My head-cold's a little too painful right now to look at your code more closely and try and figure out if the noise is "gradient" or "value" noise.

This is actually Notch's noise effect algorithm, taken from Twitch livestream. I'm interested in your quote, especially in:
• How did you "see" that it has an odd grid pattern? From a few noise map patterns, I see no differences. I probably lack experiences, henceforth.
• You say the implementation looks pretty fast, and it could be a useful tradeoff. What tradeoff are you thinking about?
philfrei
 « Reply #11 - Posted 2013-12-25 06:28:42 »

It seems to be comprised of squares approximately 1x1mm in size on my screen. But not exactly that, more like I'm looking through a semi-opaque glass with a grid pebbling on it, with obvious vertical and horizontal gradations occurring at that frequency. Maybe this has to do with the resolution of this algorithm.

The Simplex implementation I've been using tends to lead more towards hexagons and triangles. And they are not as obvious.

The tradeoff I was referring to was between performance and the graphical effect. Perlin's algorithms are pretty efficient, but they still have a significant cost in terms of cpu. Something that can give "good enough" noise that takes less cpu than Perlin noise could be useful in some contexts.

"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
Longarmx
 « Reply #12 - Posted 2013-12-25 06:52:32 »

I used this code and quickly came up with a simple little demo. I basically just re-implemented TheCodingUniverse's heightmap tutorial with random terrain generation.

Here is a jar and source(look in the world file for usage, look in the noise package for implementation) if you want to test it out.

trollwarrior1
 « Reply #13 - Posted 2013-12-25 07:58:42 »

It seems to be comprised of squares approximately 1x1mm in size on my screen. But not exactly that, more like I'm looking through a semi-opaque glass with a grid pebbling on it, with obvious vertical and horizontal gradations occurring at that frequency. Maybe this has to do with the resolution of this algorithm.

The Simplex implementation I've been using tends to lead more towards hexagons and triangles. And they are not as obvious.

The tradeoff I was referring to was between performance and the graphical effect. Perlin's algorithms are pretty efficient, but they still have a significant cost in terms of cpu. Something that can give "good enough" noise that takes less cpu than Perlin noise could be useful in some contexts.

Umm..... I don't think you understand the problem here. This image was done in 64x64 or 128x128 resolution. That is why it is "blocky". What I mean is that those squares are individual pixels, stretched on 512x512 image.

Here is a smooth looking image:

And my implementation is really slow. Here is my current code. It allows to adjust the size of these noise areas. You can make a first heightmap really small, and then stretch it onto huge height-map and resample it a lot of times (64 and more) and it will give you a really smooth height-map with huge noise areas.
Here is an example:

if I want to generate a 512x512 smooth image with "huge" noise areas, it takes about 5 seconds... It is really slow.. I will need to learn Perlin / Simplex noise for proper use.
Roquen
 « Reply #14 - Posted 2013-12-25 13:34:09 »

It's a value noise variant.  5 sec for 512x512...crazy.  Look at the wiki page. http://www.java-gaming.org/topics/noise-bandpassed-white/27071/view.html
philfrei
 « Reply #15 - Posted 2013-12-26 02:20:39 »

@trollwarrior1 Yes, the smooth image looks more like what I'd expect. Sorry to hear the implementation is so slow. Definitely check out Roquen's link, and consider using Gustavson's Simplex implementation (I cited earlier--it is linked in his article).

@Longarmx -- Pretty cool! The StackOverflow link shows that the base implementation is Gustavson's.

"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
tom_mai78101
 « Reply #16 - Posted 2013-12-26 04:24:16 »

Speaking of base implementations, what is Notch's algorithm's base implementation? It looks like the diamond-square method, but I'm not confident enough to say it's the correct answer.
opiop65

JGO Kernel

Medals: 154
Projects: 7
Exp: 3 years

JumpButton Studios

 « Reply #17 - Posted 2013-12-26 04:26:18 »

No, its not diamond square, its far simpler and way less CPU intensive. I believe its gradient noise, but someone else already said it could also be value noise. I don't know much about this certain algorithm type, so I could not tell you.

Roquen
 « Reply #18 - Posted 2013-12-26 06:17:32 »

Sigh.  Reading comprehension is a useful skill.

On a different topic.  Never ever use java.util.Random.
trollwarrior1
 « Reply #19 - Posted 2013-12-26 09:14:49 »

This is really slow and stuff. Can't you read the code plox?

First, I create an array of doubles, which I fill with random doubles from -1 to 1.

 1  2  3  4  5  6  7 `      values = new double[width * height];      for (int y = 0; y < height; y++) {         for (int x = 0; x < width; x++) {            values[x + y * width] = random.nextDouble() * 2 - 1;         }      }`

Then I just "blend" nearby pixels together.
 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21 `for (int y = 0; y < height; y++) {            for (int x = 0; x < height; x++) {               double a = getSample(x, y);               double b = getSample(x + 1, y);               double c = getSample(x + 1, y + 1);               double d = getSample(x, y + 1);               double e = getSample(x - 1, y + 1);               double f = getSample(x - 1, y);               double g = getSample(x - 1, y - 1);               double h = getSample(x, y - 1);               double j = getSample(x + 1, y - 1);               double z = (a + b + c + d + e + f + g + h + j) / 9 * mult;               if (z > 1) z = 1;               if (z < -1) z = -1;               setSample(x, y, z);            }         }`

Blending pixels only 1 time doesn't do the trick, so you need to blend them a few times over and over again. After blending them a few times, you get something that looks like Perlin Noise. Just read the code plox. It is pretty simple..
Roquen
 « Reply #20 - Posted 2013-12-26 09:23:11 »

Stop messing around with this.  Look at the wiki.  This is filling an array with white noise then doing multiple passes of a bad box filter.  This is insanely slow and very poor quality...you're wasting your time.  Use a real noise generation function from from the last 30 years.
Longarmx
 « Reply #21 - Posted 2013-12-26 16:28:42 »

Take a look at the simplex noise code I linked you to. With this code, it can generate a 512x512 in 79ms. It can also generate 10000x10000 (10 billion) points in 39.8s. With the code you have, generating a (smooth) 512x512 takes 5s. If you tried to generate 10000x10000, it would take almost 53 HOURS.

trollwarrior1
 « Reply #22 - Posted 2013-12-26 17:43:28 »

Take a look at the simplex noise code I linked you to. With this code, it can generate a 512x512 in 79ms. It can also generate 10000x10000 (10 billion) points in 39.8s. With the code you have, generating a (smooth) 512x512 takes 5s. If you tried to generate 10000x10000, it would take almost 53 HOURS.

THanks, I didn't notice the link to stackoverflow earlier. I just copy/pasted the code and it works perfectly. My head is going to break at the awesomeness of people who can create such maths. I want to able to do something like that too some day.
philfrei
 « Reply #23 - Posted 2013-12-26 19:41:02 »

@trollwarrior1

Thanks for giving an explanation of the code. Earlier, I only read as far as seeing the array being filled with randoms, and things got "fuzzy" with the box filter step. I definitely have room to improve with my code reading skills.

I think it is neat that a decent noise/cloud can be generated this way. It does has the benefit of using very little code. But the inefficiency is pretty awful compared to other techniques that are readily available.

Math is awesome. Do stick with it in school! (I didn't do so as much as I now wish I had.) I think that the path to being able to create maths comes not just from study, but from playing with it, exploring on the way, as you are already doing.

"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
trollwarrior1
 « Reply #24 - Posted 2013-12-27 09:02:51 »

So I think I worked out the Perlin Noise algorithm at last (Check the modified original post. I put everything in there). Now what I need to do, is to make it kinda random.

Is there anyone who knows how to generate random numbers between -1 and 1 based on x,y and seed?
Roquen
 « Reply #25 - Posted 2013-12-27 09:04:13 »

If you were to look at the local wiki page there are links to working implementations in java.
matheus23

JGO Kernel

Medals: 106
Projects: 3

You think about my Avatar right now!

 « Reply #26 - Posted 2013-12-27 14:43:24 »

Is there anyone who knows how to generate random numbers between -1 and 1 based on x,y and seed?

This is exactly the problem I encountered. Once upon a time I made a forum topic about that, too and Roquen helped me out. This is what came out of it in the end:

 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16 `private static long hashWang(long key) {    key = (~key) + (key << 21); // key = (key << 21) - key - 1;    key = key ^ (key >>> 24);    key = (key + (key << 3)) + (key << 8); // key * 265    key = key ^ (key >>> 14);    key = (key + (key << 2)) + (key << 4); // key * 21    key = key ^ (key >>> 28);    key = key + (key << 31);    return key;}private FastRand getRand(int x, int y) {    rand.setSeed(hashWang((x << 17) ^ y) + seed);    return rand;}`
(look at it on github)

FastRand in the end uses simple xor logic for generating a random boolean:
 1  2  3  4  5  6  7  8  9 `public long randLong() {    seed ^= (seed << 21);    seed ^= (seed >>> 35);    seed ^= (seed << 4);    return seed;}public boolean randBool() {    return randLong() > 0;}`

Though it might be sufficient to use the first bit (bit no. 0) of the hashWang result:

 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15 `private static long hashWang(long key) {    key = (~key) + (key << 21); // key = (key << 21) - key - 1;    key = key ^ (key >>> 24);    key = (key + (key << 3)) + (key << 8); // key * 265    key = key ^ (key >>> 14);    key = (key + (key << 2)) + (key << 4); // key * 21    key = key ^ (key >>> 28);    key = key + (key << 31);    return key;}private boolean getRand(int x, int y) {    return hashWang((x << 17) ^ y) + seed) & 1 == 0; // == 0 should be faster than == 1}`

See my:
My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
trollwarrior1
 « Reply #27 - Posted 2013-12-28 20:58:15 »

Is there anyone who knows how to generate random numbers between -1 and 1 based on x,y and seed?

This is exactly the problem I encountered. Once upon a time I made a forum topic about that, too and Roquen helped me out. This is what came out of it in the end:

 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16 `private static long hashWang(long key) {    key = (~key) + (key << 21); // key = (key << 21) - key - 1;    key = key ^ (key >>> 24);    key = (key + (key << 3)) + (key << 8); // key * 265    key = key ^ (key >>> 14);    key = (key + (key << 2)) + (key << 4); // key * 21    key = key ^ (key >>> 28);    key = key + (key << 31);    return key;}private FastRand getRand(int x, int y) {    rand.setSeed(hashWang((x << 17) ^ y) + seed);    return rand;}`
(look at it on github)

FastRand in the end uses simple xor logic for generating a random boolean:
 1  2  3  4  5  6  7  8  9 `public long randLong() {    seed ^= (seed << 21);    seed ^= (seed >>> 35);    seed ^= (seed << 4);    return seed;}public boolean randBool() {    return randLong() > 0;}`

Though it might be sufficient to use the first bit (bit no. 0) of the hashWang result:

 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15 `private static long hashWang(long key) {    key = (~key) + (key << 21); // key = (key << 21) - key - 1;    key = key ^ (key >>> 24);    key = (key + (key << 3)) + (key << 8); // key * 265    key = key ^ (key >>> 14);    key = (key + (key << 2)) + (key << 4); // key * 21    key = key ^ (key >>> 28);    key = key + (key << 31);    return key;}private boolean getRand(int x, int y) {    return hashWang((x << 17) ^ y) + seed) & 1 == 0; // == 0 should be faster than == 1}`

Thanks for the code.
I implemented it. I might be doing something wrong, but the performance is 3-4 times worse than it was with just generating an array. My method has its limitations, but for small stuff it is pretty slick.
Pages: [1]
 ignore  |  Print

You cannot reply to this message, because it is very, very old.

 Add your game by posting it in the WIP section, or publish it in Showcase. The first screenshot will be displayed as a thumbnail.
 Nickropheliac (15 views) 2014-08-31 22:59:12 TehJavaDev (23 views) 2014-08-28 18:26:30 CopyableCougar4 (33 views) 2014-08-22 19:31:30 atombrot (41 views) 2014-08-19 09:29:53 Tekkerue (40 views) 2014-08-16 06:45:27 Tekkerue (35 views) 2014-08-16 06:22:17 Tekkerue (25 views) 2014-08-16 06:20:21 Tekkerue (37 views) 2014-08-16 06:12:11 Rayexar (72 views) 2014-08-11 02:49:23 BurntPizza (49 views) 2014-08-09 21:09:32
 BurntPizza 38x Rayvolution 30x kevglass 28x Riven 27x princec 25x Longor1996 15x PandaMoniumHUN 12x Roquen 11x basil_ 10x theagentd 10x gouessej 9x ags1 9x nsigma 8x SHC 7x trollwarrior1 7x cylab 7x
 List of Learning Resources2014-08-16 10:40:00List of Learning Resources2014-08-05 19:33:27Resources for WIP games2014-08-01 16:20:17Resources for WIP games2014-08-01 16:19:50List of Learning Resources2014-07-31 16:29:50List of Learning Resources2014-07-31 16:26:06List of Learning Resources2014-07-31 11:54:12HotSpot Optionsby dleskov2014-07-08 01:59:08
 java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org