This is a procedural ocean shader for Unity completely procedural and using mathematical noise for normal displacement instead of normal maps. The shader includes large wave displacement from wind direction, small ripple displacement from normaldistortion using noise, fresnel effect, depth rendering for foamlines and using scene height for large wave foam. Performance is around 70-80 FPS in HD resolution.
** Working on expanding the project into an unlit shader that computes reflection and refraction. **
The large waves are parametrized according to the wind direction and the wind strength, as well as how frequently the waves should appear (smaller wavelength). A set of trochoidal waves are used for displacement that successfully describes a progressive wave of permanent form on the surface. Since some problems occur with looping when the amplitude of a wave is too large compared to its wavelength, a third trochoidal wave is only added if a high enough wavelength are chosen.
The small ripples on the surface are consisting of a combination of Perlin noise with different octaves. This combination of noise with different frequencies creates an almost "cloudlike" feeling when using smaller octaves, and will be much more detailed with a higher octave.
In order to being able to use the depth texture, it is needed to enable this on the current rendering camera. Attach the following script to the camera that is being used for the scene.
[ExecuteInEditMode]
public class depth : MonoBehaviour
{
private Camera cam;
void Start()
{
cam = GetComponent<Camera>();
cam.depthTextureMode = DepthTextureMode.Depth;
}
}
If correctly attached, you can see the following appearing in the inspector for the camera.
When the camera depth texture exists, this can be used for calculating if points on the surface are near objects that cut through the surface or close to a shoreline.
float rawZ = SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(IN.screenPos));
float sceneZ = LinearEyeDepth(rawZ);
float partZ = IN.eyeDepth;
float fade = 1.0;
if (rawZ > 0.0) // Make sure the depth texture exists
fade = abs(saturate(_InvFade * (sceneZ - partZ)));
o.Alpha = 1;
if (fade < _FadeLimit)
o.Albedo += (0, 0, 0, 0) * fade +_ColorDetail * (1 - fade);