#### Response title

This is preview!

Loading...

Copy code

Permalink

Please tell us why you want to mark the subject as inappropriate.
(Maximum 200 characters)

Private Message

Feedback

Private Message

Type the characters you see in the picture below.

Type the characters you see in the picture below.

Attach files

Desktop
Google Docs

Loading User Profile...

This is preview!

Sign In

You can also use the below options to login

- Login with Facebook
- Login with Google
- Login with Yahoo

- Recent Topics
- All Forums
- Search All
- Tags
- Author
- Advanced Search

Search

Move this topic

Hi all -- just started using Cinder a few days ago and am loving it...have ported over several of my applications and experiments from OF and Processing. Congratulations to the Barbarians and everyone else who has contributed to this effort, and long may it live!

But -- am I going crazy? It seems surprising that such a major glitch wouldn't have been caught yet (especially considering the love-in people have with spatial noise), but it does seem to be there... The problem? That calls to the various Perlin noise functions always seem to return 0 for arguments that happen to be integer numbers.

An example:

This outputs:

By contrast, if I shift the starting indices by 0.5, I get this result instead:

I am using the official drop of Cinder on OS X, but I checked on Github and the Perlin library hasn't received any fixes since then.

Thanks,

Glen.

But -- am I going crazy? It seems surprising that such a major glitch wouldn't have been caught yet (especially considering the love-in people have with spatial noise), but it does seem to be there... The problem? That calls to the various Perlin noise functions always seem to return 0 for arguments that happen to be integer numbers.

An example:

- float x, y;
- float noise, fBm;
- Perlin myPerlin;
- for ( y = 0; y < 3; y += 1.0 )
- {
- for ( x = 0; x < 3; x += 1.0 )
- {
- noise = myPerlin.noise( x, y );
- fBm = myPerlin.fBm( x, y );
- console() << "noise at: " << x << ", " << y << " = " << noise <<
- " (fBm " << fBm << ") " << endl;
- }
- }

This outputs:

noise at: 0, 0 = 0 (fBm 0)

noise at: 1, 0 = 0 (fBm 0)

noise at: 2, 0 = 0 (fBm 0)

noise at: 0, 1 = 0 (fBm 0)

noise at: 1, 1 = 0 (fBm 0)

noise at: 2, 1 = 0 (fBm 0)

noise at: 0, 2 = 0 (fBm 0)

noise at: 1, 2 = 0 (fBm 0)

noise at: 2, 2 = 0 (fBm 0)

By contrast, if I shift the starting indices by 0.5, I get this result instead:

As you move away from the integers (e.g. by 0.01, 0.1, ...), better-looking values gradually start to "fade in". Has anyone else noticed this distinctly un-random behaviour? It happens with all the variants of Perlin. Is it possible I'm doing something wrong? I've checked and I'm not using more than one instance of the Perlin class in my application (although this doesn't seem to make a difference anyhow).noise at: 0.5, 0.5 = 0.375 (fBm 0.1875)

noise at: 1.5, 0.5 = -0.25 (fBm -0.125)

noise at: 2.5, 0.5 = 0.25 (fBm 0.125)

noise at: 0.5, 1.5 = 0.125 (fBm 0.0625)

noise at: 1.5, 1.5 = -0.375 (fBm -0.1875)

noise at: 2.5, 1.5 = 0.375 (fBm 0.1875)

noise at: 0.5, 2.5 = 0 (fBm 0)

noise at: 1.5, 2.5 = 0 (fBm 0)

noise at: 2.5, 2.5 = -0.125 (fBm -0.0625)

I am using the official drop of Cinder on OS X, but I checked on Github and the Perlin library hasn't received any fixes since then.

Thanks,

Glen.

1

Hmm, I can't speak for the dev team but looking at the source code, I think it has to do with the following lines of code in the noise functions. It also affects the fBm functions because they rely on them. (Just to be clear - I'm talking about the use of floorf.)

float Perlin::noise( float x ) const

{

int32_t X = ((int32_t)floorf(x)) & 255;

x -= floorf(x)

[...]

}

It seems that this is simply how their implementation works. And I don't think you would ever use *in practice* the noise functions with such integer increments, right?

Leave a comment on num3ric's reply

To answer my own question...

I know that there is no reason why it should be zero on the integers "in principle", since theoretically the noise works by evaluating random values on the integers, then interpolating between them. But since most Perlin noise is implemented (to be fast) using a limited number of random values and those permutation tables, what I've observed is apparently a known side effect.

Another disadvantage that might not be obvious is that the noise function always returns 0 at integer values. Although this is not noticable on static images it is very apparent on animated images. I made a 3D perlin noise function and rendered it on a 2D texture map while moving along the z-axis, this had the effect of a pulsating map. This because every time the z value was integer there where many values around 0, while the z where between integer values there where more randomness.

Fortunately there is a simple solution for this. What you do is that you rotate the coordinate system before calling the noise function, this has the effect that not many samples will be on integer values at the same time.

The rotating trick works pretty well, though it adds a few more calculations.

- Perlin myPerlin;
- const float cosTheta = 0.99854f; // Theta (rotation) of about 3.1 degrees (quite arbitrarily)
- const float sinTheta = 0.05408f;
- float noiseScale = 0.01f;
- for ( int j = 0; j < getWindowHeight(); j += 25 )
- {
- for ( int i = 0; i < getWindowWidth(); i += 25 )
- {
- gl::drawSolidCircle( Vec2f( i, j ), 10 * abs( myPerlin.fBm( noiseScale * ( i * cosTheta - j * sinTheta ), noiseScale * ( i * sinTheta + j * cosTheta ) ) ) );
- }
- }

