I am looking for opinions on the use of DOTS for generating large forests. Previously on this huge 49km x 49km sector of real world terrain the Unity Terrain would slow to a crawl if you got half the density needed to simulate a southern Appalachia rain forest. I converted all 49 terrains to mesh and got a few hundred FPS back. I then replanted the trees and other vegetation and got a thicker density for those that were by the roadside. However…it is a track simulator with 318 turns in 11 miles and the number one motorcycle run in the US and one of top 10 in the world so i would like some major degree of fidelity to the actual tun (Tail Of The Dragon, Hwy 129 Robbinsville NC). There are dozens of corners and straightaways where the view extends for miles and consists of rolling mountains that are thickly forested. Framerates drop here, Occlusion Culling used to kill framerates circa 2017 and entire grid sectors would be missing coming around bends only to appear joltingly
I have been wondering how DOTS may be able to assist me in keeping framerate up while having a dense forest canopy. I would be using SpeedTree trees, Low poly hand made trees for farther away and dense roadside vegetation I created from photos of local species. I would like to weigh some options and opinions as well as figure out before i get into it whether I am going to cause myself unsolvable headaches. This is a fixed price contract and i don’t want to end up making flipping burger wages because i whiz banged myself into a corner with the latest tech.
Well it’s not going to make things render faster if you’re bandwidth bound on the GPU. So make sure you check that and eliminate that first.
As for culling, which is the only actual use you’d have from DOTS, compare with C# culling first. It’s why I’m leaving a note of caution here.
Back when I did forests, they were all pre-batched in clumps and as you got further away, merged into more optimised clumps so culling never became a thing on the profiler, and I wouldn’t have seen a benefit going with DOTS.
Now if you’re going to be changing those trees often then DOTS will above and beyond perform better.
From what I understand of the megacity demo, the sub scene workflow is likely what you’re looking for to load and unload parts of an environment quickly and have an LOD system render the detail you need. The big BUT here comes from a few comments I’ve seen from Joachim on the forum saying that the sub scene workflow only works / is designed to currently work with static entities that are effectively baked into each subscene as it currently hinges off the GameObject authoring workflow. Generated entities don’t get a few of the luxuries that converted entities get.
I wouldn’t know what to suggest apart from waiting for DOTS to mature towards this use case more. But my rule of thumb for DOTS is to never use it if there is any rigid time or budget constraints.
If you could perhaps adjust the scope of the project to be a fixed environment rather than a generated one so you can use the subscene workflow like it was done in megacity then you should go for it since you’re following in someone else’s footsteps and not pioneering on your own.
megacity is not the same problem as a forest with a lot of the same tree. Megacity tests the scenario where you would want to stream a lot of unique geo in and out of memory in realtime and you don’t necessarily have visibility info baked either.
Forests are all constructed from things that are essentially the same models so you can actually achieve higher perf not doing that.
But DOTS can work if you don’t want to put a lot of work into it and just brute force too…
How did you achieve the “more optimized clumps”? I could use something like this and an editor script that follows the road and raycasts every ten meters for grid sector visibility, divide the road into sections/distance markers based on when grid sector visibility changes, using those to preactivate those grid squares and forests on approach at runtime. Perhaps even “stream them in” at so many per frame to avoid fps jolts. The toughest part so far was getting that mountaintop treeline to look anywhere near realistic and I don’t want to hide it behind fog.
Vegetation Studio pretty much uses all the best known approaches, and it’s going to be updated for SRP before too long also. For this problem you can’t really beat it, or even get close with anything DOTS offers (VS uses the job system itself for placement).
The big hit with cpu culliing isn’t the time spent culling (if using jobs), it’s having to send all the data to the gpu every frame. VS uses instanced indirect and stores partitioned data on the gpu and also uses billboards. Plus all of the other details involved that are vegetation specific.
Hybrid renderer you could make work with severe limitations and then only if you are on SRP. But it would still suck in comparison to VS most likely.
Also if mesh terrains are beating the Unity terrain something is wrong. Turn on instancing and also grab a decent shader like Microsplat and there is just no way a simple mesh workflow beats that.
I have MegaSplat… couldn’t get the terrain to match the terrain in the real world I am producing. Got better non-abrupt transitions with just Unity splats. I have 49 sq km to cover…some views are over 6 miles…some are 100 yards. I can build a billboard system in a few hours. My experience with almost very terrain and vegetation app is you gotta follow their rules…it takes some setup and a learning curve and after all the hoopla I was disappointed. I probably spent over 1K USD on toolsets so far.
I’ll offer a few thoughts. (An aside: I haven’t driven Tail of the Dragon, but I did drive the Diamondback which is just up the road. I’m sure it would have been way more fun on a 2-wheeler, powered or not, than in a 4-door Kia sedan with an automatic transmission.) I’ll echo the recommendations for Microsplat and Vegetation Studio. I’ll also plug EasyRoads3D which I’m using for my own real-world simulation, although mine is far less exciting and much, much, flatter (Florida).
My observations of the roadside in NC: the forest is really dense. You probably only need detailed trees really close to the road. I’m assuming you won’t be allowing players to free-roam throughout the forest. Any trees more than, say, 10 meters from anywhere a player could get to, likely don’t ever need to be anything other than a billboard.
That said, I don’t really see DOTS being all that helpful here, other than the sub-scene workflow part. Most of the density is far too distant to need individual handling of entities. You’ll really only have the immediate trees (~10m radius), even the roadside trees ahead more than that distance probably don’t need full 3d detail, unless you’re trying to simulate wildlife hiding behind individual branches.
One other thought: is it possible to billboard an entire terrain? On of the nice things about a mountain scene is that if you’re looking at a distant (say 1-2km) terrain that is behind foreground terrain, using a billboard for the terrain + vegetation is probably indistinguishable from a real terrain + billboard vegetation, especially for a (I’m assuming) motorcycle driving game where spending that much time paying attention to very distant parallax errors is probably going end in a crash.
In reply to your previous question ipp, basically I simply did HLOD or hierarchical lod, but simpler. This is always faster. The concept is simple:
you have a pool of reusable trees and store the settings for each one, position etc.
you generate merged batches of trees, these are in cells in the world, and typically quite low poly
repeat step 2 again as many times as needed so the futher out you get the more stuff is merged and decimated
This generally uses less memory than storing all the trees for all the terrain and is a typical technique used by GTA 5 and similar open world games: they just merge separate draw calls into bigger batches the futher away you are, and reduce the polys of those batches.
As colin says above, you really only need the individual ones right up close. In fact you might even find some light using a technique like amplify impostors.
There’s a few gpu instancing packages (veg studio is not the only solution) so look for what might suit doing less work. The HLOD approach is the most work for the fastest performance. It’s always faster because it works best how the GPU works: less verts, less state changes, less calls… but there is no off the shelf HLOD solution for Unity at present and further work would be required to tailor it for pooling.
TLDR: try impostors for dramatic poly reduction or instancing assets for dramatic batch reduction like gpu instancer. Vegetation studio is a heavyweight full on solution. I like it but it’s too heavy for my projects. If your project is all about the vegetation and you need a fully managed dynamic solution then it’s ideal.
If you just want a faster forest on desktop and you dont look too close, and don’t want to mess about changing much then look at impostors or GPU Instancer.
Of all these only the HLOD solution is good enough for mobiles, since you can’t really use cutout there.