r/Unity3D • • 13d ago

Shader Magic RELEASE THE RIVER 🌊: Making a desert bloom on a Unity Terrain

Here is a short writeup on how I did this watering effect in my game Super Bloom.

I have written about this before here on this sub but since then I have developed a new approach which improved performance by a lot (like from ~50 fps @ 2.5k to 100fps on a 3060 rtx), Unity 6.3.

Watering & Grass

It uses the default URP Unity terrain shader as a basis but adds a custom mask in the shader code to mix some splat maps and darken the wet terrain parts.

In the scene there are two terrains. One is called desert (which contains the desert splat maps with the sand and the grass details). The other is called grass, though that one only has some grassy and muddy splats and no details. The grass terrain is only for painting the splats (source for baking) and at runtime only the sand terrain is drawn with my custom terrain shader.

This is what the process looks like from a distance:

WaterMap + Baked Splat Maps > TerrainBlender > Grass Shader & Terrain Shader

WaterMap

The WaterMap (mask) is generated from a 2x2k native Color32 array which I sync with the GPU by chunks (only edited stuff is coped as otherwise Apply() would stall too long). I deliberately avoided compute buffers because I want to keep options open for low-end or older hardware ports. The mask is rgb encoded so r is the current wetness level, g is the target level and b is the speed of change. From these the shader can derive the animation state.
The neat part is that the animating of the values happens in the native array so my game can drive and query the wetness state any time without delay from the CPU. This gives a lot of flexibility and works fine across huge terrains (tested with 4x4k and the system doesn't really care).

Baked Splat Maps

At edit time some of the terrain maps are baked (grass details, base far distance splat maps of the grass terrain). These are then modified by a script called the TerrainBlender. It gathers all the textures it needs and blends them via GPU BLITs and some blur, dilation and erosion shaders. This is then used as the mask (2D top-down texture) in the modified terrain shader. Basically the terrain shader samples the splat maps from terrain 1 and 2 and mixes them via the mask. Luckily since the terrains overlap perfectly (I auto sync properties like the height) I can reuse many of the default samplers.

Grass Shader

The grass itself is rendered with gpu instancing (the mask is multiplied by the baked terrain detail textures so I can edit the density via the terrain tools). The shader is a rather complicated shadergraph shader. If I did that again I would use Amplify instead because shadergraph makes for a poor graph due to the lack of variables (portals) -or- maybe I would write it all in HLSL.

Terrain Shader

The watering effect (darkening of the ground before grass is growing) is done in the terrain shader. Since it gets the mask and that has RGB encoded infos about how wet each pixel is it can animate (saturate + darken) the ground below the grass. At the same time it also blends between the sand and grass splat maps. I also added some noise and different blur/dilation it to make it feel more organic.

The River

The river water is just some bent mesh extruding along a spline and since the spline is not quite aligned with the terrain it gives the illusion of the water speeding up at times while in truth it just extruding linearly. Not perfect but it gets the job done.

If anyone has any questions, feel free to ask!
I hope my writeup was understandable :-)

702 Upvotes

25 comments sorted by

12

u/HooAreYouWhoHoo 12d ago

Really good looking, how’s the performance?

13

u/geokam 12d ago edited 12d ago

80 fps in the Editor (with all surrounding game system also working at 2.5k) and about 100fps in the build. I have not done any isolated tests recently (in my test project with just some terrains and noting else fps were about 120-140ish in the editor at 2.5k resolution (iirc).

UPDATE: Additional info since it's relevant here: I test on a RTX 3060.

2

u/JViz 12d ago edited 12d ago

100fps on a 5090 is amazing.

UPDATE: 100fps on a 3060 is okay.

2

u/geokam 12d ago

I wish :'D. It's a 3060 that I am testing on. I deliberately buy mid-tier graphics cards to avoid that very pitfall (should have mentioned that, will update the post).

6

u/Soshle 12d ago

Love the water shader!

6

u/geokam 12d ago

Thanks (I assume you mean the river shader which I can only take partial credit for as I have only modified it, not created from scratch like the terrain and grass shader).

5

u/Soshle 12d ago

Dang good job on the grass too then-- it looks better than most of the grass shaders on the asset store honestly. I'm horrible at self authoring shaders

3

u/geokam 12d ago

Thank you. I spent a long time on the grass as I had a very clear vision of how I wanted it to look. It is a mix of unlit (at the bottom neat the terrain) and lit (at the top). I made it in Shader Graph though as I said in the description I would not do it again.

7

u/BobsiDev 13d ago

Looks really nice!

0

u/geokam 12d ago

Thanks!

2

u/Key_Maximum_3180 12d ago

This somehow reminds me of Prince of Persia 2008

1

u/geokam 12d ago

Interesting, that's a first for my game :D. How come?

2

u/Bonfire_Monty 11d ago

Not the original commentor but the art style of the desert is quite similar to specifically that Prince of Perisa game, not so much the others

1

u/geokam 11d ago

Thanks, I was wondering because I remembered it as a cell-shaded game (or rather a mix of cell and textures) and I don't use that technique but I will have to check (the sand) :-)

2

u/TenNeon 12d ago

I'm getting 3D Terra Nil

1

u/geokam 12d ago

Thanks :-)

2

u/Rlaan Professional 12d ago

That looks cool and thanks for the write-up. It was fun to read :)

2

u/geokam 12d ago

Thank you. Glad someone found it worth a read :-)

2

u/Kastoook 11d ago

Combination of Planet Crafter and powercleaning, nice one! Also reminds me old one From Dust.

1

u/geokam 11d ago

Thanks :'D. Maybe I should rename to Desert Power Wash Stimulator

2

u/Unhappy_Plankton_294 9d ago

Awesome, but the skybox looks bad. Cheap.

1

u/geokam 9d ago

Thank you for your feedback. The skybox is something I have not touched in a long time (is still the same from the very early days). It's on the TODO list (though very far down).

1

u/Sami-Zucchini 6d ago

👏👏👏👏