FAQ
Cover
This is the archive Discourse for the Processing (ALPHA) software.
Please visit the new Processing forum for current information.

   Processing 1.0 _ALPHA_
   Topics & Contributions
   Simulation, Artificial Life
(Moderator: REAS)
   Seamless looping noise? (for terrain)
« Previous topic | Next topic »

Pages: 1 
   Author  Topic: Seamless looping noise? (for terrain)  (Read 2195 times)
rrrufusss


Seamless looping noise? (for terrain)
« on: Jul 3rd, 2004, 12:43am »

Hello,
 
I am trying to come up with a way of getting the noise function to wrap seamlessly.  I'm working on a random terrain generation tool, so it's important that the resulting image is seamless (horezontally, at least) since it will be wrapped around a sphere.
 
I've noticed that at certain scales, there is a definate repetition in the noise function, but for each 'loop' horezontally, there is a slight shift vertically.  So, it *almost* lines up, but not quite.
 
Try this out and you'll see what I mean:
 
 
void setup()
{
  size(500,500);
   
  int x = 0;
  int y = 0;
   
  float noise_scale = 0.2;
   
  for(x = 0; x < width; x++)
  {
    for(y = 0; y < height; y++)
    {
 stroke(noise(x * noise_scale, y * noise_scale) * 255);
 point(x,y);
    }
  }
}
 
}
 
 
So, has anyone else run into this and found a solution?  I tried just making a copy of the noise and flipping it horezontally.  That works but it's really easy to see that it's just the same pattern reversed which doesn't look very good.
 
any ideas?
 
thanks!
-rrrufusss
 
skloopy

WWW
Re: Seamless looping noise? (for terrain)
« Reply #1 on: Jul 3rd, 2004, 10:03am »

Umm..
 
I think theoretically you could take the average of 4 flipped noises. The 4 noises would be like this
 
* not flipped
* flipped horzontal
* flipped vertical
* flipped both
 
Fi you average them I think it'd give you a seamless texture. I haven't tried it though.
 
Sjeiti

WWW
Re: Seamless looping noise? (for terrain)
« Reply #2 on: Jul 5th, 2004, 9:29am »

what if you use a sine to fade in the last part of the map with the first part of the map (total length of the map has to be a bit bigger than the final map you use on the sphere)
 

http://www.sjeiti.com/
narain


Re: Seamless looping noise? (for terrain)
« Reply #3 on: Jul 5th, 2004, 6:23pm »

That's the idea I was thinking of too, though I figured that ideally, you could fade all the way across the sphere...
 
In pseudocode, with x as the longitude in degrees:
noise1 = noise(x);
noise2 = noise(x - 360');
noise_final = fade_somehow(noise1, noise2, x/360');
 
At 0', noise_final = noise1 = noise(0').
At 360', noise_final = noise2 = noise(360'-360') = noise(0').
...And it all fits together, no seams.
 
(fade_somehow should blend between noise1 and noise2. You can use linear interpolation (search for 'lerp' on this forum), or a cosine like Sjeiti said for a smoother effect.)
 
One problem with this is that the blending will reduce the strength of the noise when x is somewhere in the middle. You could always try boosting it artificially depending on the position...
 
rrrufusss


Re: Seamless looping noise? (for terrain)
« Reply #4 on: Jul 7th, 2004, 11:58pm »

Thanks for the suggestions!
 
I tried them out, and unfortunately the symetry in the result is still easy to spot.  Check out http://www.optocentric.com/p/seamlessnoise/ and you can see it for yourself.
 
I'll keep poking around with it and post if I come up with something.
 
-rrrufusss
 
narain


Re: Seamless looping noise? (for terrain)
« Reply #5 on: Jul 8th, 2004, 5:27am »

Hmm... Looks to me like you're doing what scloopy suggested. I think that will be perfectly symmetrical, no way around it. What Sjeiti and I suggested shouldn't be, though.
Your source code link isn't working... Please upload your pde file.
 
