html5 css3 particle wave two

html5 css3 particle wave

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Particle Wave</title>

<style>
html, body {
height: 100%;
  background:#000;
}
body {
margin: 0;
}
canvas {
display: block;
}
.waves {
position:absolute;
left:0;
top:0;
right:0;
bottom:0;
}
</style>
</head>
<body>
<div class="waves"></div>

<script>
class ShaderProgram {
  constructor( holder, options = {} ) {
    options = Object.assign({
      antialias: false,
      depthTest: false,
      mousemove: false,
      autosize: true,
      side: 'front',
      vertex:`
        precision highp float;

        attribute vec4 a_position;
        attribute vec4 a_color;

        uniform float u_time;
        uniform vec2 u_resolution;
        uniform vec2 u_mousemove;
        uniform mat4 u_projection;

        varying vec4 v_color;

        void main() {

          gl_Position = u_projection * a_position;
          gl_PointSize = (10.0 / gl_Position.w) * 100.0;

          v_color = a_color;

        }`,
      fragment:`
        precision highp float;

        uniform sampler2D u_texture;
        uniform int u_hasTexture;

        varying vec4 v_color;

        void main() {

          if ( u_hasTexture == 1 ) {

            gl_FragColor = v_color * texture2D(u_texture, gl_PointCoord);

          } else {

            gl_FragColor = v_color;

          }

        }`,
      uniforms: {},
      buffers: {},
      camera: {},
      texture: null,
      onUpdate: ( () => {} ),
      onResize: ( () => {} ),
    }, options )

    const uniforms = Object. assign({
      time: { type: 'float', value: 0 },
      hasTexture: { type: 'int', value: 0 },
      resolution: { type: 'vec2', value: [ 0, 0 ] },
      mousemove: { type: 'vec2', value: [ 0, 0 ] },
      projection: { type: 'mat4', value: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ] },
    }, options. uniforms )

    const buffers = Object. assign({
      position: { size: 3, data: [] },
      color: { size: 4, data: [] },
    }, options. buffers )

    const camera = Object. assign({
      fov: 60,
      near: 1,
      far: 10000,
      aspect: 1,
      z: 100,
      perspective: true,
    }, options. camera )

    const canvas = document. createElement( 'canvas' )
    const gl = canvas. getContext( 'webgl', { antialias: options. antialias } )
    if ( ! gl ) return false
    this.count = 0
    this.gl = gl
    this. canvas = canvas
    this. camera = camera
    this.holder = holder
    this.onUpdate = options.onUpdate
    this.onResize = options.onResize
    this.data = {}
    holder. appendChild( canvas )
    this.createProgram( options.vertex, options.fragment )
    this. createBuffers( buffers )
    this. createUniforms( uniforms )
    this. updateBuffers()
    this. updateUniforms()
    this. createTexture( options. texture )

    gl. enable( gl. BLEND )
    gl. enable( gl. CULL_FACE )
    gl.blendFunc( gl.SRC_ALPHA, gl.ONE )
    gl[ options. depthTest ? 'enable' : 'disable' ]( gl.DEPTH_TEST )

