DzzD
|
 |
«
Posted
2011-02-11 20:01:17 » |
|
another fastest something  needing a very fast Perlin noise generator, I look around on internet and did not find anything suitable, so I decided to built my own, absolutly nothing revolutionary it work the same as described by Ken Perlin on his website except that the implementation have been highly optimized. Usage :Raw noise :  Raw noise through a cloud function :  More advanced usage: Click to try Online Applet
  Try online AppletIt can be easily improved to use different or dynamic octave/persistence : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
public class FastNoise { public static int noise(double x,double y,int nbOctave) { int result=0; int frequence256=256; int sx=(int)((x)*frequence256); int sy=(int)((y)*frequence256); int octave=nbOctave; while(octave!=0) { int bX=sx&0xFF; int bY=sy&0xFF;
int sxp=sx>>8; int syp=sy>>8;
int Y1376312589_00=syp*1376312589; int Y1376312589_01=Y1376312589_00+1376312589;
int XY1376312589_00=sxp+Y1376312589_00; int XY1376312589_10=XY1376312589_00+1; int XY1376312589_01=sxp+Y1376312589_01; int XY1376312589_11=XY1376312589_01+1;
int XYBASE_00=(XY1376312589_00<<13)^XY1376312589_00; int XYBASE_10=(XY1376312589_10<<13)^XY1376312589_10; int XYBASE_01=(XY1376312589_01<<13)^XY1376312589_01; int XYBASE_11=(XY1376312589_11<<13)^XY1376312589_11;
int alt1=(XYBASE_00 * (XYBASE_00 * XYBASE_00 * 15731 + 789221) + 1376312589) ; int alt2=(XYBASE_10 * (XYBASE_10 * XYBASE_10 * 15731 + 789221) + 1376312589) ; int alt3=(XYBASE_01 * (XYBASE_01 * XYBASE_01 * 15731 + 789221) + 1376312589) ; int alt4=(XYBASE_11 * (XYBASE_11 * XYBASE_11 * 15731 + 789221) + 1376312589) ; int grad1X=(alt1&0xFF)-128; int grad1Y=((alt1>>8)&0xFF)-128; int grad2X=(alt2&0xFF)-128; int grad2Y=((alt2>>8)&0xFF)-128; int grad3X=(alt3&0xFF)-128; int grad3Y=((alt3>>8)&0xFF)-128; int grad4X=(alt4&0xFF)-128; int grad4Y=((alt4>>8)&0xFF)-128; int sX1=bX>>1; int sY1=bY>>1; int sX2=128-sX1; int sY2=sY1; int sX3=sX1; int sY3=128-sY1; int sX4=128-sX1; int sY4=128-sY1; alt1=(grad1X*sX1+grad1Y*sY1)+16384+((alt1&0xFF0000)>>9); alt2=(grad2X*sX2+grad2Y*sY2)+16384+((alt2&0xFF0000)>>9); alt3=(grad3X*sX3+grad3Y*sY3)+16384+((alt3&0xFF0000)>>9); alt4=(grad4X*sX4+grad4Y*sY4)+16384+((alt4&0xFF0000)>>9); int bX2=(bX*bX)>>8; int bX3=(bX2*bX)>>8; int _3bX2=3*bX2; int _2bX3=2*bX3; int alt12= alt1 - (((_3bX2 - _2bX3) * (alt1-alt2)) >> 8); int alt34= alt3 - (((_3bX2 - _2bX3) * (alt3-alt4)) >> 8); int bY2=(bY*bY)>>8; int bY3=(bY2*bY)>>8; int _3bY2=3*bY2; int _2bY3=2*bY3; int val= alt12 - (((_3bY2 - _2bY3) * (alt12-alt34)) >> 8); val*=256; result+=(val<<octave); octave--; sx<<=1; sy<<=1; } return result>>>(16+nbOctave+1); } }
|
|
|
|
|
|
DzzD
|
 |
