OCEAN MODULE
In General
  Waves from the movie "Dunkirk" compared to waves generated by this module.

The simplest way to create an ocean wave is to use a variation of the sine formula. However, creating a realistic display requires a lot of waves. But using the sine formula to compute all of these waves is slow. The iFFT (or Tessendorf) wave generator uses an inverse of the FFT (Fast Fourier Transform) method to quickly generate a lot of waves.

There are now several versions of this module, which are all available on our GitHub repository and have all been updated to r180.

The WebGPU versions include:

* Ocean - This is the latest version that uses compute shaders and is available in the jsm directory.
* Ocean4 - This is an update of the WebGl2 version and is available in the xtra_perm/jsm directory.

The WebGL2 version is:

* Ocean3 - This version uses texture shaders and is available in the xtra_perm/jsm directory.
History

Our initial challenge with creating this module was that we were unable to find a current example of a three.js iFFT wave generator. The best example we found was a three.js wave generator created in 2015 by Jérémy Bouny, based on a 2014 js version created by David Li which was adapted to three.js by Aleksandr Albert.

Attila Schroeder created an updated version of the WebGL2 program and assisted us with converting that into the Ocean2 module. In doing so, we combined all of the Jérémy Bouny programs and shaders into a single program. We eliminated the portion of the program and the shaders used to create the final display. Instead, the program simply creates displacement and normal maps which you can use with standard three.js materials. We eliminated the program dealing with reflections since you can create reflections using three.js materials.

Attila then created an improved version of the program and assisted us in converting that into the Ocean3 module. For a short time, we were able to use the module with NodeMaterials which provided better materials.

Attila Schroeder then converted his WebGL2 program to WebGPU. When NodeMaterials were no longer available in WebGL2, he helped us create a GPU module (Ocean4).

Attila then created an improved WebGPU version that primarily uses compute shaders (available only in WebGPU). And, as before, helped us convert his program to create what may become the final module, the one we are using now.

Using the Current Ocean Module in Your Program
Import Module into Program

In a three.js program, you import all the three.js and other modules at the beginning of the program. You use this instruction to import the Ocean4 module:

import {Ocean} from "https://PhilCrowther.github.io/Aviation/jsm/Ocean.js";
Variables

The Ocean module uses the following variables to store data.

//- Grid Square Data
let GrdSiz = 2400;      // Smallest Grid Square
let GrdSeg = 384;       // Segments (256 to 512)
//- Module
let waves = 0;          // Where the Ocean module is stored
let wav_ = {
	// General
	size: 1024,	// resolution of iFFT computation
	gsiz: GrdSiz,	// size of grid square (used to compute Normal Map)
	lambda: 0.9,
	renderer: renderer,
	anisotropy: renderer.getMaxAnisotropy(),
	// InitSpec Variables (for GrdSiz = 2400 meters)
	waveLength: 1500,
	boundaryLow: 0.0001,
	boundaryHigh: 9999,
	// Wave Spectrum 1
	depth: 100,
	scaleHeight: 1,
	windSpeed: 3,
	windDirection: 315,
	fetch: 100000,
	spreadBlend: 1,
	swell: 0.198,
	peakEnhancement: 3.3,
	shortWaveFade: 0.01,
	fadeLimit: 0.0,
	// Wave Spectrum 2
	d_depth: 100,
	d_scaleHeight: 1,
	d_windSpeed: 2,
	d_windDirection: 315,
	d_fetch: 300000,
	d_spreadBlend: 1,
	d_swell: 0.5,
	d_peakEnhancement: 3.3,
	d_shortWaveFade: 0.01,
	d_fadeLimit: 0.0,
};
Initialization
You can use the following command in your initialization section to initialize the Ocean4 module:
waves = new Ocean(wav_);
Animation
You can use the following command in your render section to animate the Ocean4t module:
waves.update();
You can create a Plane Mesh to display the Ocean waves. Here a simple example:
let WtrGeo = new THREE.PlaneGeometry(GrdSiz,GrdSiz,GrdSeg,GrdSeg);	
	WtrGeo.rotateX(-Math.PI*0.5); // Must rotate plane to make it flat
