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

Worley noise feature point selection is needlessly slow and restrictive #177

Open
tayloraswift opened this issue Jun 9, 2017 · 0 comments

Comments

@tayloraswift
Copy link

Your current feature point selection code constrains the generated points along 8 axes (2D) and contains needless branching. It also creates relatively visually unappealing noise. A much better point distribution can be generated by using the hash values directly: (this is swift, i am not a rust programmer)

let hash:Int = self.permutation_table.hash(generating_point.a, generating_point.b)
// hash is within 0 ... 255, take it to 0 ... 0.5

// Notice that we have 256 possible hashes, and therefore 8 bits of entropy,
// to be divided up between 2 axes. We can assign 4 bits to the x and y
// axes each (16 levels each)

//          0b XXXX YYYY

let dpx:Double = (Double(hash >> 4         ) - 15/2) * 1/16,
    dpy:Double = (Double(hash      & 0b1111) - 15/2) * 1/16

I didn’t write down the benchmarks, but this ran about two to three times faster than a direct port from what y’all were using.

3D can be done like this:

let hash:Int = self.permutation_table.hash(gen_point.a, gen_point.b, gen_point.c)
// hash is within 0 ... 255, take it to 0 ... 0.5

// Notice that we have 256 possible hashes, and therefore 8 bits of entropy,
// to be divided up between three axes. We can assign 3 bits to the x and
// y axes each (8 levels each), and 2 bits to the z axis (4 levels). To
// compensate for the lack of z resolution, we bump up every other feature
// point by half a level.

//          0b XXX YYY ZZ

let dpx:Double = (Double(hash >> 5                                         ) - 7/2) * 1/8,
    dpy:Double = (Double(hash >> 2 & 0b0111                                ) - 7/2) * 1/8,
    dpz:Double = (Double(hash << 1 & 0b0111 + ((hash >> 5 ^ hash >> 2) & 1)) - 7/2) * 1/8

This also avoids some modulo biasing issues in your 3D hashing, as well as the modulo instruction.

Did not implement 4D, but it can probably be done by taking two 2D hashes of x, y and z, w, and then XOR’ing 4 combinations of 4 bits from each to get the 4 displacements.

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

No branches or pull requests

2 participants