Create natural Perlin Noise

249 views Asked by At

http://image.kilho.net/?pk=1420781

I am trying to use perlin noise to create terrain.

But I always get above noise.

http://image.kilho.net/?pk=1420774

What I want to get is the last(7th) image.

But my noise image looks like 4th or 5th image.

here is my code (java)

int seed;

public Noise() {
    Random ran = new Random();
    seed = ran.nextInt();
}
/**
 * Brut noise generator using pseudo-random
 */
public double noise(int x,int y)
{
    x=x + y * seed;
    x=((x<<13) ^ x);
    double t=(x * (x * x * 15731 + 789221) + 1376312589) & 0x7fffffff;
    return 1-t*0.000000000931322574615478515625;

}

/**
 * Smoothed noise generator using 9 brut noise
 */
public double sNoise(int x,int y)
{
    double corners = ( noise(x-1, y-1)+noise(x+1, y-1)+noise(x-1, y+1)+noise(x+1, y+1) ) * 0.0625;
    double sides   = ( noise(x-1, y)  +noise(x+1, y)  +noise(x, y-1)  +noise(x, y+1) ) *0.125;
    double center  =  noise(x, y) *0.25;
    return corners + sides + center;        
}

/**
 * Linear Interpolator
 *
 * @param a value 1
 * @param b value 2
 * @param x interpolator factor
 * 
 * @return value interpolated from a to b using x factor by linear interpolation
 */
public double lInterpoleLin(double a,double b,double x)
{
    return  a*(1-x) + b*x;      
}


/**
 * Cosine Interpolator
 *
 * @param a value 1
 * @param b value 2
 * @param x interpolator factor
 * 
 * @return value interpolated from a to b using x factor by cosin interpolation
 */
public double lInterpoleCos(double a,double b,double x)
{

    double ft = x * 3.1415927;
    double f = (1 - Math.cos(ft)) * .5;
    return  a*(1-f) + b*f;
}

/**
 * Smooth noise generator with two input 2D
 * <br>
 *  You may change the interpolation method : cosin , linear , cubic 
 * </br>
 * @param x x parameter
 * @param y y parameter
 *
 * @return value of smoothed noise for 2d value x,y
 */
public double iNoise(double x,double y)
{
    int iX=(int)x;
    int iY=(int)y;
    double dX=x-iX;
    double dY=y-iY;
    double p1=sNoise(iX,iY);
    double p2=sNoise(iX+1,iY);
    double p3=sNoise(iX,iY+1);
    double p4=sNoise(iX+1,iY+1);
    double i1=lInterpoleLin(p1,p2,dX);
    double i2=lInterpoleLin(p3,p4,dX);
    return lInterpoleLin(i1,i2,dY); 
}   

/**
 * Perlin noise generator for two input 2D
 * 
 * @param x x parameter
 * @param y y parameter
 * @param octave maximum octave/harmonic
 * @param persistence noise persitence
 * @return perlin noise value for given entry
 */
public double pNoise(double x,double y,double persistence,int octave)
{
    double result;
    double amplitude=1;
    int frequence=1;
    result=0;
    for(int n=0;n<octave;n++)
    {
        result+=iNoise(x*frequence,y*frequence)*amplitude;
        frequence<<=1;
        amplitude*=persistence;
    }
    return result;  
}

}

1

There are 1 answers

0
Canis Artorus On

If you call this code with a persistence value less than unity you will over-sample high frequencies.
The fractal / fBm octave summation method you are using is an octaves down limiter, starting with the most jittery result and blending it into wider feature spreads. For terrain generators one generally desires medium- large features with some details - I've heard that one should make the primary pass at least 5, possibly 20 pixels wide to get smooth features. Since your code is doing one pixel per cell, the white-ish 'TV static' noise is probably overpowering the signal you want to see.

I'd wager the sample picture gallery you refer to was using a near-unity (or possibly higher) persistence parameter to get the final image.