let WtrMat = new THREE.MeshStandardNodeMaterial({
	colorNode: color(0x001080), // Basic Color
	metalness: 0.5,
	roughness: 0.1,
	positionNode: positionLocal.add(texture(waves.displacement)), // Displacement Map
	normalNode: normalMap(texture(waves.normMapTexture),new THREE.Vector2(1,1)) // Normal Map
});
let WtrMsh = new THREE.Mesh(WtrGeo,WtrMat);
scene.add(WtrMsh);
Sample Programs
Here is a static program that uses the Ocean module:
Using the Ocean4 and Ocean3 Modules in Your Program
Import Module into Program

In a three.js program, you import all the three.js and other modules at the beginning of the program. You use the appropriate instruction to import the module:

import {Ocean} from "https://PhilCrowther.github.io/Aviation/xtra_perm/jsm/Ocean4.js"; // for WebGPU
import {Ocean} from "https://PhilCrowther.github.io/Aviation/xtra_perm/jsm/Ocean3.js"; // for WebGL2
Variables

The module uses the following variables to store data.

//- Grid Square Data
let GrdSiz = 3200;      // Smallest Grid Square (2400 meters)
let GrdRes = 512;       // Resolution of Computation
let AnmSpd = 1;         // The Animation Speed (can vary with GrdSiz)
//- Constants
let WndSpd = 20.0;      // Wind Speed
let WndHdg = 0.0;       // Wind Heading
let Choppy = 2.0;       // Wave Choppiness
//- Variables
let waves = 0;          // Where the Ocean module is stored
let wav_ = {
    Res: GrdRes,        // Resolution - segments per square (default = 512)
    Siz: GrdSiz,        // Size of Smallest Square = default = 3200m = 2 miles
    WSp: WndSpd,        // Wind Speed
    WHd: WndHdg,        // Wind Heading
    Chp: Choppy,        // default = 1
    NMS: new THREE.Vector2(1,1), // Normal Map Scale (flip Y for left-handed maps)
    Spd: AnmSpd         // The Animation Speed
};
Initialization
You can use the following command in your initialization section to initialize the module:
waves = new Ocean(renderer,wav_);
Animation
You can use the following command in your render section to animate the module:
waves.update();
You can create a Plane Mesh to display the Ocean waves. For WebGPU programs (Ocean4), you can use NodeMaterials. Here a simple example:
let WtrGeo = new THREE.PlaneGeometry(GrdSiz,GrdSiz,GrdSeg,GrdSeg);	
	WtrGeo.rotateX(-Math.PI*0.5); // Must rotate plane to make it flat
let WtrMat = new THREE.MeshStandardNodeMaterial({
	colorNode: color(0x001080), // Basic Color
	metalness: 0.5,
	roughness: 0.1,
	positionNode: positionLocal.add(texture(waves.dispMapTexture)), // Displacement Map
	normalNode: normalMap(texture(waves.normMapTexture),new THREE.Vector2(1,1)) // Normal Map
});
let WtrMsh = new THREE.Mesh(WtrGeo,WtrMat);
scene.add(WtrMsh);
For WebGPU programs (Ocean4) and WebGL2 programs (Ocean3), you can use regular Materials. Here a simple example:
let WtrGeo = new THREE.PlaneGeometry(GrdSiz,GrdSiz,GrdSeg,GrdSeg);	
    WtrGeo.rotateX(-Math.PI*0.5); // Must rotate plane to make it flat
let WtrMat = new THREE.MeshStandardMaterial({
        color: 0x001080,
        metalness: 0.5, // 1 for max reflection (1.0)
        roughness: 0.2, // 0 for max reflection (0.7)
        normalMap: waves.normalMapFramebuffer.texture, // Normal Map
//      normalScale: new THREE.Vector2(2.5,2.5), // use this to increase wave contrast
        // Special Instructions Required for Displacement Map
        onBeforeCompile: shader => {
            shader.uniforms.dmap = {value: waves.displacementMapFramebuffer.texture};
            shader.vertexShader = `
                uniform sampler2D dmap;
                ${shader.vertexShader}
            `
            .replace(
                `#include `,
                `#include 
                    transformed += vec3(1.0,1.0,1.0)*(texture(dmap, uv).rgb * 1.0 + 0.0);
                `
            );
        }
});
let WtrMsh = new THREE.Mesh(WtrGeo,WtrMat);
scene.add(WtrMsh);
Sample Programs
Here is a static program that uses the Ocean4 module. Here is a static program that uses the Ocean3 module. Both programs are available in the xtra_perm direction as sdem_ocean_gpu and sdem_ocean_gl2, respectively.