问题描述:

Firstly, I am new to asking questions here (although I have lurked about for quite a while) so please excuse me if I don't format or word things correctly.

Secondly, I'm not looking for links to any libraries (personally, I don't like them because I don't have access to the source... and, in my opinion, they feel like a potential security exploit waiting to happen), I'm just after plain old C code to do the desired task (preferably not using objects/structs).


I am trying to generate 2-dimensional noise, and I seem to have hit a roadblock.

I have written my own pseudorandom number generator, where you give it seed/input values and it always gives the same output (from 0.0 -> 1.0) for the same seed/input. In other words, it can happily generate deterministic 1-dimensional noise.

Using this method, I can create seperate x/y axis of noise (I would post example images to demonstrate what I mean, but I require 10 rep points to post images... but suffice it to say that they look like black/grey/white barcodes oriented horizontally/vertically)

However my efforts to combine to two axis have resulted in an image that resembles a black & white "tartan" type of pattern (again, I'd post demo images if I could). I'm after a "fluffy cloud" style pattern, like perlin noise generates.

My goal is to have a single function that when supplied seed/x/y values it gives the desired 2-D output.

Precomputing an array of values (which is the method I've found in several places on Google) is out of the question here. The noise is to be used for procedural world generation, and the 2-D input co-ordinates can go from -1,088,391,168 to +1,088,391,168 (for both x & y axis, which would be (4*(10^18)) bytes)... so the output has to depend directly on the input values given and calculated on-the-fly.


My question is: given two seperate axis of 1-D noise (x axis/y axis) how can I combine the two axis into a single 2-D noise value? Or in other words, how can I combine my horizontal and vertical barcodes together to create a 2-D noise field?


EDIT:

const double noise_x1 = Noise(seed, x);

const double noise_x2 = Noise(seed, x + 1);

const double noise_y1 = Noise(seed + 1, y);

const double noise_y2 = Noise(seed + 1, y + 1);

This gets the noise values for the x/y axis, and the noise values for the next x/y point. How can I mathematically combine these 4 values for use as the "corners" of the "grid cell"? Do I simply average them out?

EG:

const double noise_x1y1 = (noise_x1 + noise_y1) * 0.5;

const double noise_x2y1 = (noise_x2 + noise_y1) * 0.5;

const double noise_x1y2 = (noise_x1 + noise_y2) * 0.5;

const double noise_x2y2 = (noise_x2 + noise_y2) * 0.5;

And then what would the formula/algorithm be for interpolating the exact spot inside the given "cell"?

I've seen other people use "grid based logic" for noise but it seems to befuddle me :P


UPDATE (7:35pm, 30th October 2014, Australian Eastern Standard Time/AEST):

Upon digging even further into this problem, I've come across Morton codes (which aren't actually related to noise functions, although they can be used to "hash" the input co-ordinates into a single number). Morton codes interleave the bits of two input numbers like so:

First input number...

00000001 -> 00000000 00000001 = 1

00000010 -> 00000000 00000100 = 4

00000100 -> 00000000 00010000 = 16

00001000 -> 00000000 01000000 = 64

00010000 -> 00000001 00000000 = 256

00100000 -> 00000100 00000000 = 1024

01000000 -> 00010000 00000000 = 4096

10000000 -> 01000000 00000000 = 16384

Second input number...

00000001 -> 00000000 00000010 = 2

00000010 -> 00000000 00001000 = 8

00000100 -> 00000000 00100000 = 32

00001000 -> 00000000 10000000 = 128

00010000 -> 00000010 00000000 = 512

00100000 -> 00001000 00000000 = 2048

01000000 -> 00100000 00000000 = 8192

10000000 -> 10000000 00000000 = 32768

These two output numbers are then combined together into a single number. This process can be easily expanded out to work with two 32bit inputs (to form a single 64bit output).

The output number can then be fed into a 1-Dimensional noise function, giving deterministic output for any 32bit inputs.

网友答案:

The easiest way to get true, deterministic xD noise is to use some hash function to combine the coordinates together:

  1. Convert the coordinates into integers of the desired granularity.

  2. Hash the integers together. Your requirement is somewhere between a simple function that is used for hash tables and the overkill produced by cryptographic hashes. Where you strike the compromise is entirely up to you, so I can't give too much advise on which hash function to use.

  3. Convert the resulting hash into a float between 0 and 1.

网友答案:

Just use this: https://gist.github.com/KdotJPG/b1270127455a94ac5d19

2D, 3D, and 4D noise with significantly fewer directional artifacts than Perlin noise, and especially compared to what you're attempting to do.

相关阅读:
Top