Procedural Terrain with Dense Forests

[Edit]I asked a mod to change the title to be more accurate. Basically, I am building the terrain mesh from the heightmap data, and have my own system for grass, details and tree placement.
One of the main goals was that it support distant and dense forests. I think it works very well, see the 2nd or 3rd page.

I’m finally getting my homemade terrain to the point that it doesn’t look like junk.

This has been…interesting. You give it a heightmap, and define your custom LOD zones centered around the player, and it generates the terrain. You can see that the more distant mountains are less detailed, while the closer stuff is smoother. For each LOD zone, you determine how detailed it is, and how many “tiles” it is split up into.

The last bits where matching the seams up well, and also calculating the normals based on the heightmap. Overall…I think it looks nice.

I still need a good 8+texture splat shader :slight_smile: The one shown only handles 4.

Next…grass.
/wrists

Been working on drawing grass over the last few days on my terrain mesh.

Looks really good. I can never make terrain look like this.

Thanks. I’m especially proud of it as it’s all done procedurally.

hi there,

that looks really great, congrats!
and you have already done half the way.
but how would you self judge the speed compared to unity’s built in terrain?

lars

Thanks lars! Right now, it’s fast…about 350 fps on my machine, for a very large area of grass. But it’s not really a fair comparison, my grass is very simple at the moment. I don’t have another project handy that is similar enough, using Unity’s terrain and grass, to really compare it.

Currently, it
Splits the area into tiles of grass meshes.
Draws them using Graphics.Drawmesh (I need to add culling, that will help performance). Until then, it draws all of the grass meshes.
Places the grass very accurately on the terrain, based on the heightmap. No grass above/below the terrain. Finally found a bilinear interpolation function to help me with this, to get exact heights.
Randomize grass placement and rotation.

But it’s still in pretty early stages.
I need to make it move with the player (by moving/recalculating meshes on a separate thread).
Height noise.
Wind. I am going to have to have wind at some point, based on noise. I just got done looking at your shaders for this, but I’m really not certain how to “plug them in”.
And I’ll need to add support for more than one grass type.
I’d like to add curve support for slopes, so that on steeper slopes you have less grass.

Sounds good and the grass blending is looking great. How much memory does something like this use to generate during runtime or is this something pre generated?

I created a test scene using the same heightmap, one terrain texture and the same grass. Basically tried to make it mirror my own. Honestly, Unity’s seems faster and appears to use less memory. So I either need to do a better comparison that is apples to apples, or I have a lot of tweaking ahead of me :slight_smile:

The Unity scene uses about 350 mb, while mine uses about 500. But mine had more terrain textures and a different terrain shader, so again…I need to do a more even comparison.

hi jc,