And there you go, in case you ever need to get rid of this side-effect. The good news -- apparently this is not a bug, since I confirmed that one of Ken Perlin's permutation versions did the same thing when evaluated at or very close to integer points. Or you can also write your own interpolating noise routine (as I've done), which may be a tad slower but will give good values consistently throughout space, with no periodic glitches.

Leave a comment on totalgee's reply

Hey Glen - everything you've written above I believe is correct. This definitely trips people up though, and I've considered whether we should introduce a *scale* into Perlin, as you generally need one anyway, and a few multiplies are not going to be a problem in terms of performance. In general our philosophy has been to avoid penalizing performance for the sake of convenience but I don't think this should be an issue here. Assuming we did this, we might default the scale to 0.001 or something so that the thing people often want to do, which is feed a pixel coordinate directly into Perlin, just works.

BTW - our Perlin implementation is derived from the one you linked above.

Anyone else have any thoughts?

Leave a comment on andrewfb's reply

That sounds reasonable. This is how I normally end up using perlin noise anyhow:

float sc = 0.01f;

float r = mPerlin.fBm(u, mTime * sc, 100.0f);

float g = mPerlin.fBm(u, mTime * sc, 200.0f);

float b = mPerlin.fBm(u, mTime * sc, 300.0f);

or something to that effect. So a scale parameter would be nice. It's very rare that the default noise scale is unadjusted.. or actually.. i don't think i've ever used the default scale ;)

Leave a comment on notlion's reply

Im surprised about this, usually all perlin noise functions I had worked with come with some methods to control de amplitude and frequency but here the frequency is one by default for what I see.

I think a method to change frequency would be highly appreciated.

Thanks.

I think a method to change frequency would be highly appreciated.

Thanks.

Leave a comment on javi.agenjo's reply

I'm glad I found this post. I was going crazy trying to figure out why this wasn't working. I've got an integer grid that needed some variation. I'll do some multiplication on it to get it off the integer values.

Leave a comment on drewish's reply

@totalgee wrote,*I know that there is no reason why it should be zero on the integers "in principle", since theoretically the noise works by evaluating random values on the integers, then interpolating between them.*

Actually this is a misunderstanding of how Perlin noise works. Yes, there is a random vector (gradient) defined for each grid (integer) point, but the gradient (or interpolation of gradients) is not what the noise function returns. Instead, the return value is based on a dot product of the gradient with another vector, P-Q.

For whatever input point P you're evaluating, and for each surrounding grid point Q, P - Q is the vector from the grid point Q to the input point P. So if P is on an integer coordinate, P-Q will have length zero! And therefore its dot product with the gradient vector will be zero. (See Ken Perlin's presentation slide.)

There are more details to it of course, including interpolation, but that's the basic reason why Perlin noise is zero on the integers.

So, there is a reason why the noise function should yield zero on the integers, in principle. As Matt Zucker wrote in his great Perlin noise math FAQ,

*An interesting consequence of all of this is that the noise function becomes zero when x and y are both whole numbers. This is because the vector (x, y) - (x0, y0) *[or P - Q, as Perlin referred to them]* will be the zero vector. Then the dot product of that vector and g(x0, y0) *[i.e. the gradient vector]* will evaluate to zero, and the weights for the averages will also always be zero, so that the zero dot product will influence the final answer 100%. The funny thing is that looking at the noise function, you would never guess that it ends up being zero at regular intervals.*

Actually this is a misunderstanding of how Perlin noise works. Yes, there is a random vector (gradient) defined for each grid (integer) point, but the gradient (or interpolation of gradients) is not what the noise function returns. Instead, the return value is based on a dot product of the gradient with another vector, P-Q.

For whatever input point P you're evaluating, and for each surrounding grid point Q, P - Q is the vector from the grid point Q to the input point P. So if P is on an integer coordinate, P-Q will have length zero! And therefore its dot product with the gradient vector will be zero. (See Ken Perlin's presentation slide.)

There are more details to it of course, including interpolation, but that's the basic reason why Perlin noise is zero on the integers.

So, there is a reason why the noise function should yield zero on the integers, in principle. As Matt Zucker wrote in his great Perlin noise math FAQ,

So this "feature" of Perlin noise was known by the inventor, and was not considered a problem for his purposes. (His talk "Making Noise" is very insightful and enlightening about how Perlin noise can be used ... I recommend it.) In situations where the zero-pinning at grid points is a problem, Perlin noise may not be the right tool -- or may need to be adapted, as you did.

By rotating the input coordinates, you moved the zero points ("nodes") away from the integer input coordinates. If that's **all** you needed, seems like it would be a little cheaper to do translation than rotation... and you'd guarantee that your input points would *never* be on a node. But yeah, if you need to avoid having the nodes lined up along an axis, rotation is a good solution. Another solution (more expensive) would be to layer (sum) 2 variants of Perlin noise, one of which is translated/scaled/rotated relative to the other. This would avoid having *any* node points. (And you could take that technique further and make fractal noise.)

Leave a comment on Lars1's reply

Change topic type

Link this topic

Provide the permalink of a topic that is related to this topic

Reply to totalgee's problem

- © 2020 ZOHO Corp.
- All Rights Reserved.
- Privacy
- Terms & Conditions
- RSS
- Powered by