Jonathan van Immerzeel, also known as Staggart Creations, talked about his lovely Stylized Water Shader and the way water shaders can be set up in Unity.
Hello! My name is Jonathan van Immerzeel, and I’m what you may consider a Technical Environment Artist. I had a programming background and organically grew into this role during my studies in the field of game art and production. In a nutshell, this means I focus on creating game environments and any of the tech or tools required to achieve what I’m going for. Shaders are what I enjoy delving into the most, but vegetation has a solid place in my heart, too!
Since 2017, I primarily operate as a self-employed Unity asset store publisher under the name Staggart Creations. Which – if you ask me – is a dream job! Additionally, I’m working on the environment for Lake, a game currently in production at Gamious. This project presents a wealth of world-building challenges for me to sink my teeth in. Every aspect of my skill set comes into play, which means there’s never a dull day!
Using Shader Forge I churned out a preliminary version, which was met with plentiful interest in seeing it as a separately available asset. Unlike planned, I put the entire project on hold to flesh out the water shader first, which I later released in September 2016.
Over the following years, I learned a great deal about what it means to be an asset store publisher. As well as many shader optimizations and quirks. The package has seen several improvements since its inception and was overhauled as a “version 2” last May.
It’s important to understand that water is a very complex natural phenomenon and can take on just about any form. It can arguably be one of the most complex shaders you’ll see at work in various games. This means a lot of its behavior has to be approximated.
Nowadays, levels of indistinguishable realism can be achieved. Realistic waves are often done through approximated equations, “Gerstner” waves being very popular in games next to FFT (Fast Fourier Transformation) on the high-end of the spectrum (seen in various movies as well).
I personally never strive towards realism in game art, but rather focus on believability and aesthetics. Fortunately, this means a lot of rules can be broken or bent and creates room for artistic expression.
By using heightmaps I found it was more straightforward to achieve specific looking waves, such as sharp or billowed waves, without needing an equation flexible and understandable enough to do so.
Textures are also easier to understand and author for artists than trigonometry, myself included. The package offers a set of premade heightmaps, with the ability to pipe in your own.
The water is made up of several layers based on cross-panning textures, the main influence being the color controls, though other aspects are not unimportant!
The inspector is designed in such a way that a user can move its way from top to bottom, where only one section can be expanded at a time. This was intended to avoid information overload, as it would be a long list of potentially confusing parameters otherwise.
Here follows an example of how a specific look is made up:
Refraction through water surfaces is what you commonly see in shallow water. As light passes through the water, to the viewer, it is distorted by the water surface. Causing a visual distortion. Physics are involved, but in the context of a shader, an approximated implementation is nothing too crazy.
Unity has a built-in texture which represents the scene before a specific object is being rendered, in this case, the water plane. Commonly known as a “GrabPass”. This texture can essentially be used to access the colors behind (or underneath) an object. Naturally, it being texture, it requires a UV, which in turn is free to be modified before the texture is actually sampled. That’s where I use whatever normal map the water is rendering to distort the UV.
I found it negatively impacted performance on several mobile devices. And seeing as the mobile shader can potentially be deployed to a large variety of devices, it’s best to play it safe. Especially since this wasn’t a function that could be toggled on or off. Which is why it’s not featured in the mobile shader variant.
Since the shader is a “surface shader”, Unity’s reflection probes work out of the box. These are very flexible since they offer full control over what they render, when and by which intensity. Though a reflection probe will fail to capture the nuances of a scene, such as a character or small rock. I personally think reflecting the skybox is the most important part since this largely represents a scene’s lighting. Reflection probes are perfect for that task.
Alternatively, “Planer Reflections” can be toggled, which will render the scene from a mirrored perspective into a texture. Subsequently, the texture can be distorted or blurred for added effect. This will yield the most accurate reflections, but is best utilized when only reflecting specific layers, rather than the whole scene, for performance reasons.
Fortunately, both methods can be combined.
I think anyone who’s steering towards a stylized art direction will find Stylized Water Shader to be a welcome addition to their environment. It is flexible enough to be turned into lava or toxic water need it may be. It supports a wide range of platforms as well as VR.