I was lucky to work on Cairn as Technical Art Director, I thought it might be interesting to share some of its "development secrets".
This one is about something I called "MicroMeshes". Basically it's small meshes batched in one big mesh, each micromesh have its local pivot stored in UV so we can do some fancy operations like billboarding, wind motion, etc... It's heavily inspired by "Vertex Shader Population" technique you can find in this Uncharted tech docs : https://advances.realtimerendering.com/other/2016/naughty_dog/index.html
More about Cairn :
https://www.thegamebakers.com/cairn/
Reach a summit never climbed before in this survival-climber from the creators of Furi and Haven. Climb anywhere and plan your route carefully, managing pitons and resources to survive the unforgiving Mount Kami. Discover what Aava is willing to sacrifice to achieve the ascent of a lifetime.
© The Game Bakers
The idea is to be able to draw lots of small meshes on terrain.
It's useful for debris, small pebbles, grass, foliage, etc...
Here you can see lots of micromeshes automatically follow level design and art changes.
But first, we WANT to place them manually. For this, I create a small tool called MicroMeshesDrawer.
You setup "micromeshes": billboards or regular meshes / tints / scales / etc... and it will instantiate them as you draw.
(me destroying level art)
Each "micromesh" has its pivot local position stored in uv2, so we can do fancy stuff like wind motion and player collision in vertex shader.
and optionally we do some vertex culling when micromesh is fading out at distance
Level artists used this one a lot for foliage but also for some vfx like falling water droplet in caves
(in the case the final mesh is invisible, vertices are only used as spawn points by a particle system)
Then, we want an automatic and more optimal way to place some kind of micromeshes (especially grass), here comes MicroMeshesProjection.
For MicroMeshesProjection, we use same mesh structure : we bake a big squared mesh full of micromeshes, this mesh is tilable.
At runtime, we render some terrain layers top-down to multiple Render Textures (2RT: Normals + Depth + Blendmap)
The previous big squared mesh is drawn manually multiple times using gpu instancing (a big grid in front of camera frustrum) with a custom shader.
We can render multiple layers of meshes (grass lods, rocks, etc)
in the vertex shader, we sample our mutliple render textures to :
- project using depth value,
- re-align/rotate usign normals value,
- attenuate scale using blendmap value.
Obviously it is far from perfect :
- Rendering MRT cost because of terrain drawcalls count
- sampling textures for each vertex is quite expensive
- it is top-down, so if you have something that occlude, it doesn't work...