"Rain is a big part of what sets the mood in the demo levels right now, so it’s super important. I was using the built-in particle system in Unity for rain and splash effects, but I wasn’t happy with it. The built-in particle system is nice for a lot of things, but it runs on the CPU so it’s hard to get the density I require for certain effects. CPU is already so busy calculating enemy logic, navigation, and other crucial things. Even when GPU instancing is enabled, I think the built-in particle system still runs its simulation code on the CPU, so it’s not possible to have hundreds of thousands or millions of particles.
I’d been playing around with compute shaders a lot, so I decided to make a compute shader particle system for the rain and splash effects… and it was the right call! Now I can have millions of rain and splash particles without leaving a dent in CPU usage because everything runs on the GPU. Compute shaders are hard to set up at first, but once you know the tricks it’s so amazing. And now that VFX Graph is out, many other people can experience the benefits of compute shaders without learning the hard coding part. I wish I could use VFX Graph instead, but I have a lot of legacy shaders and code in this project, so I can’t upgrade to Unity 2019 yet. Unity is killing it with VFX Graph, Shader Graph, and DOTS! I really can’t wait to start a new project with all those new things.
But back on topic - in the clip above, there are three things going on. 1 million rain particles, 500k splash particles, and reflective ripples. With some added wetness to the terrain shader. The rain particles are straightforward - instanced quads with some alpha falloff towards the top. Splash particles use flipbook animation inside the shader, though they’re really small so it’s hard to see the sprite animation. Their positions are the same as the rain particles, so they share the same compute buffer. No need to hit the GPU with the same math twice. And then reflective ripples on the terrain are all in the terrain shader - basically drawing dots that get added to the metallic and smoothness channels in the terrain shader. Getting dots to appear in random positions is probably the hardest part - that’s done with some pseudo-random functions inside the shader. It’s all pretty cheap.
So far I think it’s pretty convincing. There are more things I can do though. The terrain used to have lots of puddles with ripples, but those reflective puddles were really distracting for gameplay, so I took them out. They occluded the enemy sight cones and drew too much attention - it was messy. And turning down their reflection turned them into black pools, which looked ugly. Maybe I could find a way to bring them back."
Update Nov 2019: Previously I was using a baked heightmap of the level for splash particle bounce height. But this meant I had to re-bake the heightmap each time I moved anything on the level (very time consuming!). Also rain would have to only bounce off of static elements using this implementation. So I scrapped this system in favor of an orthographic camera looking down from above the player that outputs a depthmap. This camera doesn’t have to output a high resolution render texture since low precision is okay. In the GIF above, the dynamic heightmap camera only outputs a 256 x 256 texture, and it seems very accurate even when it goes to the edges of the buildings. I already have too many cameras in this game, but a camera that outputs such small texture will probably be okay. No noticeable performance hit so far… (c) Sean, the Wonhon: A Vengeful Spirit developer.
Rain is a big part of what sets the mood in the demo levels right now, so it’s super important. I was using the built-in particle system in Unity for rain and splash effects, but I wasn’t happy with it. The built-in particle system is nice for a lot of things, but it runs on the CPU so it’s hard to get the density I require for certain effects. CPU is already so busy calculating enemy logic, navigation, and other crucial things.
Posted by Super!com on