2
\$\begingroup\$

I'm having a bit of trouble implementing Perlin Noise, I've included an example the problem below. I've tried debugging but everything appears to be working correctly, and I can't figure out what's causing the sharp edges in the output.

Perlin Noise Test

Below is a snippet of the code that I'm using to generate the noise (sorry about lack of comments, most should be self-explanatory though).

inline int ffloor(float i)
{
    return (i >= 0 ? (int)i : (int)i-1);
}

inline float dot(float x, float y, Vector grad) 
{
    return (x * grad.x + y * grad.y);
}


inline float lerp(float t, float a, float b)
{
    return a + t * (b - a);
}

inline float scurve(float t)
{
    return (t*t*t*(t*(6*t -15) + 10));
}

inline Vector getVec(int x, int y)
{
    unsigned char a = permutations[x & 255];
    unsigned char b = permutations[y & 255];
    unsigned char val = permutations[(a + b) & 255];
    return gradients[val];
}

float noise2(float xPos, float yPos)
{
    float x0 = ffloor(xPos);
    float x1 = x0 + 1.0f;
    float y0 = ffloor(yPos);
    float y1 = y0 + 1.0f;

    float fracX = xPos - x0;
    float fracY = yPos - y0;

    float n00 = dot(fracX, fracY, getVec(x0, y0));
    float n01 = dot(fracX, fracY - 1.0f, getVec(x0, y1)); 
    float n10 = dot(fracX - 1.0f, fracY, getVec(x1, y0)); 
    float n11 = dot(fracX - 1.0f, fracY - 1.0f, getVec(x1, y1)); 

    float sx = scurve(fracX);
    float sy = scurve(fracY);

    float avgX0 = lerp(sx, n00, n11);
    float avgX1 = lerp(sx, n01, n11);

    return lerp(sy, avgX0, avgX1);      
}

void init(void)
{
    int i, j, k;
    float step = 6.24f / 256;
    float val = 0.0f;

    for (i = 0; i < 255; i++)
    {
        permutations[i] = rand() & 255;

        gradients[i].x = (float)sin(val);
        gradients[i].y = (float)cos(val);
        val += step;    
    }

}

To generate the noise map I'm calling init and then iteratively calling the noise2 function with coordinates that have been scaled to the size of the map I want (so xPos and yPos are always between 0 and 1).

\$\endgroup\$
2
\$\begingroup\$

There's a typo in your interpolation code:

float avgX0 = lerp(sx, n00, n11);  // <-- should be n10, not n11
float avgX1 = lerp(sx, n01, n11);
| improve this answer | |
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.