<!doctype html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width,initial-scale=1">

<title>JYPSYEYE — VORTEX</title>


<style>

html,body{

  margin:0;

  height:100%;

  background:#000;

  overflow:hidden;

  font-family:Arial,Helvetica,sans-serif;

}


#stars{

  position:fixed;

  inset:0;

  width:100%;

  height:100%;

  z-index:0;

  pointer-events:none;

}


#frame{

  position:absolute;

  left:50%;

  top:50%;

  transform:translate(-50%,-50%);

  background:#000;

  z-index:1;

}


#c{

  display:block;

}


#counter{

  position:fixed;

  top:14px;

  right:16px;

  z-index:2;

  color:#39ff14;

  font-size:13px;

  letter-spacing:.08em;

  background:rgba(0,0,0,.55);

  padding:8px 10px;

  border:1px solid rgba(255,255,255,.18);

  border-radius:6px;

  white-space:pre;

}

</style>

</head>


<body>


<canvas id="stars"></canvas>


<div id="frame">

  <canvas id="c"></canvas>

</div>


<div id="counter">VISITORS: ...</div>


<script>

fetch("https://api.countapi.xyz/hit/jypsyeye/vortex")

.then(function(res){ return res.json(); })

.then(function(data){

  document.getElementById("counter").textContent = "VISITORS: " + data.value;

})

.catch(function(){

  document.getElementById("counter").textContent = "VISITORS: --";

});

</script>


<script>

const starCanvas = document.getElementById("stars");

const sctx = starCanvas.getContext("2d");

let stars = [];


function resizeStars(){

  const dpr = window.devicePixelRatio || 1;


  starCanvas.width = Math.floor(innerWidth * dpr);

  starCanvas.height = Math.floor(innerHeight * dpr);


  starCanvas.style.width = "100%";

  starCanvas.style.height = "100%";


  sctx.setTransform(dpr,0,0,dpr,0,0);


  const count = Math.floor((innerWidth * innerHeight) / 9000);

  stars = [];


  for(let i=0;i<count;i++){

    stars.push({

      x: Math.random() * innerWidth,

      y: Math.random() * innerHeight,

      r: Math.random() * 1.4 + 0.2,

      a: Math.random() * 0.6 + 0.2,

      tw: Math.random() * 1.5 + 0.3,

      ph: Math.random() * Math.PI * 2

    });

  }

}


function drawStars(t){

  sctx.clearRect(0,0,innerWidth,innerHeight);


  for(let i=0;i<stars.length;i++){

    const s = stars[i];

    const alpha = s.a * (0.6 + 0.4 * Math.sin(t * 0.001 * s.tw + s.ph));


    sctx.fillStyle = "rgba(255,255,255," + alpha + ")";

    sctx.beginPath();

    sctx.arc(s.x, s.y, s.r, 0, Math.PI * 2);

    sctx.fill();

  }


  requestAnimationFrame(drawStars);

}


addEventListener("resize", resizeStars);

resizeStars();

requestAnimationFrame(drawStars);

</script>


<script>

const canvas = document.getElementById("c");

const frame = document.getElementById("frame");

const gl = canvas.getContext("webgl",{alpha:false,antialias:false});


if(!gl){

  document.body.innerHTML = "WebGL not supported";

  throw new Error("no webgl");

}


const ASPECT = 2.39;

const SCALE = 0.58;


function resize(){

  const dpr = window.devicePixelRatio || 1;


  let w = window.innerWidth * SCALE;

  let h = w / ASPECT;


  if(h > window.innerHeight * SCALE){

    h = window.innerHeight * SCALE;

    w = h * ASPECT;

  }


  frame.style.width = w + "px";

  frame.style.height = h + "px";


  canvas.width = Math.floor(w * dpr);

  canvas.height = Math.floor(h * dpr);


  canvas.style.width = w + "px";

  canvas.style.height = h + "px";


  gl.viewport(0,0,canvas.width,canvas.height);

}


addEventListener("resize", resize);


const vs = `

attribute vec2 p;

void main(){

  gl_Position = vec4(p,0.0,1.0);

}

`;


const fs = `

precision mediump float;

uniform vec2 r;

uniform float t;

uniform sampler2D tex;


void main(){

  vec2 p = (gl_FragCoord.xy - r * 0.5) / min(r.x,r.y);


  float ang = atan(p.y,p.x) / 6.28318 + 0.5;

  float dep = 1.0 / max(length(p),0.03);


  float u = ang + t * 0.00004;

  float v = dep * 0.10 - t * 0.000075;


  vec2 uv = vec2(fract(u),fract(v));

  gl_FragColor = texture2D(tex,uv);

}

`;


function compile(type,src){

  const s = gl.createShader(type);

  gl.shaderSource(s,src);

  gl.compileShader(s);


  if(!gl.getShaderParameter(s, gl.COMPILE_STATUS)){

    throw new Error(gl.getShaderInfoLog(s) || "shader compile error");

  }


  return s;

}


const prog = gl.createProgram();

gl.attachShader(prog, compile(gl.VERTEX_SHADER,vs));

gl.attachShader(prog, compile(gl.FRAGMENT_SHADER,fs));

gl.linkProgram(prog);


if(!gl.getProgramParameter(prog, gl.LINK_STATUS)){

  throw new Error(gl.getProgramInfoLog(prog) || "program link error");

}


gl.useProgram(prog);


const buf = gl.createBuffer();

gl.bindBuffer(gl.ARRAY_BUFFER,buf);

gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([

  -1,-1,

   1,-1,

  -1, 1,

  -1, 1,

   1,-1,

   1, 1

]),gl.STATIC_DRAW);


const loc = gl.getAttribLocation(prog,"p");

gl.enableVertexAttribArray(loc);

gl.vertexAttribPointer(loc,2,gl.FLOAT,false,0,0);


const tex = gl.createTexture();

gl.activeTexture(gl.TEXTURE0);

gl.bindTexture(gl.TEXTURE_2D,tex);


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.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);

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


gl.uniform1i(gl.getUniformLocation(prog,"tex"),0);


const rLoc = gl.getUniformLocation(prog,"r");

const tLoc = gl.getUniformLocation(prog,"t");


const img = new Image();

img.src = "images/BROTHERHOOD.jpg";


img.onload = function(){

  gl.bindTexture(gl.TEXTURE_2D,tex);

  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1);


  gl.texImage2D(

    gl.TEXTURE_2D,

    0,

    gl.RGB,

    gl.RGB,

    gl.UNSIGNED_BYTE,

    img

  );


  resize();

  requestAnimationFrame(draw);

};


img.onerror = function(){

  document.getElementById("counter").textContent = "VISITORS: IMAGE ERROR";

};


function draw(time){

  gl.uniform2f(rLoc, canvas.width, canvas.height);

  gl.uniform1f(tLoc, time);


  gl.drawArrays(gl.TRIANGLES,0,6);

  requestAnimationFrame(draw);

}


resize();

</script>


</body>

</html>