Stylized Water Shader
7.Troubleshooting
(Mobile) Water turns invisible. Or depth/intersection effects disappear when running on the target device
If you’re using Forward rendering, check if your camera has the EnableDepthBuffer
script attached to it. In many cases this will fix any issues.
Or if you aren’t using shadows anywhere in the game, Unity still strip the functionality from all shaders that enables them to write to the depth texture. The depth texture is used by the water as a way to measure its depth.
To get around this, create a new empty scene with a shadowed directional light. Then add a few objects to it, ensuring that any shader used in the game occurs in this scene (eg. Standard, terrain and custom shaders). Save the scene, then add it to the build list. This way, Unity will not strip the “ShadowCaster” pass from all the shaders, retaining the depth writing functionality.
Water depth and intersection effect do not appear (on some objects)
If you’re using Forward rendering, check if your camera has the EnableDepthBuffer
script attached to it. In many cases this will fix any issues.
Objects intersecting with the water must use a shader that writes to the depth texture, otherwise there is no way to tell where it is positioned in 3D space. For instance, unlit and transparent shaders do not write to the depth texture. You can download a modified Unlit shader here, which does: https://staggart.xyz/public/Unlit_ZWrite.shader. For custom shaders, they need a “ShadowCaster” pass in order to write to the depth texture.
If using shaders other than Unlit shaders is not viable for your project, consider using vertex painting to paint the intersection effect instead.
(Mobile) When using an orthographic camera, water appears below other objects/terrain and intersection effects aren’t visible
This issue is caused by transparency sorting, mobile devices are less accurate in this manner. To rectify this, reduce the “Far clipping plane” on your camera until it starts to clip your geometry. By default this is set to 1000 units, which is overkill for orthographic scenes. Secondly, move the camera as close to the environment as possible.
These steps reduce the rendering range for the camera and therefore increase the accuracy of sorting. After which, the water should render correctly.
Fog post processing doesn’t affect the water
This is a general 3D rendering issue. Seeing as water/particle shaders are transparent, they do not write to the depth buffer. Fog is a depth-based effect, making transparent shaders virtually invisible to it. Circumventing this is not a trivial thing to do, and would at least require the water/particle shader to be modified. Unfortunately, I cannot offer such a solution as it delves more into creating a custom renderer (eg SRP).
This occurrence is barely noticed for shallow water bodies or particles close up.
Switching between perspective and orthographic camera changes water appearance
This is essentially correct, between the two camera modes, depth is rendered very differently and affects how the water is rendered. The material parameters should be configured for the camera mode you are actually using. This does mean you most likely can’t use a single material for both a perspective- and orthographic camera at the same time.
Waves aren’t high enough, even with the highest “Wave height” value
In this case, your water mesh is probably be very big. If you need higher waves than the shader value allows for, increase the scale of your mesh on the Y-axis to the same effect
Waves look very pointy, triangular
This is an indication that the vertex-density/polycount of your water mesh is too low. Add subdivisions to your mesh to increase the wave fidelity. Or consider creating a set of rectangular water mesh tiles in a grid.
Much like a pin-art toy; the more pins it has, the more detailed the shape becomes.
Transparency is set to 0, but water still has a faint bright color
This only applies to the Desktop shader. The transparency parameter doesn’t actually control the shader’s opacity, but rather controls the amount of visibility of the objects rendered underneath the water. This is known as a GrabPass. The water shader is built on the PBR model, so it inherits some shading properties such as fresnel, which explains the faint brightness.
This behaviour is by design, so it’s still possible to have crystal clear water, while retaining the refraction capabilities. Otherwise the water would simply turn invisible. When the “Unlit” toggle is checked, this is not an issue, since all lighting is overridden.
Refraction shows artifacts along edges
This is actually correct behavior, and is a common limitation of using a GrabPass. Essentially opaque objects above the water are also refracted.
A way around this is to render the geometry underneath the water into a separate refraction camera. However, the performance trade-off for such a technique is generally not worth the small visual improvement, which is why it is not implemented. It’s also something that’s can’t be toggled, based on quality settings, so would affect all users.
Water material looks black
If there is no Directional Light in your scene this may be the case. Most mobile setups do not use any lighting, for performance. In which case you should set the lighting method to “Unlit” in the Lighting tab.
Water surface flickers white and the intersection effects disappears
This is usually caused if there is no light source in the scene, or your scene-view has lighting switched off.
Objects show a pixellated white outline
This occurs when using Unity’s built-in MSAA and can be remedied by using an Anti-Aliasing image effect instead. This is because the depth texture Unity renders is created before MSAA is applied.
Surfaces looks jagged
This is due to compression of the shader textures. You can override this compression in the inspector under the “Advanced” tab.
This will impair a slightly larger memory cost as the two textures will be larger in file size.
(iOS) Black dots appear on the water
You can elevate this issue by doing taking the following steps:
- Unset the Sun object in the Lighting tab, if set
- Raise the Shadow Bias value on your Directional Light
`System.IO.File’ does not contain a definition for `WriteAllBytes’ error
The “WebPlayer” target platform does not support writing files to disk and is thus not supported. The WebPlayer functionality was officially deprecated since Unity 5.4.