EDIT: UPDATED TO INCLUDE MORE RECENT PICS AND A VIDEO (ABOVE) IN THE FIRST POST
I’ve been looking at all sorts of commercial and non-commercial solutions for terrain environments and nothing seemed quite right for what I wanted. After a LOT of “auditioning”, I decided to roll my own custom solution.
Credit where it is due, scrawkblog.com was a great resource with code examples for getting into the guts of what I needed to do. I have a pretty deep background in rendering, but for the sake of expedience, a couple of algorithms were “borrowed” whole cloth, so thanks!
Anyway, here are some pics of a first pass at generating and rendering some procedural terrain in Unity. The intent is to create compelling environments for our conversational AI driven characters to interact with players.
It’s not where I want it to be yet, but I feel like I’ve got a good start on a customizable procedural system.
Looks nice! How did you manage to get the blending between materials so clean? or is this just a single ‘material’ with seperate top/side/bottom triplanar mapping?
Thanks for the feedback everyone. It is a WIP, but I’m happy enough with the foundation.
wasstraat65, I am currently using a single custom material/shader for the entire scene (excepting the skybox of course). The shader does use triplanar mapping for determining texturing coordinates, but has more complex parametric rules for blending various surface types so that I don’t need large color (splat) maps for each terrain.
Those screens were captured running 60fps at 1280x720 on an old machine with a GTX 555M processor, so performance is good so far. We’ll see what happens when I start adding more features.
Yeah like I thought. Have you thought of a solution to yet to blend several voxel types smoothly together? I currently only have hard edges between seperate voxel types, which are caused by using one submesh for each voxel type
Currently, the voxels themselves don’t have much effect on surface type(s). This is mostly determined parametrically at the shader level, so blending is handled procedurally.
That said, I am looking at embedding additional controls for the shader(s) into unused parts of the mesh vertex data. In particular, I’m interested in smooth transitions between multiple procedural shaders in order to sync up with large changes in terrain type. Maybe a multipass render for blending materials.
Here are some new images with improvements to terrain generation and shaders. Specifically, more surface types and controls in the shader, multi-uv support, and more complex terrain generation algorithms.
Kind of a big update. But I wanted to show some more features including auto-generation of winding paths into the hills, support for more layers in the shader, multi-uv blending that preserves color and surface normal richness, a more realistic look in general, more layers of mountain strata, snow at higher altitudes, etc.
Side note: In all of the screenshots I have posted, I am basically “exploring” the generated terrain in first-person mode.
I’ve optimized terrain generation, fixed bugs in the process, and I now have more intuitive layered parametric controls in the procedural terrain editor.
I have also moved ALL terrain surfacing decisions to the pixel shader. Mesh vertex color data is now free to use however I see fit.
Visually, texturing is much improved as are terrain geometry features. And what should be obvious, I now have added controls for automatic procedural placement of objects such as trees, shrubs, rocks, and even water.
I had problems picking screen shots this time because with all of these fixes and improvements, no matter where I go in the world every shot is a beauty shot. Also, there seems to be a painterly quality to some of these shots that I like.
This is probably a stupid question, but if I don’t ask I’ll never know,
What classifies this as ‘voxel-based’? A general answer will suffice, I’m an animator.
Most terrain systems work in 2D space, where one or more 2D maps are generated and/or painted to define the terrain features. At least one of these maps is applied to a grid mesh of polygons to raise or lower individual points in the mesh as determined by the maps. Unity’s built in terrain system works this way.
However, in a voxel-based terrain system:
Density values are created in a 3D grid space (voxels) instead of height values in a 2D map space (pixels).
For each voxel at a given 3D coordinate, the density value can be “solid”, “empty”, or something in between.
If a voxel is “solid”, no polygons are constructed in that voxel. It is completely “inside” the terrain.
4).If a voxel is “empty”, no polygons are constructed in that voxel. It is completely “outside” the terrain.
If the value is in somewhere in between, it contains a boundary between solid and empty that has to be calculated and rendered.
Using values at each corner of any “boundary” voxels, one or more polygons are calculated and created that conform to the density changes between that voxel and its neighbors.
In simple terms, because voxels are computed in all three dimensions of space instead of the two dimensions of a flat height map, they allow for things like caves, overhangs, and other true 3D geometries to be more easily and automatically created as part of the terrain generation process.
We’re finally approaching more realistic results better suited to the game we’re developing. The game design requires a “rocky desert” theme and now we’re finally getting there.
(see attached image)
Technical stuff: By switching to a lower resolution voxel grid, but augmenting with noise displacement and more detailed textures, we are getting overall better visual quality and greater distance views. Voxels are still converted to mesh data, but that mesh data is much more low res so we can hold larger terrain areas in memory.
With fractal noise, lower resolution voxels introduce more noticeable “terraces” (think Minecraft). However, adding a noise-based displacement mitigates this problem enough for our needs.
The terrain textures are from Yughues Free in the asset store (a total of 4 diffuse+normal maps used in this scene). The 1K resolution in these textures certainly helps. The rest of the scene is completely procedural (no hand editing).
For “infinite detail” I would like to someday use image-space pixel shaders like this:
Alas, it would be quite a time-consuming feat to integrate typical Unity gameplay elements with a non mesh-based solution like this.