1
$\begingroup$

I tried implementing Perlin Noise using the Wikipedia as my main resource. From what I can tell my implementation of the algorithm is spot on but for some reason I'm getting a lot of values equating to 1 or to 0.

This is my Perlin function:

GLfloat perlin(GLfloat x, GLfloat y)
{
    // Turn param into vector
    glm::vec2 xy = glm::vec2(x, y);

    // Grid Cell Coordinates
    glm::vec2 bottomLeft = glm::vec2(std::floor(x), std::floor(y));
    glm::vec2 topRight = glm::vec2(bottomLeft.x + 1, bottomLeft.y + 1);

    GLfloat sx = x - bottomLeft.x;
    GLfloat sy = y - bottomLeft.y;

    GLfloat bottomLeftDot = glm::dot(gradients[(GLint)bottomLeft.x][(GLint)bottomLeft.y], xy - bottomLeft);
    GLfloat bottomRightDot = glm::dot(gradients[(GLint)topRight.x][(GLint)bottomLeft.y], xy - glm::vec2(topRight.x, bottomLeft.y));

    GLfloat smooth1 = glm::smoothstep(bottomLeftDot, bottomRightDot, sx);

    GLfloat topLeftDot = glm::dot(gradients[(GLint)bottomLeft.x][(GLint)topRight.y], xy - glm::vec2(bottomLeft.x, topRight.y));
    GLfloat topRightDot = glm::dot(gradients[(GLint)topRight.x][(GLint)topRight.y], xy - topRight);

    GLfloat smooth2 = glm::smoothstep(topLeftDot, topRightDot, sx);

    GLfloat value = glm::smoothstep(smooth1, smooth2, sy);
    return value;
}

enter image description here

As you can see, I am using the generated values as a height map. In the image above you can see that there's a straight wall and I'm wondering if maybe I'm not interpolating correctly. Can someone point out my mistake?

I'm generating a 100 by 100 grid and my input values are from 0.00 to 0.99 on each axis.

Another question I have is Wikipedia says to use a smoothstep function but I'm not sure for what values?

Update: I changed the smoothstep and function to the lerp function and now everything seems to be working well but can someone please explain why the outcome is so drastically different.

New outcome below:

enter image description here

$\endgroup$

1 Answer 1

3
$\begingroup$

It looks like the way you're using smoothstep isn't quite right.

With lerp, the first two parameters are the endpoints of the output range, and the third is a 0–1 value specifying how far to interpolate. It looks like you're trying to use smoothstep the same way, but it doesn't work like that: the first two parameters to smoothstep are endpoints of the input range, and the third is a value in the input range; the output of smoothstep is always in 0–1. It's almost the inverse of lerp in that regard. (See also the GLM docs for smoothstep).

To use smoothstep here, you'd want to do something like this:

glm::lerp(bottomLeftDot, bottomRightDot, glm::smoothstep(0, 1, sx));

This applies smoothstep to the sx value (which is between 0 and 1). The result, which is another 0–1 value, is then used to lerp between the two "dot" values.

$\endgroup$
2
  • $\begingroup$ But what exactly is the smoothstep doing? How will it change the outcome? $\endgroup$
    – Archmede
    Commented Sep 1, 2017 at 19:25
  • 2
    $\begingroup$ Smoothstep is just a hermite curve (a 3rd degree polynomial) that smoothly varies between 0 and 1. Rather than a straight line, it ramps up slowly at first, then faster, then eases up at the end. So it looks sort of like an integral symbol if you map it from 0 to 1. Like this: ∫. You can read the wikipedia article, which has a graph. $\endgroup$ Commented Sep 1, 2017 at 20:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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