Some background on how I'm rendering the water line, because it's almost arcane 🪄 #unity3d
The key goal is figuring out if a certain pixel on the screen is above, or below water. This in turn can be used to apply effects to a specific part of the screen.
I've tried a bunch of different things, none worked reliably, or were prohibitively expensive. Witcher 3 has this, so technically was possible! What ended up working flawlessly is rendering a subdivided plane directly on the camera's plane, then animating it.
Finding the point where it intersects with the water took the most effort, since it needs to account for any kind of camera rotation, aspect ratio and FoV. The green debug line represents this point. Started with a script here, easier to debug, then translated the math to HLSL.
With the intersection point (in world-space) known, the water shader's wave function is used with identical settings, so returns the exact same wave height. Position goes in, wave position comes out.
The waterline/meniscus does the same thing, and it drawn on top of it all.
The animated mesh is rendered into a 1/4th resolution texture, which can then be reused by any post-processing effect and shader. Teeny tiny gradient at the very top, as to remove any aliasing.
The underwater shading itself is garden-variety depth-based fog. It doesn't affect the water surface itself, instead the same shading functionality is incorporated into the water shader directly. So it ends up matching seamlessly.
But in order to prevent fog from affecting anything actually above the water, all the water meshes in view are rendered into a custom depth texture. This way it's possible to compare depth values between the water and environment, and exclude anything "behind" the water.
Final important visual factor turned out to be lighting. The fog/water color is lit by the directional light and ambient color, so it ends up looking mostly correct under different lighting conditions.
So, plenty of technobabble and nitty gritty details skimmed over, but that's the gist of my implementation! Proudest piece of programming so far, and it's 98% ready for the asset store 🥳
• • •
Missing some Tweet in this thread? You can try to
force a refresh