Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Perlin noise 2d implementation problems #1326

Open
deanm opened this issue Feb 22, 2016 · 6 comments
Open

Perlin noise 2d implementation problems #1326

deanm opened this issue Feb 22, 2016 · 6 comments

Comments

@deanm
Copy link
Contributor

deanm commented Feb 22, 2016

Basically the Cinder 2D Perlin noise is just 3D Perlin noise with a hardcoded z=0. It uses the same 3D gradient dot products as 3D noise, but just again with z=0. The problem with this is that 3D Perlin noise is designed with cube gradients, and behaves especially badly at z = 0 (and many others, integers probably being worse). The 3D Perlin gradients are the midpoints on a cube, for a 2D implementation, for example, Stefan Gustavson says:

"A good choice for 2D and higher is to pick gradients of unit length but different directions. For 2D, 8 or 16 gradients distributed around the unit circle is a good choice. For 3D, Ken Perlin’s recommended set of gradients is the midpoints of each of the 12 edges of a cube centered on the origin."

Attached is an image of Perlin noise with a z of 0, see the long horizontal lines, for example at Y=-1 when X < 0. But in the image you can easily see several places where the entire edge of one or more neighbouring cells is zero across the entire cell.

If you were to do the same thing but with z = 0.1, you get something like this:

So basically, it's not the best idea to implement 2D Perlin with 3D Perlin, and if you do it should at least be better to not use an integer value of z. But really, you should implement it with a different set of 2d gradients altogether (ie distributed around a circle). This would basically just involve a new Perlin::grad( int32_t hash, float x, float y ) function, which shouldn't be a very big change.

Just mentioning @notlion and @meshula as they were part of other discussions on noise.

@andrewfb
Copy link
Collaborator

This all makes sense, and there's no doubt the Perlin implementation is in serious need of refactoring. It's likely to me that the analytic derivatives are incorrect too, though I haven't looked at it in depth. Is this something you'd be willing to help out with?

@deanm
Copy link
Contributor Author

deanm commented Feb 22, 2016

Just to leave a few more notes as a reference. Here is more of a debug image that overlays the gradients. When you remove the z component you go from 12 to 8 gradient vector, and it seems like 8 just isn't enough, since 8^4 means there are only 4096 possible cells, so there is basically just 4096 tiles (and conceptually even less because each one also has its rotations). You can already see a bit the repetition in the image.

The overlay is the gradient vector and the hash value for that corner.

perlin2d

@notlion
Copy link
Contributor

notlion commented Feb 22, 2016

Hey, Dean!

I see you posted in the thread over at #901, but have you tried this with GLM's perlin/simplex functions from glm/gtc/noise.hpp? I'm curious if they would fare better.

@deanm
Copy link
Contributor Author

deanm commented Feb 22, 2016

Simplex noise is something else, so wouldn't expect to see anything similar.

I don't use GLM, but a quick look at:

https://github.com/g-truc/glm/blob/master/glm/gtc/noise.inl

Make it look like it's the GPU algorithm from McEwan/Gustavson, see 5.4 here:

http://webstaff.itn.liu.se/~stegu/jgt2011/supplement.pdf

Perhaps it is so they can match the same noise across CPU and GPU implementations, but using a permutation polynomial will be a bit different than how Cinder works currently. But anyway, yes this algorithm should improve the output.

@notlion
Copy link
Contributor

notlion commented Feb 22, 2016

Yup. GLM's implementation is based on webgl-noise which I believe was written by Gustavson. glm/gtc/noise.hpp is included with Cinder and has both perlin (classic) and simplex noise implementations which is why I mentioned it.

@meshula
Copy link

meshula commented Feb 23, 2016

Ashima's webgl-noise is great :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants