text: import * as mouse from "./mouse_utils.js"
  'use strict';
  
  // particle initialization
  const vInit = `
    precision mediump float;
    attribute vec2 position;
    varying vec2 v_position;
  
    void main() {
      v_position = 0.5 * position + 0.5;
      gl_Position = vec4(position, 0.0, 1.0);
    }`;
  const fInit = `
    precision mediump float;
    varying vec2 v_position;
  
    void main() {
      gl_FragColor = vec4(v_position, 0.0, 0.0);
    }`;
  
  // particle physics in a cycle
  const vPhysics = `
    precision mediump float;
  
    attribute vec2 position;
    varying vec2 v_texcoord;
  
    void main() {
      v_texcoord = 0.5 * position + 0.5;
      gl_Position = vec4(position, 0.0, 1.0);
    }`;
  
  const fPhysics = `
    precision mediump float;
  
    varying vec2 v_texcoord;
    uniform sampler2D u_texture;
    uniform vec2 gravity_center;
    uniform float off_gravity;
    uniform float restore_colors;
    uniform float dt;
  
    vec2 n2rand() {
      return vec2(fract(sin(dot(v_texcoord.xy, vec2(12.9898, 78.233))) * 43758.5453),
        fract(sin(dot(v_texcoord.xy * 1.61803, vec2(12.9898, 78.233))) * 43758.5453));
    }
  
    void main() {
      vec4 particle = texture2D(u_texture, v_texcoord);
      vec2 r, d, a, x, v;
  
      x = particle.xy;
      v = particle.zw;
      r = x - gravity_center;
      d = x - v_texcoord;
  
      // physics emulation
      a = (1.0 - off_gravity) * ( -normalize(r) * dt * clamp(3. / dot(r, r), 0., 2.) + 0.03 * (n2rand() - 0.5) );
      x += (1.0 - restore_colors) * (v - 0.5) * dt;
      x += restore_colors * -d;
      v += a;
  
      // mirror edge
      v -= 2.0 * (v - 0.5) * step(0.0, abs(x - 0.5) - 0.5);
      x = abs(abs(abs(x) - 1.0) - 1.0);
  
      gl_FragColor = vec4(x, v);
    }`;
  
  // drawing particles
  const vDraw = `
    precision mediump float;
  
    attribute vec2 v_texcoord;
    uniform sampler2D u_texture;
    varying vec3 color;
  
    vec3 hsv2rgb(vec3 c) {
      vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
      vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
      return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
    }
  
    void main () {
      vec4 particle = texture2D(u_texture, v_texcoord);
      color = hsv2rgb(vec3(0.5 * v_texcoord + 0.4, 0.9));
      gl_Position = vec4(particle.xy * 2.0 - 1.0, 0.0, 1.0);
      gl_PointSize = 1.0;
    }`;
  const fDraw = `
    precision mediump float;
    varying vec3 color;
  
    void main () {
      gl_FragColor = vec4(color, 1.);
    }`;
  
  const mousepos = [0.5, 0.5];
  // Création du contexte WebGL
  //const canvas = document.querySelector('#glcanvas');
  //console.log(canvas);
  //var gl = canvas.getContext("webgl") // || canvas.getContext("experimental-webgl");
  // Création du contexte WebGL
  const canvas = document.querySelector('#glcanvas1');
  console.log(canvas);
  var gl = canvas.getContext("webgl") // || canvas.getContext("experimental-webgl");
  
  const programInit = twgl.createProgramInfo(gl, [vInit, fInit]);
  const programPhysics = twgl.createProgramInfo(gl, [vPhysics, fPhysics]);
  const programDraw = twgl.createProgramInfo(gl, [vDraw, fDraw]);
  
  const n = 256;
  const m = 256;
  let fb1 = twgl.createFramebufferInfo(gl, undefined, n, m);
  let fb2 = twgl.createFramebufferInfo(gl, undefined, n, m);
  const positionObject = { position: { data: [1, 1, 1, -1, -1, -1, -1, 1], numComponents: 2 } };
  const positionBuffer = twgl.createBufferInfoFromArrays(gl, positionObject);
  
  const pointData = [];
  for (let i = 0; i < n; i++) {
    for (let j = 0; j < m; j++) {
      pointData.push(i / (n - 1));
      pointData.push(j / (m - 1));
    }
  }
  const pointsObject = { v_texcoord: { data: pointData, numComponents: 2 } };
  const pointsBuffer = twgl.createBufferInfoFromArrays(gl, pointsObject);
  
  // particle initialization
  gl.useProgram(programInit.program);
  twgl.setBuffersAndAttributes(gl, programInit, positionBuffer);
  twgl.bindFramebufferInfo(gl, fb1);
  twgl.drawBufferInfo(gl, positionBuffer, gl.TRIANGLE_FAN);
  
  let dt;
  let prevTime;
  let temp;
  let offGravity = 0;
  let restoreColors = 0;
  
  function draw(time) {
    twgl.resizeCanvasToDisplaySize(gl.canvas);
    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
    dt = (prevTime) ? time - prevTime : 0;
    prevTime = time;
  
    // particle physics
    gl.useProgram(programPhysics.program);
    twgl.setBuffersAndAttributes(gl, programPhysics, positionBuffer);
    twgl.setUniforms(programPhysics, {
      u_texture: fb1.attachments[0],
      gravity_center: mousepos,
      off_gravity: offGravity,
      restore_colors: restoreColors,
      dt: 2.5 * dt,
    });
    twgl.bindFramebufferInfo(gl, fb2);
    twgl.drawBufferInfo(gl, positionBuffer, gl.TRIANGLE_FAN);
  
    // drawing particles
    gl.useProgram(programDraw.program);
    twgl.setBuffersAndAttributes(gl, programDraw, pointsBuffer);
    twgl.setUniforms(programDraw, { u_texture: fb2.attachments[0] });
    twgl.bindFramebufferInfo(gl, null);
    twgl.drawBufferInfo(gl, pointsBuffer, gl.POINTS);
  
    // ping-pong buffers
    temp = fb1;
    fb1 = fb2;
    fb2 = temp;
  }
  
  (function animate(now) {
    draw(now / 1000);
    requestAnimationFrame(animate);
  })(0);
  
  function setMousePos(e) {
    const pos = mouse.getNoPaddingNoBorderCanvasRelativeMousePosition(e, gl.canvas);
    mousepos[0] = pos.x/2+0.5;
    mousepos[1] = pos.y/2+0.5;
  }
  
  canvas.addEventListener('mousemove', setMousePos);
  
  canvas.addEventListener('mouseleave', () => {
    mousepos[0] = 0.5;
    mousepos[1] = 0.5;
  });
  
  canvas.addEventListener('mousedown', e => {
    if (e.button === 0) {
      offGravity = 1;
    } else {
      restoreColors = 1;
    }
  });
  
  window.addEventListener('mouseup', () => {
    offGravity = 0;
    restoreColors = 0;
  });
  
  function handleTouch(e) {
    e.preventDefault();
    setMousePos(e.touches[0]);
  }
  
  canvas.addEventListener('contextmenu', e => e.preventDefault());
  canvas.addEventListener('touchstart', handleTouch, {passive: false});
  canvas.addEventListener('touchmove', handleTouch, {passive: false});
  