A new version of our low poly terrain tool - Polaris - has been started for a while which aim to supercharge runtime & editor performance, enhance workflow & experience, strengthen assets integration and many more.
In this post, we will give you a first glance at what we've achieved so far!
*This post was written during the development of the asset. Things are subject to change.
Upgraded foliage renderers
In this version, tree and grass renderer are completely destroyed and rebuilt. Culling process now done quickly and precisely, which greatly reduce the workload put on your GPU, while efficiently use the spare power on the CPU. It also comes with better LOD-ing so you can build more complex outdoor scene.
Cell-based culling for tree
The terrain space is recursively subdivided into smaller "cells" using quadtree, where each cell contains 4 children cells. We test each cells agains the camera view frustum, if a cell is culled, we can quickly remove all children cells from the visible set.
Applying this method offer a huge gain in culling time.
![Cell-based culling](https://static.wixstatic.com/media/8755ac_3db3467efbbf4da4a6df65edf3289246~mv2.gif)
To squeeze it even more, we shrink those cells so they only encapsulate their content:
![Cell-based culling](https://static.wixstatic.com/media/8755ac_1e4c1d0226304a7f8ba1beccb04ed5c9~mv2.gif)
Additional level of detail for tree & grass
Tree & grass now support an additional LOD1, where you can choose to use simpler models and materials that take less time to render on the GPU (fewer vertices, disable expensive visual effects such as wind, translucency, etc.)
![Tree LOD visualization](https://static.wixstatic.com/media/8755ac_40bcf2782a1848de9a554301c411a07a~mv2.jpg/v1/fill/w_980,h_577,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/8755ac_40bcf2782a1848de9a554301c411a07a~mv2.jpg)
There is also a "LOD Transition Distance" setting to nicely blend between LOD.
![Grass with LOD0 and LOD1. Far away instances don't sway, have less vertices and no shadow by default.](https://static.wixstatic.com/media/8755ac_978c413b6eb04130af260f07f2dd9e06~mv2.gif)
Ever wonder why we can reduce the grass vertex count without changing it look? Here's the trick:
For LOD0, we use a regular quad mesh:
![Grass rendered as a quad, 4 vertices](https://static.wixstatic.com/media/8755ac_fd29d7db7edf4c0ba4a39cbbb21894b8~mv2.jpg/v1/fill/w_980,h_986,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/8755ac_fd29d7db7edf4c0ba4a39cbbb21894b8~mv2.jpg)
For LOD1, we use a flipped triangle, where the tip goes deep below the "zero line"
![Grass rendered as a flipped triangle, 3 vertices, weird to look at but does the trick as seen far away.](https://static.wixstatic.com/media/8755ac_adf3affbd6d145e2934bb07392e73d5c~mv2.jpg/v1/fill/w_980,h_998,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/8755ac_adf3affbd6d145e2934bb07392e73d5c~mv2.jpg)
Just 1 vertex? That doesn't sound impressive!
Hold on, the saving is far more with other grass shapes, especially when you have millions of instances.
LOD0 vertex count | LOD1 vertex count | Save % | Save per 1M instances | |
---|---|---|---|---|
Quad | 4 | 3 | 25% | 250K |
Cross | 8 | 5 | 37.5% | 375K |
TriCross | 12 | 7 | 41.7% | 417K |
Clump | 60 | 45 | 25% | 250K |
Benchmarking
We've setup 2 project in Unity 2022.3.9f1, one uses Polaris 2021 and one uses Polaris 3, with a grid of 3x3 terrains with the same settings and compare the result using Unity's analysis tools (Profiler, Frame Debugger, Stats).
System specs:
Intel Core i9 9900K, 3.6 GHz, 16 cores
NVIDIA GeForce RTX 2060
Note: result may differ depending on machine specs & scene setup. Data below is for reference only.
Time spent on the TreeRenderer.Render() function with 135K trees in the scene:
![Time spent on tree Render() function](https://static.wixstatic.com/media/8755ac_ef24ad05b94b4bae9672423addb0b757~mv2.png/v1/fill/w_752,h_447,al_c,q_85,enc_auto/8755ac_ef24ad05b94b4bae9672423addb0b757~mv2.png)
![Stats from the Profiler](https://static.wixstatic.com/media/8755ac_0b6b870c32714bfe9ff3a8df93ea9f2f~mv2.jpg/v1/fill/w_980,h_360,al_c,q_80,usm_0.66_1.00_0.01,enc_auto/8755ac_0b6b870c32714bfe9ff3a8df93ea9f2f~mv2.jpg)
Frame time & stats with 135K trees in the scene:
![Polaris 3 scene stats with 135K trees](https://static.wixstatic.com/media/8755ac_e2860ab9cda242b7ac018ced8e9f9059~mv2.jpg/v1/fill/w_980,h_588,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/8755ac_e2860ab9cda242b7ac018ced8e9f9059~mv2.jpg)
![Polaris 2021 scene stats with 135K trees](https://static.wixstatic.com/media/8755ac_fc2e8c9d2a094766b73c61a56f474489~mv2.jpg/v1/fill/w_980,h_591,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/8755ac_fc2e8c9d2a094766b73c61a56f474489~mv2.jpg)
Time spent on the GrassRenderer.Render() function with 1 million instances in the scene:
![Time spent on grass Render() function](https://static.wixstatic.com/media/8755ac_e0bfe62db6e1433bb6a13aafe2b13106~mv2.jpg/v1/fill/w_752,h_452,al_c,q_80,enc_auto/8755ac_e0bfe62db6e1433bb6a13aafe2b13106~mv2.jpg)
Frame time & stats with 1 million grass instances in the scene:
![Polaris 3 scene stats with 1M grass blades](https://static.wixstatic.com/media/8755ac_9854cf9e66d2420383665b33265cc849~mv2.jpg/v1/fill/w_980,h_583,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/8755ac_9854cf9e66d2420383665b33265cc849~mv2.jpg)
![Polaris 2021 scene stats with 1M grass blades](https://static.wixstatic.com/media/8755ac_00b9361d785a4d5f8fb2d1a696a9dc13~mv2.jpg/v1/fill/w_980,h_581,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/8755ac_00b9361d785a4d5f8fb2d1a696a9dc13~mv2.jpg)
You can see that Polaris 3 has a reduction in batches & vertices count, which is valuable especially on mobile devices.
Frame time & stats in the Demo_00 scene:
![Demo_00 scene in Polaris 3](https://static.wixstatic.com/media/8755ac_5d5d4f08429341a488408ddbcdeb4460~mv2.jpg/v1/fill/w_980,h_588,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/8755ac_5d5d4f08429341a488408ddbcdeb4460~mv2.jpg)
![Demo_00 scene in Polaris 2021](https://static.wixstatic.com/media/8755ac_220bc093646e4b419c15d842927d4685~mv2.jpg/v1/fill/w_980,h_581,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/8755ac_220bc093646e4b419c15d842927d4685~mv2.jpg)
It's clear that there is performance gain for existing scenes, just by upgrading the asset.
Improvement to low poly terrain mesh generation
Seams matching
Seams matching between terrain tiles will now write to the terrain datas.
Prior to this, adjacent tiles will calculate the median height value at a point "on the fly". This introduce a problem that seams won't match anymore if you dynamically load/unload tiles.
With this change, it's now easier to do terrain streaming without breaking the scene.
Mesh creation
It just got faster!
After a several optimizations, the Profiler showed an impressive result:
Processing time is about 334% faster.
Heap allocation is about 248% less.
Actual time may vary depending on your setup. We've a few screenshots of stats on the Discord channel.
Final words
And that's what we've got so far. Good things are coming!
Follow our devlog to learn more about exciting features ahead.
Low poly terrain creation is just a very small part of the making of your game, we hope our effort for Polaris can contribute something to your game's success.
If you're using or plan to use Polaris in your dream project, we're proud to be a part of it.
Comments