Vertex shaders access the displacement graphic.
Fragment shaders access either the space or color grid graphic.
Upload the space or color grid graphic to a uniform Sampler2D
declared in the fragment shader.
Upload the displacement map to a uniform Sampler2D
declared in the vertex shader.

A number of initialization details were left out, to focus on the main topic.
Most WebGL projects initialize as
described in the WebGL e-book series.
However information in this tutorial should apply to other WebGL projects, such as those that use
Unity or three.js, as well.

Graphics

Displacement Map

Vertex Shader

The vertex shader samples just the blue
channel, from the displacement map, based on the current
texel. A texel is a texture coordinate.
The vertex shader modifies vertex X and Y coordinates
based on the value of the blue channel
and a uniform named uf_time.
Uniform uf_time represents
the current frame of animation.
JavaScript increments and uploads
uniform uf_time
for each animation frame.
Both frame time and values
from the displacement
map move vertices on the model.
Vertices move over time creating a tunnel effect.

The following lines demonstrate
moving vertices based on both
displacement map values
and animation frame time.
The value assigned to
vector v4_position equals the modified mesh's
X and Y coordinates, divided by the
product of time and the displacement map's blue channel.

v4_position.xy /= f_blue * uf_time;

Assign v4_position
to built in vector gl_Position.
Vector gl_Position prepares to
display the vertex at it's new location.

gl_Position = v4_position;

The following listing includes
the entire vertex shader.
Uniform u_sampler1
accesses the
displacement map.

Displacement Shader JavaScript

The following JavaScript initializes
a flat plane with two hundred fifty six
squares. The more squares the more
vertices to move during rendering.
The model named Plane256()
declares a flat plane with 256 sections.
You may download or view JavaScript which declares
the plane with 256 squares. See
Plane256.js.

The variable shapes includes
vertices, texels, and indices to define the plane.
The property array aOffset includes
one offset for drawing the plane.
The property array aCount includes
the number of elements needed to draw the plane.
The classGLEntity
initializes a texture. ClassGLEntity
maintains the count and offset for
drawing operations later.

The first parameter to GLEntity is a string
representing the path to an image file.
The second parameter is the texture index for the image,
once it's uploaded to the GPU.
The following listing demonstrates initializing two GLEntity.
The first GLEntity uploads the space, or colorful
grid graphics,
to the fragment shader.
The second GLEntity uploads the
displacement graphic
to the vertex shader.

Initialize the Controller

The following listing demonstrates initializing a controller
which uploads the plane's vertices and indices.
The shapes property named aVertices includes
all vertices and interleaved texels which map both graphics
to the model of a flat square plane.
The shapes property named aIndices
includes integers for use as an element array buffer in WebGL.

The controller initializes the shaders and buffers.
Seven Thunder Software doesn't rely on Three.js, Babylon.js or Unity
for WebGL development. Early testing demonstrated prepared libraries don't
always run on the wide variety of WebGL enabled devices.
Most projects at SevenThunderSoftware.com were tested on
iPhone, Android, Windows phone, and Windows PCs with WebGL enabled browsers.

Draw the Plane

The following listing demonstrates how simple it is to draw
the plane.
The variable e represents the GLEntity
described earlier.
Property nCount indicates how many
elements to draw.
Property nOffset indicates where to begin
drawing, within the vertex buffer object (VBO).

The following listing includes all
initialization applied to the plane
for viewing with WebGL.
The code uses open source glMatrixclassmat4
to move and scale the plane into view.
Notice method init()
saves the location of
uf_time from the vertex shader.

Render Everything

The render() method displays
one animation frame.
The following listing demonstrates
uploading a floating point value useful
for the current animation frame, to the vertex shader.
JavaScript updates variable nRad
for each animation frame.
WebGL method uniform1f()
uploads the floating point value, nRad,
to the vertex shader's, uf_time, uniform
as follows.

gl.uniform1f
(
glDemo.uTime,
controller.nRad
);

The entire render() method follows.
Method render() draws one frame
at a time.
Method render() uses glMatrix method mat4.rotate()
to rotate the plane around the Z axis for each animation frame.
Method render() uploads the modified transformation matrix
and new floating point time value, to the vertex shader.