    if ( options. autosize )
      window.addEventListener( 'resize', e => this.resize( e ), false )
    if ( options. mousemove )
      window.addEventListener( 'mousemove', e => this.mousemove( e ), false )
    this. resize()
    this. update = this. update. bind( this )
    this.time = { start: performance.now(), old: performance.now() }
    this. update()
  }

  mousemove( e ) {
    let x = e.pageX / this.width * 2 - 1
    let y = e.pageY / this.height * 2 - 1
    this.uniforms.mousemove = [ x, y ]
  }

  resize( e ) {
    const holder = this.holder
    const canvas = this. canvas
    const gl = this.gl
    const width = this.width = holder.offsetWidth
    const height = this.height = holder.offsetHeight
    const aspect = this. aspect = width / height
    const dpi = this.dpi = devicePixelRatio
    canvas.width = width * dpi
    canvas.height = height * dpi
    canvas.style.width = width + 'px'
    canvas.style.height = height + 'px'
    gl. viewport( 0, 0, width * dpi, height * dpi )
    gl. clearColor( 0, 0, 0, 0 )
    this.uniforms.resolution = [ width, height ]
    this.uniforms.projection = this.setProjection( aspect )
    this.onResize(width, height, dpi)
  }

  setProjection( aspect ) {
    const camera = this. camera
    if (camera. perspective) {
      camera.aspect = aspect
      const fovRad = camera.fov * ( Math.PI / 180 )
      const f = Math.tan( Math.PI * 0.5 - 0.5 * fovRad )
      const rangeInv = 1.0 / ( camera. near - camera. far )

      const matrix = [
        f / camera. aspect, 0, 0, 0,
        0, f, 0, 0,
        0, 0, (camera. near + camera. far) * rangeInv, -1,
        0, 0, camera. near * camera. far * rangeInv * 2, 0
      ]

      matrix[ 14 ] + = camera.z
      matrix[ 15 ] + = camera.z

      return matrix

    } else {

      return [
         2 / this. width, 0, 0, 0,
         0, -2 / this.height, 0, 0,
         0, 0, 1, 0,
        -1, 1, 0, 1,
      ]

    }

  }

  createShader( type, source ) {

    const gl = this.gl
    const shader = gl. createShader( type )

    gl. shaderSource( shader, source )
    gl. compileShader( shader )

    if ( gl. getShaderParameter (shader, gl. COMPILE_STATUS ) ) {

      return shader

    } else {

      console. log( gl. getShaderInfoLog( shader ) )
      gl. deleteShader( shader )

    }

  }

  createProgram( vertex, fragment ) {

    const gl = this.gl

    const vertexShader = this. createShader( gl. VERTEX_SHADER, vertex )
    const fragmentShader = this. createShader( gl. FRAGMENT_SHADER, fragment )

    const program = gl. createProgram()

    gl. attachShader( program, vertexShader )
    gl. attachShader( program, fragmentShader )
    gl. linkProgram( program )

    if ( gl. getProgramParameter( program, gl. LINK_STATUS ) ) {

      gl. useProgram( program )
      this.program = program

    } else {

      console. log( gl. getProgramInfoLog( program ) )
      gl. deleteProgram( program )

    }

  }

  createUniforms( data ) {

    const gl = this.gl
    const uniforms = this.data.uniforms = data
    const values = this. uniforms = {}

    Object.keys( uniforms ).forEach( name => {

      const uniform = uniforms[name]

      uniform.location = gl.getUniformLocation( this.program, 'u_' + name )

      Object.defineProperty( values, name, {
        set: value => {

          uniforms[name].value = value
          this.setUniform( name, value )

        },
        get: () => uniforms[name].value
      } )

    } )

  }

  setUniform( name, value ) {

    const gl = this.gl
    const uniform = this.data.uniforms[name]

    uniform. value = value

    switch ( uniform. type ) {
      case 'int': {
        gl. uniform1i( uniform. location, value )
        break
      }
      case 'float': {
        gl. uniform1f( uniform. location, value )
        break
      }
      case 'vec2': {
        gl. uniform2f( uniform. location, ... value )
        break
      }
      case 'vec3': {
        gl. uniform3f( uniform. location, ... value )
        break
      }
      case 'vec4': {
        gl. uniform4f( uniform. location, ... value )
        break
      }
      case 'mat2': {
        gl. uniformMatrix2fv( uniform. location, false, value )
        break
      }
      case 'mat3': {
        gl. uniformMatrix3fv( uniform. location, false, value )
        break
      }
      case 'mat4': {
        gl. uniformMatrix4fv( uniform. location, false, value )
        break
      }
    }

    // ivec2 : uniform2i,
    // ivec3 : uniform3i,
    // ivec4 : uniform4i,
    // sampler2D : uniform1i,
    // samplerCube : uniform1i,
    // bool : uniform1i,
    // bvec2 : uniform2i,
    // bvec3 : uniform3i,
    // bvec4 : uniform4i,

  }

  updateUniforms() {

    const gl = this.gl
    const uniforms = this.data.uniforms

    Object.keys( uniforms ).forEach( name => {

      const uniform = uniforms[name]

      this.uniforms[name] = uniform.value

    } )

  }

  createBuffers( data ) {

    const gl = this.gl
    const buffers = this. data. buffers = data
    const values = this. buffers = {}

    Object.keys( buffers ).forEach( name => {

      const buffer = buffers[name]

      buffer.buffer = this.createBuffer( 'a_' + name, buffer.size )

      Object.defineProperty( values, name, {
        set: data => {

          buffers[name].data = data
          this. setBuffer( name, data )

          if ( name == 'position' )
            this.count = buffers.position.data.length / 3

        },
        get: () => buffers[name].data
      } )

    } )

  }

  createBuffer( name, size ) {

    const gl = this.gl
    const program = this. program

    const index = gl. getAttribLocation( program, name )
    const buffer = gl. createBuffer()

    gl. bindBuffer( gl. ARRAY_BUFFER, buffer )
    gl. enableVertexAttribArray( index )
    gl.vertexAttribPointer( index, size, gl.FLOAT, false, 0, 0 )

    return buffer

  }

  setBuffer( name, data ) {

    const gl = this.gl
    const buffers = this.data.buffers

    if ( name == null & amp; & amp; ! gl. bindBuffer( gl. ARRAY_BUFFER, null ) ) return

    gl.bindBuffer( gl.ARRAY_BUFFER, buffers[ name ].buffer )
    gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( data ), gl.STATIC_DRAW )

  }

  updateBuffers() {

    const gl = this.gl
    const buffers = this.buffers

    Object.keys( buffers ).forEach( name =>
      buffers[name] = buffer.data
    )

    this. setBuffer( null )

  }

  createTexture( src ) {

    const gl = this.gl
    const texture = gl. createTexture()

    gl.bindTexture( gl.TEXTURE_2D, texture )
    gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array( [ 0, 0, 0, 0 ] ) )

    this.texture = texture

    if ( src ) {

      this.uniforms.hasTexture = 1
      this. loadTexture( src )

    }

  }

  loadTexture( src ) {

    const gl = this.gl
    const texture = this.texture

    const textureImage = new Image()

    textureImage.onload = () => {

      gl.bindTexture( gl.TEXTURE_2D, texture )

      gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureImage )

      gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR )
      gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR )

      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)

      // gl.generateMipmap( gl.TEXTURE_2D )

    }

    textureImage.src = src

  }

  update() {

    const gl = this.gl

    const now = performance. now()
    const elapsed = ( now - this.time.start ) / 5000
    const delta = now - this.time.old
    this.time.old = now

    this.uniforms.time = elapsed

    if ( this. count > 0 ) {
      gl.clear( gl.COLORBUFFERBIT )
      gl. drawArrays( gl. POINTS, 0, this. count )
    }

    this. onUpdate( delta )

    requestAnimationFrame( this. update )

  }

}

