1
\$\begingroup\$

I'm using perlin noise to calculate different values for 3d block-world terrain. I calc roughly six (at most) noise values for various terrain features for every 4 blocks in a chunk. The missing values are then filled in by a linear interpolation method. I've built most of this from looking at how existing games like minecraft, terasology, etc do it.

The terrain I've finally wound up with is exactly where I want it - it looks great. However, the game FPS drops heavily any time a new set of chunks are loaded as the player walks.

Each chunk is 16x16x128 blocks. At max settings, the player may have 10 chunks in every direction visible, so if you walk sixteen blocks forward, roughly 10 new chunks are loaded and ten unloaded.

Even with calculating noise for only 1/4 the blocks in a chunk, the performance hit is too much. I've run some profiling and it's the noise calculation method that's the culprit.

Obviously, I need to address this. I just need some advice.

  • Are there any specific perlin/simplex implementations that are known to be tuned for performance?
  • Would it be possible/advisable for me to run all of the noise calculations asynchronously and then pass those back to the main thread for actual block-fill and rendering?
\$\endgroup\$
3
\$\begingroup\$

Moving the chunk generation into another thread can keep the fps relatively constant while the terrain continues generating. In my limited attempts to create voxel engines, there was a significant benefit to moving the creation of block faces (in addition to the noise generation) into a different thread. Something like a 'chunks to generate queue' can be made, and chunks can be added to this todo list as the player moves around. A chunk in this sense is both the noise-generated data, and a mesh or collection of vertices. Chunks nearest the player can be prioritized. Also, having cube chunks (e.g. 32x32x32) is an option for worlds that don't want specific limitations on their height.

I can't speak to specific noise generation implementations in java, but simplex noise is faster than perlin noise as more dimensions are introduced. Your lerp technique, as well as resampling an existing section of noise are other tricks to reduce the total number of calls to a noise.generate(x,y,z) function. Reducing the octaves can also affect speed significantly at the expense of some detail.

Some elements of some generation themes can also avoid new calls to noise altogether. As an example, I've created a temperature gradient for a hemisphere of a hypothetical world by mixing a gradient with a small section of existing noise. A seeded pseudodrandom number generator and varying types of automata algos can also produce some interesting results.

\$\endgroup\$
2
\$\begingroup\$

Have you considered moving your terrain generation to the GPU? I have had huge performance increases since I started creating height maps in shaders rather than on the CPU. A good way to do this, if you're interested, is to implement Perlin noise as describe here and render the result to a texture using a framebuffer object. Good luck.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.