«
Reply #2 - Posted
2011-02-11 22:55:10 » |
|
arf!! I just see that another little optimisation can be done (avoiding two cast), source code updated ! changes :1 2 3 4 5 6
| for(int n=0;n<8;n++) { int frequence256=frequence*256; int sx=(int)(x*frequence256); int sy=(int)(y*frequence256); ... |
replaced by : 1 2 3 4 5 6 7 8 9
| int frequence256=frequence*256; int sx=(int)(x*frequence256); int sy=(int)(y*frequence256); for(int n=0;n<8;n++) {... ... sx<<=1; sy<<=1; } |
|
|
|
|
Games published by our own members! Check 'em out!
|
|
Roquen
|
 |
«
Reply #3 - Posted
2011-03-16 11:09:23 » |
|
Thanks for post/code. BUT since I'm obviously in a pedantic mood this is "value noise" and not Perlin noise. We might be able to juice some extra cycles out of this by replacing the rng with something simpler. Poke me if I don't give some options.
|
|
|
|
DzzD
|
 |
«
Reply #4 - Posted
2011-03-16 11:45:38 » |
|
I agree that modifying RNG is probably the easiest way to make it faster, I did not try to re-create one and just picked it somewhere, also in this version final RNGs values are clamped to 0-255, maybe it make some of the computation useless (but it let user able to increase value range easily by modifying the mask 0xFF) hum.. I never realized that it was not true perlin noise... I based it on Hugo Elias explanations, who seems to have made the same confusion as me... To be true I cant see interrest of perlin noise (using gradiants to mak weighted interpolation) VS "value noise" (maybe you can highlite me ?), difference is only in the interpolation method (weighted) no ? The above implementation is low quality but I would say that it is IMO more related to the fact it use a linear interpolation rather than it is not a true gradiant noise no ? (I guess that using cubic should give really nice result with still good speed)
|
|
|
|
Roquen
|
 |
«
Reply #5 - Posted
2011-03-16 19:07:12 » |
|
Hugo Elias's page has been largely responsible for this misunderstand.
Value, Perlin's gradient & simplex noises are all similar in the types of images that they can create, so if your happy with value noise then there's no need to change. The downsides of value noise are: It's slower to create an equivalently complex image, mostly due to the need of higher number of samples to produce. It has 'worse' defects.
|
|
|
|
DzzD
|
 |
«
Reply #6 - Posted
2011-03-16 20:28:59 » |
|
The downsides of value noise are: It's slower to create an equivalently complex image, mostly due to the need of higher number of samples to produce. It has 'worse' defects. I think I ve understood both technic but still cant get what the benefit of grandiant noise.... less samples because no need to iterate on n octave ? only difference I was able to found was on wikipedia Unlike the value noise, gradient noise has more energy in the high frequencieswich I dont understand why too... here is a local gradiant noise from Ken Perlin himself ( I've read that paper a cupple of time but never notice before the link to open this animation :/) once again I ve trouble to understand benefit of Gradiant noise VS value noise  give me more info plz
|
|
|
|
krasse
|
 |
«
Reply #7 - Posted
2011-03-16 22:08:23 » |
|
I just read in the book "Texturing & Modeling - A procedural approach" the following:
"The gradient method uses an interpolation based on the gradients at the eight corners of a single lattice cell, rather than the 64-vertex neighborhood used in the cubic interpolation method described in the previoius section."
I interpret this as: The gradient noise is cheaper than value noise if you want a cubic-like function.
The book also mentions that the power spectrum of gradient noise is better than for value noise. The spectrum for gradient noise looks more spread out than for the value noise but still within the required limit. This makes it more varied frequency-wise, which is good for a noise function in terms of predictability and visual regularity perhaps? I am not really sure.
|
|
|
|
DzzD
|
 |