const pointSize = 2.5

const waves = new ShaderProgram( document. querySelector( '.waves' ), {
  texture: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAgCAMAAABEpIrGAAAAb1BMVEUAAAD///8v0wLRAAAAJHRSTlMAC/goGvDhmwcExrVjWzrm29TRqqSKenRXVklANSIUE8mRkGpv + HOfAAABCElEQV Q4y4VT13LDMAwLrUHteO + R9f/fWMfO6dLaPeKVEECRxOULWsEGpS9nULDwia2Y + ALqUNbAWeg775zv + sA4/FFRMxt8U2FZFCVWjR/YrH4/H9sarclSKdPMWKzb8VsEeHB3m0shkhVCyNzeXe AQ9Xl4opEieX2QCGnwGbj6GMyjw9t1K0fK9YZunPXeAGsfJtYjwzxaBnozGGorYz0ypK2HzQSYx1y8DgSRo2ewOiyh2QWOEk1Y9OrQV0a8TiBM1a8eMHWYnRMy7CZ4t1CmyRkhSUvP3 gRXyHOCLBxNoC3IJv//ZrJ/kxxUHPUB + 6jJZZHrpg6GOjnqaOmzp4NDR48OLxn/H27SRQ08S0ZJAAAAAAElFTkSuQmCC',
  uniforms: {
    size: { type: 'float', value: pointSize },
    field: { type: 'vec3', value: [ 0, 0, 0 ] },
    speed: { type: 'float', value: 5 },
  },
  vertex:`
    #define M_PI 3.1415926535897932384626433832795

    precision highp float;

    attribute vec4 a_position;
    attribute vec4 a_color;

    uniform float u_time;
    uniform float u_size;
    uniform float u_speed;
    uniform vec3 u_field;
    uniform mat4 u_projection;

    varying vec4 v_color;

    void main() {

      vec3 pos = a_position. xyz;

      pos.y + = (
        cos(pos.x / u_field.x * M_PI * 8.0 + u_time * u_speed) +
        sin(pos.z / u_field.z * M_PI * 8.0 + u_time * u_speed)
      ) * u_field.y;

      gl_Position = u_projection * vec4( pos.xyz, a_position.w );
      gl_PointSize = ( u_size / gl_Position.w ) * 100.0;

      v_color = a_color;

    }`,
  fragment:`
    precision highp float;

    uniform sampler2D u_texture;

    varying vec4 v_color;

    void main() {

      gl_FragColor = v_color * texture2D(u_texture, gl_PointCoord);

    }`,
  onResize( w, h, dpi ) {

    const position = [], color = []

    const width = 400 * ( w / h )
    const depth = 400
    const height = 3
    const distance = 5

    for ( let x = 0; x < width; x + = distance ) {
      for ( let z = 0; z < depth; z + = distance ) {

        position.push(-width / 2 + x, -30, -depth / 2 + z)
        color.push( 0, 1 - ( x / width ) * 1, 0.5 + x / width * 0.5, z / depth )

      }
    }

    this.uniforms.field = [ width, height, depth ]

    this.buffers.position = position
    this.buffers.color = color

    this.uniforms.size = (h / 400) * pointSize * dpi

  },
} )</script>