rrrufusss


Re: Seamless looping noise? (for terrain)
« Reply #6 on: Jul 8th, 2004, 6:34pm »

I fixed the code link (for some reason my hosting company has issues with the .pde file extension.. I had to rename it..)
 
I don't know if fading between flipped copies of the noise will be much better.  I haven't tried it in processing, but I simulated the result in photoshop:
 
http://www.optocentric.com/p/seamlessnoise/fade_test.jpg
 
I just took a screen dump of the normal noise, then made two layers in photoshop.  I flipped one of them horezontally, then faded it to transparency from left to right.
 
-rrrufusss
 
narain


Re: Seamless looping noise? (for terrain)
« Reply #7 on: Jul 9th, 2004, 5:55am »

Uh... no, that's not what I meant.
Don't flip the texture... Flip == symmetry == bad. In this case, at least =)
 
The idea is to use a texture slightly longer than required and fade the beginning with the end.
Imagine taking your texture and wrapping it around a cylinder. If it's exactly the right length, it'll stop where it started with an ugly seam. Instead, make the texture slightly longer, and let the extra length overlap the beginning. Then all you have to do is fade between the extra and the original over the length of the length of the overlap... Voila, no more seam!
 
That's Sjeiti idea...
My modification was just to take a texture so long that the flap wraps right around the cylinder again once, and fade it all over.
 
skloopy

WWW
Re: Seamless looping noise? (for terrain)
« Reply #8 on: Jul 9th, 2004, 8:21am »

I think maybe this'll help you out. I googled for tiling noise and this is what i found. It looks like you need to call the noise function 4 times though.
 
http://www.robo-murito.net/code/perlin-noise-math-faq.html#tile
 
skloopy

WWW
Re: Seamless looping noise? (for terrain)
« Reply #9 on: Jul 9th, 2004, 9:03am »

oh oops.. i just tried it
 
Code:
float nscale = 0.05;
 
void setup()
{
  size(300,200);
}
 
void loop()
{
  float level;
  for(int i=0; i < pixels.length; i++) {
    level = tilingNoise((i%width)*nscale,(i/width)*nscale,mouseY*nscale, width*nscale, height*nscale) * 255;
    pixels[i] = color(level,level,level);
  }
}
 
float tilingNoise(float x, float y, float z, float w, float h)
{
  return (
  noise(x, y, z) * (w - x) * (h - y) +  
  noise(x - w, y, z) * x * (h - y) +  
  noise(x - w, y - h, z) * x * y +  
  noise(x, y - h, z) * (w - x) * y
  ) / (w*h);
}

it looks like it's basically what i was saying to do back up there, because it still looks symmetrical. Oh well.
 
Sorry Oops I was hoping that'd be the magic answer you're after
 
Sjeiti

WWW
Re: Seamless looping noise? (for terrain)
« Reply #10 on: Jul 9th, 2004, 11:46am »

Ok.. I thought it'd be good practice to have a go at this because I never worked with those one dimensional pixel arrays before (only two)...
 
Here's sort of what I meant, only the overlap is linear instead of sinal (you can always throw in a sine around fPrt)...
 
Code:

float fScl;
int iMrg, iWdt, iHgt;
BImage eImg, eFin;
 
void setup() {
  iMrg = 50;
  iWdt = 200;
  iHgt = 100;
  fScl = 0.02;
  size(600,400);
  noiseDetail(4,.5);
  eImg = new BImage(iWdt+iMrg,iHgt+iMrg);
  eFin = new BImage(iWdt,iHgt);
}
 