«
Reply #8 - Posted
2011-03-17 09:14:36 » |
|
thanks! those are nice informations
I better understand it now, difference in complexity seems to be more true for more dimension, value noise would requiere 64 vertices for cubic in 3D (cube with 4 vertices per edges => 4*4*4 => 64 vertices), in 2D the difference is less significant.
so.... I may conclude that : the above value noise implementation is probably faster than the corresponding 2D gradiant noise, but.. as it use a linear interpolation the quality is lower, with one more dimension (3D) or a cubis interpolation it wil become not so interresting to use that value noise
If I get enought free time I would like to built a full Integer Gradiant noise too, seeing if it is possible to "shrink" it the same way of value noise
|
|
|
|
Roquen
|
 |
«
Reply #9 - Posted
2011-03-18 17:20:37 » |
|
It's slower to create an equivalently complex image, mostly due to the need of higher number of samples to produce.
less samples because no need to iterate on n octave? Yeah. Building with gradient noise will require less combinations (octaves is one example) of samples to create an equivalently complex image vs. value noise. (see next comment) Unlike the value noise, gradient noise has more energy in the high frequencies
These two are related. Very roughly speaking: In the frequency domain noise needs to be "band-limited" so that it can be an efficient constructive element. value noise would requiere 64 vertices for cubic in 3D
Value & gradient noise both have the same cell structure. The 64 number comes from the implementation in book adding extra sample points (along edges) and using splines for interpolation. This is insanely expensive.
|
|
|
|
Games published by our own members! Check 'em out!
|
|
DzzD
|
 |
«
Reply #10 - Posted
2011-04-06 17:04:06 » |
|
Same noise also used to produce realtime waves 
|
|
|
|
DzzD
|
 |
