Stylized Water 2
The shader is set to a material, which in turn can be applied to a mesh. It will always render in Forward rendering, due to its transparent nature.
The advanced shading mode takes more liberty and focuses on high-end rendering. If water in your game is only something that’s viewed in the background, or viewed from a top-down perspective it will offer little benefit.
Compared to the “Simple” shading mode it does:
- Chromatic refractions, color channels are split one pixel apart
- Caustics/sun reflection masking, even if the water does not receive shadows, the shadow map is read to avoid these effects being visible in shadows.
- Translucency color is blended with the light color more accurately.
- Double-sampling of refraction, to avoid the silhouette of objects above the water being refracted.
- 2nd normal map sample for distance normals.
It’s possible to hide the water in front of another mesh, in order to create visible holes in the water. This can be used to hide the water inside boats.
In order to do so, assign the “WaterTransparencyMask” material to a mesh, found in the StylizedWater2/Materials folder. Note that this hides every transparent material behind it, not just the water.
Network synchronized waves
All the shader effects, including the waves, use the global
_TimeParameters shader value set by Unity as a time index. This translates to
If you’re running a networked application, it may be important to ensure the waves are identical for all players (especially when using buoyancy). This requires a minor modification to the shader, to have it use a time value defined by your server.
Open the StylizedWater2/Shaders/Libraries/Common.hlsl file and uncomment the line that reads
Next, through script, set
StylizedWater2.Buoyancy.UseCustomTime to true. Then pass your time value every frame through
StylizedWater2.Buoyancy.SetCustomTime(float value). This function will pass the time value to the shader and buoyancy calculations, and keeps them in sync.
Toggling features in a build
The shader makes use of keywords, which allows specific code to be executed or bypassed entirely. Similar to C# scripting define symbols. The keyword states are saved on the material.
When building the project to the target device, Unity will compile multiple variants of the shader code. For example, one version where point/spot lights are disabled, and another where they are enabled. Ultimately, this allows for quality/performance scaling in real time. This is called a Multi-compile keyword.
For many features such as normal maps, foam and waves this isn’t the case. If a feature isn’t enabled on the material, and the project is built, a shader variant won’t be created with the feature disabled. This means you can’t toggle a feature on/off anymore. This is because the keyword is a Shader feature. This behaviour is by design though. Because multi-compile keywords exponentially increase the amount of shader variants/permutations. Using this for every feature can result in up to 2 million shader variants, which greatly affects build times (by hours).
To learn more about this, see the related Unity manual page.
Should it be important to still allow a feature to be toggled, you can modify the shader to convert a keyword into a multi-compile variant. To do so, open up the StylizedWater2.shader file. Locate the line(s) that read
#pragma shader_feature_local _WAVES and replace this with
#pragma multi_compile_local _ _WAVES. You can repeat this for any other keyword.
After which, you can toggle the keyword state on a specific material through
An (perhaps easier) workaround is to create two materials. One with the feature enabled, and another one with it disabled. You’d only need to use one of these in the scene. But as long as both materials are included in a build, a shader variant for both permutations will be compiled into the build, allowing it to be toggled on/off.