</body>
</html>

Two: particle waves

<html><head>
    <meta charset="utf-8">
    <title>Particle Wave</title>
    
    <style>
    html, body {
        padding: 0;
        margin:0
    }
    canvas {
        display: block
    }
    </style>
    </head>
    <body>
    <canvas width="1277" height="930"></canvas>
    
    <script>
    'use strict';
    
    var FastRandom = function()
    {
        this. getNextFloat = function()
        {
            return Math. random();
        };
    };
    
    var ParticleWave = function()
    {
        var me = this;
    
        var config = {
            colors: {
                background: 0x000000,
                particle : 0x477cc2
            },
            alpha : {
                particle : 1
            },
            particleCount: 30000
        };
    
        var TAU = Math.PI * 2;
    
        var random = new FastRandom();
    
        var particle;
        var particleFillStyle;
        var particleColorRGB = new Float32Array(3);
    
        var smoothGradient;
        var waterGradient;
    
        var canvas;
        var engine;
    
        var width;
        var height;
    
        var particleWaveWalker = 0;
        var randomWalker = 0;
    
        var requestTick = function()
        {
            window.requestAnimationFrame(tick);
        };
    
        var initParticle = function()
        {
            particle = new Float32Array(config. particleCount * 2);
    
            eachParticle(function(x, z) {
                particle[x] = random. getNextFloat();
                particle[z] = random. getNextFloat();
            });
        };
    
        var initCanvas = function()
        {
            var cs = document. getElementsByTagName('canvas');
    
            canvas = cs[0];
            engine = canvas. getContext('2d');
    
            width = window. innerWidth;
            height = window. innerHeight;
    
            canvas.setAttribute('width', width);
            canvas.setAttribute('height', height);
        };
    
        var initParticleColor = function()
        {
            particleColorRGB[0] = config.colors.particle >> 16 & 0xff;
            particleColorRGB[1] = config.colors.particle >> 8 & 0xff;
            particleColorRGB[2] = config.colors.particle & 0xff;
    
            particleFillStyle = 'rgb(' + particleColorRGB[0] + ',' + particleColorRGB[1] + ',' + particleColorRGB[2] + ')';
        };
    
        var initSmoothGradient = function()
        {
            smoothGradient = engine. createLinearGradient(
                width / 2,
                0,
                width / 2,
                height
            );
    
            smoothGradient.addColorStop(0.25, 'rgba(0, 0, 0, 0)');
    
            smoothGradient.addColorStop(0.45, 'rgba(0, 0, 0, 0.9)');
            smoothGradient.addColorStop(0.5 , 'rgba(0, 0, 0, 1)');
            smoothGradient.addColorStop(0.55, 'rgba(0, 0, 0, 0.9)');
    
            smoothGradient.addColorStop(0.75, 'rgba(0, 0, 0, 0)');
        };
    
        var initWaterGradient = function()
        {
            waterGradient = engine.createLinearGradient(
                width / 2,
                height / 2,
                width / 2,
                height
            );
    
            waterGradient.addColorStop(0, 'rgba(0, 0, 30, 0)');
            waterGradient.addColorStop(1, 'rgba(30, 0, 60, 0.5)');
        };
    
        var init = function()
        {
            initCanvas();
            initParticle();
            initParticleColor();
            initSmoothGradient();
            initWaterGradient();
        };
    
        var eachParticle = function(cb)
        {
            for (var i = 0; i < particle. length; i + = 2) {
                cb(i, i + 1);
            }
        };
    
        var renderParticle = function()
        {
            randomWalker + = (Math. random() - 0.5) * 0.1;
    
            particleWaveWalker += 0.03;
    
            var radius = {
                min : 1,
                add : 5
            };
    
            var midY = height / 2;
            var midX = width / 2;
    
            var spreadX = 5;
            var spreadZ = 0.0;
    
            var modZ = 0.0;
    
            var addX = 0;
            var addY = 0;
    
            var p = {
                x : 0.0,
                y : 0.0,
                r : 0.0
            };
    
            engine.fillStyle = particleFillStyle;
            // engine.beginPath();
    
            var waveControl = 10;
    
            for (var i = 0, xIndex, zIndex; i < particle. length; i + = 2) {
    
                xIndex = i;
                zIndex = i + 1;
    
                particle[zIndex] += 0.003;
    
                if (particle[zIndex] > 1) {
                    particle[zIndex] = 0;
                    particle[xIndex] = random. getNextFloat();
                }
    
                if (particle[zIndex] < 0.3) {
                    continue;
                }
    
                modZ = Math.pow(particle[zIndex], 2);
                spreadZ = 1 + (spreadX - 1) * modZ;
    
                //bottom
    
                addX = (0.5 - particle[xIndex]) * width * spreadZ;
                addY = midY * modZ * (1 + 3 / waveControl);
    
                p.x = midX + addX;
                p.y = midY + addY;
                p.r = radius.min + modZ * radius.add;
    
                p.y + = Math.sin(particle[xIndex] * 50 + particleWaveWalker) * addY / waveControl;
                p.y + = Math.cos(particle[zIndex] * 10 + particleWaveWalker) * addY / waveControl;
    
                p.y -= Math.cos(particle[zIndex] + particle[xIndex] * 10 + particleWaveWalker) * addY / waveControl;
    
                p.y -= Math.cos(particle[xIndex] * 50 + particleWaveWalker) * addY / waveControl;
                p.y -= Math.sin(particle[zIndex] * 10 + particleWaveWalker) * addY / waveControl;
    
                if (p.x < 0 || p.x > width) {
                    continue;
                }
    
                engine.fillRect(p.x, p.y, p.r, p.r);
    
                // engine. moveTo(p.x, p.y);
                // engine.arc(p.x, p.y, p.r, 0, TAU);
    
                //top
                // p.y = height - p.y;
                //
                // engine. moveTo(p.x, p.y);
                // engine.arc(p.x, p.y, p.r, 0, TAU);
            }
    
            engine.fillStyle = particleFillStyle;
    
            // engine. closePath();
            // engine. fill();
        };
    
        var colorIntToHexString = function(color)
        {
            var s = color.toString(16);
    
            return '0'.repeat(6 - s.length) + s;
        };
    
        var clear = function()
        {
            engine.fillStyle = '#' + colorIntToHexString(config.colors.background);
            engine. fillRect(0, 0, width, height);
        };
    
        var drawSmooth = function()
        {
            engine. fillStyle = smoothGradient;
            engine. fillRect(0, 0, width, height);
        };
    
        var drawWater = function()
        {
            engine.fillStyle = waterGradient;
            engine. fillRect(0, height / 2, width, height / 2);
        };
    
        var tick = function()
        {
            clear();
    
            drawWater();
            renderParticle();
            drawSmooth();
    
            requestTick();
        };
    
        this. run = function()
        {
            init();
            tick();
        };
    };
    
    var pw = new ParticleWave();
    pw. run();</script>
    
    
    
    </body></html>