Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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).

share|improve this question
2  
A little en.wikipedia.org/wiki/Rubber_duck_debugging rubber duck session would have probably led to a solution, something to consider in the future. –  Patrick Hughes Mar 28 '13 at 8:20
add comment

closed as too localized by Byte56, Sean Middleditch, Patrick Hughes, bummzack, Josh Petrie Mar 29 '13 at 14:34

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.If this question can be reworded to fit the rules in the help center, please edit the question.

1 Answer

up vote 2 down vote accepted

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);
share|improve this answer
add comment

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