void loop()  {
  background(200);
  for (int i=0; i<eImg.pixels.length; i++) {
    int iXps = i % eImg.width;
    int iYps = i / eImg.width;
    float fNse = noise( iXps*fScl, iYps*fScl, millis()*.01*fScl );
    eImg.pixels[i] = color(fNse*255,fNse*255,fNse*255);
  }
  // horizontal seam //
  for (int i=0; i<(iWdt+iMrg)*iMrg; i++) {
  color cImg = eImg.pixels[i];
  color cHsm = eImg.pixels[i + (iWdt+iMrg)*iHgt];
  float fPrt = (i/float(iWdt+iMrg))/iMrg;
  float fRed = fPrt*red(cImg) + (1-fPrt)*red(cHsm);
  float fGrn = fPrt*green(cImg) + (1-fPrt)*green(cHsm);
  float fBlu = fPrt*blue(cImg) + (1-fPrt)*blue(cHsm);
  eImg.pixels[i] = color(fRed,fGrn,fBlu);
  }
  // vertical seam //
  for (int i=0; i<(iHgt+iMrg)*iMrg; i++) {
  int iXps = i%iMrg;
  int iYps = i/iMrg;
  color cImg = eImg.pixels[i + iYps*iWdt];
  //eImg.pixels[i + iYps*iWdt] = color(0,0,0);
  color cHsm = eImg.pixels[i + iYps*iWdt + iWdt];
  //eImg.pixels[i + iYps*iWdt + iWdt] = color(255,255,255);
  float fPrt = float(iXps)/iMrg;
  float fRed = fPrt*red(cImg) + (1-fPrt)*red(cHsm);
  float fGrn = fPrt*green(cImg) + (1-fPrt)*green(cHsm);
  float fBlu = fPrt*blue(cImg) + (1-fPrt)*blue(cHsm);
  eImg.pixels[i + iYps*iWdt] = color(fRed,fGrn,fBlu);
  }
  //
  eFin.replicate(eImg, 0,0,iWdt,iHgt, 0,0,iWdt,iHgt);
  //
  image(eFin, 10, 10);
  image(eFin, 10, 10+iHgt);
  image(eFin, 10+iWdt, 10);
  image(eFin, 10+iWdt, 10+iHgt);
  //
  image(eImg, 10, 20+iHgt*2);
  //
  stroke(255,255,255,128);
  noFill();
  rect(10, 10, iWdt,iHgt);
}

 
grtz...
 
...Sjeiti
 

http://www.sjeiti.com/
narain


Re: Seamless looping noise? (for terrain)
« Reply #11 on: Jul 11th, 2004, 7:18am »

Well, turns out the problem with symmetry is Processing's fault!
 
Apparently noise() at negative x,y is simply flipped about zero... So Sjeiti's "oops" post turns out the same as just flipping the texture.
 
Avoid going to negative values, though, and we can put the magic back:
 
Code:
float ns = 0.02;
float t = 0;
 
void setup () {
  size(320,320);
  framerate(16);
}
 
void loop () {
  int w = mouseX + 1;
  int h = mouseY + 1;
  color[] tile = makeTile(w,h);
  for (int x = 0; x < width; x++) {
    for (int y = 0; y < height; y++) {
 int x_ = x % w;
 int y_ = y % h;
 pixels[x + y*width] = tile[x_ + y_*w];
    }
  }
  t += (float) 1/16;
}
 
color[] makeTile (int w, int h) {
  color[] tile = new color[w*h];
  for (int x = 0; x < w; x++) {
    for (int y = 0; y < h; y++) {
 float u = (float) x / w;
 float v = (float) y / h;
 float noise00 = noise(x*ns, y*ns, t);
 float noise01 = noise(x*ns, (y+h)*ns, t);
 float noise10 = noise((x+w)*ns, y*ns, t);
 float noise11 = noise((x+w)*ns, (y+h)*ns, t);
 float noise = u*v*noise00 + u*(1-v)*noise01 + (1-u)*v*noise10 + (1-u)*(1-v)*noise11;
 int value = (int) (255 * noise);
 tile[x + y*w] = color(value,value,value);
    }
  }
  return tile;
}
 
Pages: 1 

« Previous topic | Next topic »