waves.vert 2.3 KB
#define FMA(a, b, c) ((a) * (b) + (c))  // fused multiply-add

precision highp float;

const float kTile = 1.;

const float kPi = 3.1415926535;
const float kEpsilon = 1. / 32.;

// DALI uniforms
uniform vec3 uSize;
uniform mat4 uModelView;
uniform mat4 uProjection;
uniform mat3 uNormalMatrix;

// our uniforms
uniform float uTime;
uniform vec2 uScrollScale;
uniform float uWaveRate;
uniform float uWaveAmplitude;
uniform float uParallaxAmount;

attribute vec2 aPosition;
attribute vec2 aTexCoord;

varying vec2 vUv;
varying vec3 vViewPos;
varying vec3 vNormal;
varying float vHeight;

float CubicHermite(float B, float C, float t)
{
  float dCB = (C - B) * .5;
  float A = B - dCB;
  float D = B + dCB;
  vec3 p = vec3(D + .5 * (((B - C) * 3.) - A), A - 2.5 * B + 2. * C - D,
    .5 * (C - A));
  return FMA(FMA(FMA(p.x, t, p.y), t, p.z), t, B);
}

float Hash(float n)
{
  return fract(sin(n) * 43751.5453123);
}

float HeightAtTile(vec2 pos)
{
  float rate = Hash(Hash(pos.x) * Hash(pos.y));

  return (sin(uTime * rate * uWaveRate) * .5 + .5) * uWaveAmplitude;
}

float CalculateHeight(vec2 position)
{
  vec2 tile = floor(position);
  position = fract(position);

  vec2 cp = vec2(
    CubicHermite(
      HeightAtTile(tile + vec2( kTile * -0.5, kTile * -0.5)),
      HeightAtTile(tile + vec2( kTile * +0.5, kTile * -0.5)),
      position.x),
    CubicHermite(
      HeightAtTile(tile + vec2( kTile * -0.5, kTile * +0.5)),
      HeightAtTile(tile + vec2( kTile * +0.5, kTile * +0.5)),
      position.x)
  );

  return CubicHermite(cp.x, cp.y, position.y);
}

vec3 CalculateNormal(vec2 position)
{
  vec3 normal = vec3(
    CalculateHeight(vec2(position.x - kEpsilon, position.y)) -
      CalculateHeight(vec2(position.x + kEpsilon, position.y)),
    .25,
    CalculateHeight(vec2(position.x, position.y - kEpsilon)) -
      CalculateHeight(vec2(position.x, position.y + kEpsilon))
  );
  return normal;
}

void main()
{
  vUv = aTexCoord;

  vec2 scrollPosition = aPosition * uScrollScale + vec2(0., uTime * -kPi);
  vNormal = uNormalMatrix * CalculateNormal(scrollPosition);

  float h = CalculateHeight(scrollPosition);
  vHeight = h * uParallaxAmount;
  vec3 position = vec3(aPosition.x, h, aPosition.y);

  vec4 viewPosition = uModelView * vec4(position * uSize, 1.);
  vViewPos = -viewPosition.xyz;

  gl_Position = uProjection * viewPosition;
}