«
Reply #11 - Posted
2011-04-13 10:00:17 » |
|
source code update, function now accept a third parameter nbOctave, it should also be a little faster and perform computation with more precision.
Ps: I ve started a true gradiant noise based on this one, seems it will only requiere very few modifications, I will keep this thread up. ( even if I am not yet sure that it will have a real interrest, computation will be a little more complexe and then even if "one octave layer" will look better it will requiere more time so ... let's see)
|
|
|
|
DzzD
|
 |
«
Reply #12 - Posted
2011-04-18 17:35:37 » |
|
yet another sample : http://demo.dzzd.net/Sky/2/note that to animate this sampe I did not use a 3D noise, I simply multiply two noise : finalNoise(x,y,z)=noise2D(x,y)*noise1D(z); have used such one to make some tests of animating waves in Virtual ocean races 2, seems to give very good result this can be simply achieved with the above code. note: multiplying N noise rather than computing noise in N dimension seems more powerfull for some common usage as you replace the requiered N dimension interpolation by a simple multiplication, in case of precomputed noise it make final noise computation very fast and very low memory (same noise can be used twice with an offset) => only mixing two 2d array (or same 2d array) to get a 4D noise (noise animated in 3D), it probably modify the noise main frequency but it is only a matter of scale.
|
|
|
|
DzzD
|
 |
«
Reply #13 - Posted
2011-04-27 09:08:36 » |
|
Improved version : enable bicubic and bilinear interpolation enable value or true gradiant noise (hybrid/improved one : use grad+offset value to avoid cell corner problem : always equals to zero on pure grad noise, in this one an offset is added : basically the above grad version work like if noise(x,y) = gradNoise(x,y)+valueNoise(x,y);
First results of a fast bench tests between version : cubic interpolation give a noticable quality improvment (but not that much) at cost of speed grad noise give a more complex image with less octaves also at cost of speed but... as it requiere less octave it maybe finally more interresting in term of speed, need more tests cases to know
NB: this new version run still pretty fast but has not been yet optimized and they may have a cupple of rooms to optimize it
|
|
|
|
DzzD
|
 |
«
Reply #14 - Posted
2011-04-27 12:27:00 » |
|
here is a online Applet demo of the new version using gradiant noise (+ bicubic interpolation) : Click to try Online Applet
 rendering is better than the old one (mostly because the use of cubic interpolation), but it use less octave and maybe probably a little faster
|
|
|
|
Roquen
|
 |
«
Reply #15 - Posted
2011-04-27 12:27:55 » |
|
Fun. But note (from an earlier post) noise(nD)*noise(1d) is a quite different effect from walking through noise(n+1 D). Stuff like this is what makes play with noise amusing. Finding diffrent ways to combine and create different effects.
|
|
|
|
DzzD
|
 |
«
Reply #16 - Posted
2011-04-27 12:30:16 » |
|
Fun. But note (from an earlier post) noise(nD)*noise(1d) is a quite different effect from walking through noise(n+1 D). Stuff like this is what makes play with noise amusing. Finding diffrent ways to combine and create different effects.
yes inded but in a lot of case, as animating surface it can do the job well ( anyways the above code can be easily extended to N dimensions )
|
|
|
|
philfrei
|
 |
«
Reply #17 - Posted
2011-04-27 21:18:24 » |
|
Beautiful stuff! I love the sun & clouds & especially with the rippling water added. Amazing to see it updated live, as well. I don't know if you are concerned about this sort of thing, but I got an odd artifact when I ran the first demo.  I had moused to the upper middle right area. Using IE8 on WindowsXP. Also, a comment about sky2 & sky3. The first looks like it could be a "religious hallucination" with lots of crosses coming and going. The second, there is also a bit of banding, but it is more like a topo map. It's pretty subtle though, not that bad. But I'm wondering if there isn't some way to filter out these things? I recall reading in a music DSP discussion, one can do linear vs quadratic or cubic interpolation (for example, when taking a sound and stretching it) but the result will still have artifacts despite going to methods with higher computation costs. So, what folks do is to apply a low-pass filter to the data. Is there a similar sort of thing that can be done with these visual noise effects? (I'm really looking forward to having the time to try programming this stuff myself one of these days. For now, am just watching in awe and with appreciation.)
|
|
|
|
CommanderKeith
|
 |
«
Reply #18 - Posted
2011-04-28 02:08:17 » |
|
Beautiful! I can't say it looks a lot like clouds the way the clouds appear then disappear. Clouds tend to move across the sky. But it looks very cool and I guess you could easily use your algorithm to make more slowly animating cloud textures and then move them across the sky.
Great work
|
|
|
|
DzzD
|
 |
«
Reply #19 - Posted
2011-04-28 09:52:37 » |
|
I don't know if you are concerned about this sort of thing, but I got an odd artifact when I ran the first demo. this is a mapping problem for the skybox, urelated to the noise itself Also, a comment about sky2 & sky3. The first looks like it could be a "religious hallucination" with lots of crosses coming and going. The second, there is also a bit of banding, but it is more like a topo map. It's pretty subtle though, not that bad. But I'm wondering if there isn't some way to filter out these things? I recall reading in a music DSP discussion, one can do linear vs quadratic or cubic interpolation (for example, when taking a sound and stretching it) but the result will still have artifacts despite going to methods with higher computation costs. So, what folks do is to apply a low-pass filter to the data. Is there a similar sort of thing that can be done with these visual noise effects? the first problem arrows on sky2 comme from the interplation method, bilinear interpolation tend to produce such artefact, nothing that can really be done here as it is an inherent problem with bilinear interpolation about the artefact on sky3 (wich seems to be a discretisation problem often related to lack of precision in integer computation) I think it come from the bicubic interpolation implementation and can be corrected by increasing the precision of the computation, I did not take a lot of attention when doing this one, and as you can see the computed value is multiplied by 256 (it is not with linear), this needed multiplication means that I have used a too low scale for the computation itslef and that it lost 8 bit precision, increasing the computation scale should correct this artefact bug. But it looks very cool and I guess you could easily use your algorithm to make more slowly animating cloud textures and then move them across the sky. yes sure, noise can be used for thousand of effects, I also use it to animate water in a shader in another project
|
|
|
|
ok
Junior Newbie
|
 |
«
Reply #20 - Posted
2012-01-05 14:57:16 » |
|
Hi DzzD,
Your noise func is super-fast, thx for that ! (could be also easily simdized, yum!).
I needed a seamless xy result so I used your multiplication trick to get the pseudo 4D noise and feed it with two circle coordinates. This is also working a treat !
Probably silly question : Do you think that fake 4D is overkilling / do you have a simpler solution to get your 2D perlin signal tileable ?
The tiling is working cool with your fake 4D trick for now, but I get far more pronounced bi-cubic artefacts with this multiplication trick...
Do you think quintic interpolation could solve this ?
Much thanks again ! K
|
|
|
|
DzzD
|
 |
«
Reply #21 - Posted
2012-02-25 22:40:21 » |
|
Hi DzzD,
Your noise func is super-fast, thx for that ! (could be also easily simdized, yum!).
I needed a seamless xy result so I used your multiplication trick to get the pseudo 4D noise and feed it with two circle coordinates. This is also working a treat !
Probably silly question : Do you think that fake 4D is overkilling / do you have a simpler solution to get your 2D perlin signal tileable ?
The tiling is working cool with your fake 4D trick for now, but I get far more pronounced bi-cubic artefacts with this multiplication trick...
Do you think quintic interpolation could solve this ?
Much thanks again ! K
sry I was not on JGO for a while... but I get far more pronounced bi-cubic artefacts with this multiplication trick yes I pointed this artefact above, this is due to a lack of precision in the bicubic computation (it can be corrected) Do you think quintic interpolation could solve this ? probleme come from the discretisation of computation not the computation itself , so I believe that it wont help more than correcting the integer cubic interpolation implementation
|
|
|
|
ok
Junior Newbie
|
 |
«
Reply #22 - Posted
2012-02-26 02:29:26 » |
|
Hi DzzD, Tons of thanks for your post. sry I was not on JGO for a while... You are kidding me right ? this noise implementation is a gem. I would have appreciate using it extensively in-line but you know how it is... I don't have time to figure out if I should compute all this mess on the fly or use a raster to leave hand for therefore other basic stuff. I finally use a pre-rendered noise map for my sh..(because I need / was tempted by more tons of octaves-based visual result...  ( ). I am still planning to use your snippet to complete all this with small in-line extra layers(multiple ways, starfield, extra noise when we are close, etc...). probleme come from the discretisation of computation not the computation itself Much thanks for your input, I have to admit I am testing this cool stuff with c++(ported, for sure, in no time - one or two lines - thx to your clean coding). I am still a bit lost with fully reading your optimizations but I like the style, specifically as it is the fastest noise I found so far ! , so I believe that it wont help more than correcting the integer cubic interpolation implementation Wow, this is your job or maybe mine with few month(S) more training on this(need time to understand how to translate this "clean" on various different vector units microcode- spus, gpus... man, tons of exciting efforts ahead - at least for me...  ). I am definitely giving it a deeper shot asap ! Thanks again, ok
|
|
|
|
R.D.
|
 |
«
Reply #23 - Posted
2012-02-26 09:49:28 » |
|
Hey. Could you post an exampl code snipptet on hoe to produce e.g. an cloud image or something? I don't understand Perlin to be honest :/
|
|
|
|
Murloc992
Innocent Bystander
|
 |
«
Reply #24 - Posted
2012-06-22 12:32:20 » |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| BufferedImage bi=new BufferedImage(1024,1024,BufferedImage.TYPE_INT_RGB); for(int i=0; i<1024; i++) for(int j=0; j<1024; j++) { int col=FastNoise.noise(i/128f, j/128f, 7); int red=col; int green=col; int blue=col; int RGB=red; RGB=(RGB<<8)+green; RGB=(RGB<<8)+blue; bi.setRGB(i, j, RGB); } try { File outputfile = new File("noise.png"); ImageIO.write(bi, "png", outputfile); } catch (IOException e) { e.printStackTrace(); } |
If the code looks ugly, it's because I don't know what I am doing.  Seems to work, gives that tasty noise. :> Here it is:  EDIT: I am using VALUE NOISE, not TRUE GRADIENT here! Cuz I don't know how to get gradient one properly. 
|
|
|
|
|