;-( what a pitty…

that seems to be exactly the same way unity draws grass: using huge tiles or chunks.
and i am not sure if moving the grass with the player will be faster.

which shader do you use right now? and you might have a look at the advanced grass shader v2 or v3, which should be rather simple to be implemented. all you have to pass to the shader are the wind parameters.

i hope your system will support custom grass meshes – not only simple planes.
and it would be great if there was an option to align the mesh to the terrain’s normal (in order to get rid of floating grass on steeper slopes) either for a whole grass type or when painting.

great work!

lars

Got the shader working with some very simple wind. I’d love to be able to use a wind zone as input, but I’m not sure how to use one yet for my purposes. I created a simple wind effect just using some lerping, it’s pretty rough but at least gives me something for now. Thanks for the great shader lars.

I also had to toss in the awesome free ocean shader from the forums, it’s beautiful. It served as a brief distraction from an annoying issue with reducing grass on steep slopes.
Here’s the ocean picture:

It will definitely support meshes…the normals are very easy to get from the heightmap. But…I hadn’t really even though about releasing it as a nice, clean package on the asset store. I’ll have to give that some thought. Also, the system is somewhat tailored to the unique needs of my current main project. Heck, the only reason I started down this road is because Unity’s terrain system has some issues I just got tired of seeing.
But…this may be something I can clean up and make “generalized” enough for mass consumption. Will it ever support painting, or a nice UI? Um not sure. I honestly can’t seem to find enough time to scrape up to work on my main project as it is.

This is looking really nice. One thing that always drove me back to using Unity terrains, even after extensive efforts to program my own, is the automatic tessellation of Unity terrain. This seriously increases the performance of the terrain and I have yet to invest enough effort to explore this for my own projects. Just curious if you have any type of tessellation going on in your terrain? You mention LOD zones in your first post but it’s unclear whether these get reevaluated as the player/camera moves closer to the distant (lower) LOD zone… ?

Yes, you can add LOD zones around the player, and as you move the terrain is redrawn.

It’s pretty easy to setup. You pass in the path to the heightmap, and then give it the heightmap size in pixels, the actual terrain size. My example terrain is 2048x2048 pixels.

You define the LOD zones by telling the terrain how big the zone is, and how “detailed” it is. In the pictures I show, I have the furthest level of detail divided into 16 pixel resolution, 2048 pixels out. The next one in is 8 pixel resolution, from 512 to 128 pixels out. Around the player is an area 128x128 pixels then, at 1 pixel resolution. It’s easy to add another LOD. Here’s my inititalization

		V2 playerCellPosition = GetPixelPosition(_Player.transform.position);
		_HeightMap = new HeightMap(TerrainPath, 2048);
		_WorldData = new WorldData2(2048, 4, CollisionMesh, MeshCollider, transform, _HeightMap);
		_WorldData.CreateLOD(2048, 16, 256, _DistantTerrainPrefab, _HeightMap, 512, 8);
		_WorldData.CreateLOD(512, 8, 128, _NearTerrainPrefab, _HeightMap, 128, 1);
		_WorldData.CreateLOD(128, 1, 32, _NearTerrainPrefab, _HeightMap, 0, 0);
		_WorldData.GenerateCollisionMesh(playerCellPosition);

		_GrassGenerator = new GrassGenerator(128, playerCellPosition, _HeightMap, GrassMaterial, 16, 1024, 4);

		_WorldData.Update(playerCellPosition);
		_GrassGenerator.InitializeGrass(playerCellPosition);

		_ShiftDetectionDistance = 16; // Half the size of a region from our highest lod.

		_Initialized = true;
		_LastShiftPosition = playerCellPosition;

When you add a LOD using CreateLOD, the first parameter is the outer size in pixels. Then the pixel density. You can specify which prefab (material and renderer) to use for each LOD, above my distant one uses a distant terrain setup (no bumps on the terrain, for example). But the nearer ones do use bump maps for textures.

LODs are split into patches, for faster processing and keeping the vertex count down. So, the second LOD above is 512x512. It is split into patches, each one 128x128…so the 512x512 lod area is split into 4 patches across and 4 down. Looks something like this:

1292047--59305--$Terrain LODs.jpg

I circled the lod transitions.

It generates a local collision mesh, totally independent of the terrain mesh. You determine the radius.

1292047--59301--$CollisionMesh.jpg

The HeightMap class gives you heightmap based functions…interpolated normals, heights, etc.

Now…it’s still pretty rough imo. I definitely need to add more complexity to the grass…a noise texture for grass noise. And the terrain could definitely use more optimization…even though it gets a very nice framerate as is.

as far as i know wind zones are only made for the new tree creator shaders and only affect trees which have to be drawn each by each to react correctly to the wind. so i doubt that those would help you on grass rendering.

as most of us too.

and there is still another challenging part which are tree billboards… your latest efforts show that you are mostly able to draw mesh trees as fast as the terrain engine but what a lot of people really need is an advanced billboard rendering with correct oriented billboards along the y-axis, and correct dynamic lighting and shading.
personally i think this is the weakest part of the built in terrain engine as most other issues have already been fixed by third party solutions.
unfortunately i can’t really help much on this topic because whenever it comes to math,…

lars

Indeed…I don’t know how to solve the billboard issue either. I did some tests with the particle system, that seemed to work well. The billboards are y axis locked…but appear to pivot around the center of the particle, instead of the base of the tree which would require some tweaking. It’s not that big a deal, especially at a distance, but if you wanted close billboards you would notice that the trunk didn’t always touch the ground in the same place, if you tilted the camera up and down.

Applying a normal map definitely makes it look better though:
1292069--59309--$Billboard_Norm_1.jpg
1292069--59310--$Billboard_Norm_2.jpg

Once I have the terrain system where I want it, I’ll be putting it to use in my main project, and then I’ll turn to the tree/billboard system. If I can’t use the particle system, I’ll just use figure something else out :expressionless:

Lars, you know a lot more about shaders than I. With a pre-generated noise texture, how hard do you think it would be, when shifting the grass vertices, to sample the noise map and shift the grass by that amount? By providing an offset to the noise texture, you could “move” the wind across the grass by shifting the texture. Another vector could provide the direction that the grass is shifted (the direction of the wind).

i have never looked that closely into the grass shader but i think you do not have to look up a noise texture in order to get different bending on different clusters of grass.
in case you have to it would be “just” a texture lookup in the vertex shader – not a big deal but pretty heavy on computation.

and regarding the billboard issue: i think the c4 engine approach will still be the best!

What approach specifically? Batching up the quads, or ?

creating a depth texture, normal and shadow map for each billboard…

Gotcha.
Depth and normal are no biggie for me, with CrazyBump. But shadow map…a little trickier.

JC… If you haven’t noticed… I sent you a PM…
I really appreciate you work… Both of your threads have made for fine reading…
And…,
Lars… as I have said in the past… Much appreciation for your work also…

I have been continuing my work and I agree with you that the standard Unity Terrain has issues.
Therefore, I have been working to bypass those issues and use only Terrain Meshes…
Of course there is a whole new set of issues.
But, I find that my frame rate has skyrocketed and I can now make all data much higher quality and still run through the web player…

I found your thread here in an attempt to find a new way to use RunTime/Dynamic Foliage…
I have also found another fellow attempting what you are working on…
Here is his link to his Youtube Video…

Anyways, best of luck in your efforts and thanks…
:slight_smile: