0

I'm trying to create a basic value noise function. I've reached the point where it's outputting it but within the output there are unexpected artefacts popping up such as diagonal discontinuous lines and blurs. I just can't seem to find what's causing it. Could somebody please take a look at it to see if I'm going wrong somewhere.

First off, here are three images that it's ouputting with greater magnification on each one.

http://oi40.tinypic.com/wl2deq.jpg

//data members
float m_amplitude, m_frequency;
int m_period;  //controls the tile size of the noise
vector<vector<float> m_points; //2D array to store the lattice

//The constructor generates the 2D square lattice and populates it.
Noise2D(int period, float frequency, float amplitude)
{
    //initialize the lattice to the appropriate NxN size
    m_points.resize(m_period);
      for (int i = 0; i < m_period; ++i)
        m_points[i].resize(m_period);

    //populates the lattice with values between 0 and 1
    int seed = 209;
            srand(seed);
    for(int i = 0; i < m_period; i++)
    {
        for(int j = 0; j < m_period; j++)
        {
            m_points[i][j] = abs(rand()/(float)RAND_MAX);
        }
    }
}


//Evaluates a position
float Evaluate(float x, float y)
{
    x *= m_frequency;
    y *= m_frequency;

    //Gets the integer values from each component
    int xFloor = (int) x;
    int yFloor = (int) y;

    //Gets the decimal data in the range of [0:1] for each of the components for interpolation
    float tx = x - xFloor;
    float ty = y - yFloor;

    //Finds the appropriate boundary lattice array indices using the modulus technique to ensure periodic noise.
    int xPeriodLower = xFloor % m_period;
    int xPeriodUpper;
    if(xPeriodLower == m_period - 1) 
        xPeriodUpper = 0; 
    else    
        xPeriodUpper = xPeriodLower + 1;

    int yPeriodLower = yFloor % m_period;
    int yPeriodUpper;
    if(yPeriodLower == m_period - 1) 
        yPeriodUpper = 0; 
    else    
        yPeriodUpper = yPeriodLower + 1;

    //The four random values at each boundary. The naming convention for these follow a single 2d coord system 00 for bottom left, 11 for top right
    const float& random00 = m_points[xPeriodLower][yPeriodLower];
    const float& random10 = m_points[xPeriodUpper][yPeriodLower];
    const float& random01 = m_points[xPeriodLower][yPeriodUpper];
    const float& random11 = m_points[xPeriodUpper][yPeriodUpper];

    //Remap the weighting of each t dimension here if you wish to use an s-curve profile.
    float remappedTx = tx;
    float remappedTy = ty;

    return MyMath::Bilinear<float>(remappedTx, remappedTy, random00, random10, random01, random11) * m_amplitude;
}

Here are the two interpolation functions that it relies on.

template <class T1>
static T1 Bilinear(const T1 &tx, const T1 &ty, const T1 &p00, const T1 &p10, const T1 &p01, const T1 &p11)
{
    return Lerp(    Lerp(p00,p10,tx),
            Lerp(p01,p11,tx),
            ty);
}

template <class T1> //linear interpolation aka Mix
static T1 Lerp(const T1 &a, const T1 &b, const T1 &t)
{
    return a * (1 - t) + b * t;
}
4

1 回答 1

1

Some of the artifacts are the result of linear interpolation. Using a higher order interpolation method would help, but it will only solve part of the problem. Crudely put, sharp transitions in the signal can lead to artifacts.

Additional artifacts result from distributing the starting noise values (I.E. the values you are interpolating among) at equal intervals - in this case, a grid. The highest & lowest values will only ever occur at these grid points - at least when using linear interpolation. Roughly speaking, patterns in the signal can lead to artifacts. Two potential ways I know of addressing this part of the problem are either using a nonlinear interpolation &/or randomly nudging the coordinates of the starting noise values to break up their regularity.

Libnoise has an explanation of generating coherent noise which covers these problems & solutions in greater depth with some nice illustrations. You could also peek at the source if you need see how it deals with these problems. And as richard-tingle already mentioned, simplex noise was designed to correct the artifact problems inherent in Perlin noise; it's a little tougher to get your head around, but it's a solid technique.

于 2013-07-13T22:02:57.727 回答