Question

I'm currently generating 2d Perlin noise to a 2d array and (after interpolation) rendering the results held as a height map (essentially array[x][z] = y).

This is fine for one array, but not for tile loading based on the camera position, and I'm having difficulty where the tiles should meet at the seam.

[Noise Tiles]

noise tiles

My best attempt has been to generate a large 2d array of the base noise (-1 to 1), then have each tile as an object that stores an offset value for the base grid (which part of the noise to read).

This has allowed me to sample (for interpolation) areas of the base grid that are much larger than the tile array, but it still not lining up!

My objective is to have a flycam that loads tiles as it moves, and can travel very far without repeating.


Is this approach of 2d arrays solid enough to handle the objective?

If so, how can it be implemented to tile or wrap correctly?

Was it helpful?

Solution

I have had similar problems before and after alot of tweaking and testing I've come to the conclusion that just plain 2D perlin noise as is will never look like natural terrain, it's essentially white noise(ie no huge mountains or valleys, just hills close together)

What I recently found as the way to go is by making a fractal out of multiple Perlin Noises but with different "resolutions" -if you will, added together to get custom terrain resolution using different octaves(ie higher octave = higher noise in your terrain). I usually go about using gain = 0.5(this really do not have to be changed much, it looks pretty good as is), and octaves = ~16

Note; this is made in processing, Java might have some different syntax, but it should be quite the same

float fractal(int x,int y,float gridSubs,float gain,int octaves){
  float total = 0;
  float freq = 1.0/gridSubs;
  float amp = gain;

  for(int f=0;f<octaves;f++){
    total += noise(x*freq,y*freq)*amp;
    freq *= 2.0;
    amp *= gain;
  }
  return total;
}

Website where I found it: here

If you replace your noise() function with this you might get better looking results in the end.


As for your problem with your seams you probably have the coordinate offset in the noise function call for each chunk set wrongly, it should look somewhat like this:

noise( localX * tileSize + (chunkX * chunkSize) , localZ * tileSize + (chunkZ * chunkSize) );

You might have to add some resolution koefficent to make the noise somewhat smooth.


Now You said you are storing the heightvalues in a 2D heightMap, now that is fine and makes the heightvalues easy to access if you need to update them often or need to access them easily.

The problem with this is the size of the array easily get very large, and by that I mean, Very large. With my past experiences I could get a small map(can't remember size, but smaller than yours) to eat up 4Gb of my RAM just by loading it. I did use a float array though so using an integer array could have reduced the memory usage slightly.

How I do it now is I just recalculate each point in the terrain whenever I need to update the geometry, how I currently have set it up it does introduce a slight lagspike each time the terrain is changed when moving around. The benefit is that I can have a 4times larger map with greater detail and still use about 1-2Gb of RAM.

Since what I understood, you simply want to move around the terrain and look at it. This would benefit from not storing the heightmap in an array, since you do not really need the values after you have generated the terrain(this may differ if you are manually smoothing out the terrain).


One last thing to note; I am not an professional programmer, this is just what I have learned from my past experiences using randomly generated noise.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top