Monthly Archives: March 2017

Update 12: Terrain Generation Experiments

I talked before about the improved noise system. I’ve been playing around and experimenting with different parameters, getting some interesting results. The difference between a real island and my fake video game island is that of scale. I want mountains, sweeping rivers, wildly different biomes, all on one island that spans maybe only 1.5 miles coast to coast. So it wouldn’t make sense for my islands to perfectly imitate the natural forming islands of earth. I wouldn’t say the terrain of the islands below look realistic, however these islands might not have even been created using the same tectonic processes. I’ve thought a bit about how far a fantasy world can really deviate from the real world. I think, that If the world looks like it was formed by some sort of natural process then it gets a pass. The real question is weather these maps are fun to play and build on. They definitely provide some nice variation across seeds with each map having some distinctive features.

Below I’ve demonstrated the effect of changing lacunarity on an FBM noise which acts as an input to the frequency of a Ridged Multi noise. So thats one set of noise acting as an input on another noise. Lacunarity starts at 0.0 and increments by 0.1 to a final value of 2.5.

set1272 (1)

Lacunarity (2000 x 2000)

Below you can see the effect of changing the frequency of the input noise.

set2416.png

Frequency (2000 x 2000)

The problem with this noise generation is that quite often I get a dud seed, especially when using noise of lower frequency. Sometimes an island will be very small, or overly large. I’m thinking of writing a function which discards maps based on total landmass, then keeps trying new maps until it finds a good fit. I would only need to sample the noise few times, maybe 200 samples, to get a reasonably accurate landmass approximation.

Below is the effect of changing intensity on the input noise. It starts as a sphere because there is a radial gradient subtracted from the noise to act as a falloff. With our input noise having 0 intensity it means that the main noise has a frequency of 0, the noise becomes just a flat color.

set4752.png

Intensity (2000 x 2000)

set4216.png

Islands with increasing temperature (2000 x 2000)

image 3496.png

Island with biomes (1000 x 1000)

Update 11: World Generation Refactor

I’ve spent some time refactoring the world generation and building a useful world generation editor. I think having an actual visual interface to preview the generation in real time will be massively useful. Before, I would make changes to the algorithm in c++, then have to wait while it compiles and launches to see the changes. This is obviously painfully slow and make makes it very difficult to experiment. Now I can manipulate noise parameters in a custom editor and see the changes right away.

Noise
Before, all I could do with noise was stack them on top of each other with a blending function (Add, Subtract, Avg, Multiply..). However to get more exciting results the noise parameters need to be deviated by another noise value. So for example, now I can plug ‘Billow’ noise into the frequency parameter of an ‘FBM ‘noise. This kind of perturbation can get really interesting results.


Biomes
In all but the first post I ever made on the game you can’t see any biomes on the map. I actually disabled biomes because of a bug in the code. I’ve gone and fixed the bug and tweaked the whole biome generation system. I also wrote a script which takes the current world generation parameters and outputs one large image containg lots of maps using different seeds.

set

seeds

These maps above are using the old noise system. The mountains are just kind of splatted on top of the base noise. Next step will be to play around with the new noise system to create more natural looking mountains which blend into the terrain.

Procedural Planets

I put together a little planet generator a few months ago, thought I would share. The generation is based on several parameters like temperature(distance to sun), size, population etc… then it churns out these neat little pixel art planets. Pretty simple but a cool result, this was done in Unity3D.

23456789101112planetgen

Update 10: GPU Picking

Urho3d has a nice method for picking objects by casting a ray through the scene octree. This works well enough for picking objects using their AABBs but it was quite slow for picking points on a mesh. The issue now is that with the new terrain generation the mesh doesn’t even exist on the CPU, so it’s not possible now anyway. I thought about doing the picking on the GPU, and because,the world position for every point on screen has already been calculated for the positions buffer the work has pretty much been done already. Urho stores these buffers as textures, so I did a minor modification to the Urho3D internals and by binding the positions texture to a framebuffer I can do a glReadPixel() to get the value under the mouse cursor.

The issue with glReadPixel is that it’s super slow on some hardware, my mac was taking 10ms to get that one singular pixel. This is where ‘pixel buffer objects’ come into play. Using a PBO the call to glReadPixel is non blocking, so it won’t halt the application. Instead of reading directly into client memory the function will read values into a buffer, which you can retrieve values from later. A common set up would be to have 2+ PBO’s initiated, then alternate between reading and writing them each frame. So the data you get would be from the PBO written to on a previous frame.

Unfortunately my development machine is an older macbook pro and I was having real problems getting the glReadPixels to function asynchronously. Despite binding the PBO, when reading the pixels it would still halt the application. Despite lots and lots of testing I could see no solution to this, looks like a bug beyond my control. Very annoying, however I was able to gain some performance by placing the glReadPixel before the scene is rendered. The way opengl works is that it won’t read the pixels until every other opengl call has been executed. This was a large part of why it was so slow before. Also by using a 32bit float for the texture instead of 16 bit half float seemed to help as well. I was able to take the performance to under a millisecond, however it seems to spike randomly, taking 5 to 10ms every 10th frame or so. On better hardware with proper PBO support it shouldn’t be any issue.

I’ve set up my shaders so they write an object ID into the alpha channel of the positions buffer. So figuring out the type of object under the mouse is easy. The idea is that I would use that ID to cull objects from a CPU side raycast.

Here you can see the results, I am now able to use the mouse to draw onto the terrain in real time. Converting grass tiles into sand tiles.

Screenshot_Sun_Mar__5_14_24_19_2017.png

Screenshot_Sun_Mar__5_14_24_50_2017.png

Screenshot_Sun_Mar__5_14_25_20_2017.png

Here is some good reading on PBO’s:
http://http.download.nvidia.com/developer/Papers/2005/Fast_Texture_Transfers/Fast_Texture_Transfers.pdf
https://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-AsynchronousBufferTransfers.pdf