██████╗██╗ ██╗ █████╗ ██╗ ██╗██╗ █████╗ ███╗ ██╗███████╗████████╗ ██╔════╝██║ ██║██╔══██╗██║ ██║██║ ██╔══██╗ ████╗ ██║██╔════╝╚══██╔══╝ ██║ ███████║███████║███████║██║ ███████║ ██╔██╗ ██║█████╗ ██║ ██║ ██╔══██║██╔══██║██╔══██║██║ ██╔══██║ ██║╚██╗██║██╔══╝ ██║ ╚██████╗██║ ██║██║ ██║██║ ██║███████╗██║ ██║ ██║ ╚████║███████╗ ██║ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═══╝╚══════╝ ╚═╝
STATUS: SYSTEM MIGRATION UNDERWAY_
SPLISH SPLASH WITH THE PAINTING BRUSH

const canvas = document.createElement("canvas");
canvas.width = 400;
canvas.height = 400;
const gl = canvas.getContext("webgl");


const latB = 16, lonB = 16, r = 1.0;
const pos = [], idx = [];
for (let lat = 0; lat <= latB; lat++) {
  const theta = (lat * Math.PI) / latB;
  const sT = Math.sin(theta), cT = Math.cos(theta);
  for (let lon = 0; lon <= lonB; lon++) {
    const phi = (lon * 2 * Math.PI) / lonB;
    pos.push(r*Math.cos(phi)*sT, r*cT, r*Math.sin(phi)*sT);
  }
}
const vpr = lonB + 1;
for (let lat = 0; lat <= latB; lat++) {
  const rs = lat * vpr;
  for (let lon = 0; lon < lonB; lon++)
    idx.push(rs+lon, rs+lon+1);
}
for (let lon = 0; lon <= lonB; lon++)
  for (let lat = 0; lat < latB; lat++) {
    const f = lat*vpr+lon;
    idx.push(f, f+vpr);
  }

const vsrc = `
  attribute vec3 aPos;
  uniform mat4 uProj, uMV;
  void main() { gl_Position = uProj * uMV * vec4(aPos, 1); }`;
const fsrc = `
  precision mediump float;
  uniform vec4 uColor;
  void main() { gl_FragColor = uColor; }`;

function mkShader(src, type) {
  const s = gl.createShader(type);
  gl.shaderSource(s, src);
  gl.compileShader(s);
  return s;
}
const prog = gl.createProgram();
gl.attachShader(prog, mkShader(vsrc, gl.VERTEX_SHADER));
gl.attachShader(prog, mkShader(fsrc, gl.FRAGMENT_SHADER));
gl.linkProgram(prog);
gl.useProgram(prog);

const posBuf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, posBuf);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(pos), gl.STATIC_DRAW);
const idxBuf = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, idxBuf);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(idx), gl.STATIC_DRAW);

const aPos = gl.getAttribLocation(prog, "aPos");
gl.enableVertexAttribArray(aPos);
gl.vertexAttribPointer(aPos, 3, gl.FLOAT, false, 0, 0);

const uProj = gl.getUniformLocation(prog, "uProj");
const uMV = gl.getUniformLocation(prog, "uMV");
const uColor = gl.getUniformLocation(prog, "uColor");


const f = 1/Math.tan(45*Math.PI/360);
const proj = new Float32Array(16);
proj[0]=f; proj[5]=f;
proj[10]=(100.1)/(0.1-100); proj[11]=-1;
proj[14]=(2*100*0.1)/(0.1-100);

gl.clearColor(0.02, 0.02, 0.02, 1);
gl.enable(gl.DEPTH_TEST);

let angle = 0;
const total = idx.length;
let drawn = 0;

function frame() {
  angle += 0.01;

  const c = Math.cos(angle), s = Math.sin(angle);
  const mv = new Float32Array([
    c,0,s,0, 0,1,0,0, -s,0,c,0, 0,0,-3.5,1
  ]);

  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  gl.uniformMatrix4fv(uProj, false, proj);
  gl.uniformMatrix4fv(uMV, false, mv);
  gl.uniform4f(uColor, 0, 1, 0.25, 1);


  if (drawn < total) drawn += 4;
  const count = Math.min(drawn, total);
  gl.drawElements(gl.LINES, count, gl.UNSIGNED_SHORT, 0);

  canvas._raf = requestAnimationFrame(frame);
}
frame();

return canvas;