I’ve been working on some realistic water for the game. Previous I created a simple stylized water with scrolling textures at different scales, and it looked fine when the game looked more flat (due to orthographic camera). But with the change to perspective camera and things appearing more 3D, the old water wasn’t cutting it. So I decided to make a new water shader.
I used Amplify shader editor for the first time for this water shader. I’m really loving it. It’s very intuitive to use, and there are very useful built-in nodes that would've taken more time for me to figure out if I were writing the water shader from scratch.
This water shader is massive and has a lot of features - depth transparency, refraction based on normals, foam around objects, trail behind moving things. And splashes using particle system emitter. I learned a ton making this water for the past few days.
Also I learned how to use command buffers, which is super cool as well. Before this, I relied on render textures and multiple cameras to get the job done. I'd create a new layer, make a child camera that only sees that layer, set a new render texture to that camera, and set that render texture as a global texture accessible from shaders. This worked well and I set those render texture to render at half res, so it wasn't bad for performance. But I was starting to run out of layers, because Unity only gives you 32 layers. I have a lot of layers for different physics and rendering masks I need (I probably need to look at all of my layers and remove some unnecessary ones).
Then I came across command buffers and it seemed like an easier way to do what I was doing before, with the added flexibility of being able to choose specific objects instead of relying on tags or layers. So now my water trail particle systems are put into an array, and I render everything in that array into the water trail command buffer, turn that into a global texture, and use that to draw trails on to the water plane. Command buffer opens a whole new world of possibilities for selective effects I can apply to objects without using more layer masks and cameras, so I'm super excited. I think it should be much more efficient than using multiple cameras too - I think it uses the main camera for rendering these buffers, so it should be rendering only once? Command buffer experts, please correct me if I'm wrong.
A lot of learning on graphics programming in the last few days. I'm going to use Amplify shader editor more and more, because it's so convenient and easier to visualize results. And I'm going to use command buffers more as well. I should actually use command buffers for everything and get rid of my children cameras. I have cameras for rendering characters only - for highlighting them when they're behind obstacles - and rendering enemy sightcones only - for rendering them on top of grass and water. For both of these things I probably could've used shader render order to render them on top, but I had good reasons for not doing that (both technical and stylistic). Now I can use command buffers for all those and get rid of those annoying children cameras. Woo hoo!
So the water was looking pretty good, but it was missing something big… I didn’t react to the characters that much. There’s the bubble trail as player and NPCs move around on water, but where are the water ripples?
This effect is achieved with a particle system that fires donut shapes when something collides with the water surface. These donut shapes are rendered on a separate buffer and then added to the normal map of the water.
I would like to try directional waves with vertex displacement and tessellation later, but for now this water is already looking more interactive than before. It’s fun to run around and create ripples everywhere.