Skip to content

Instantly share code, notes, and snippets.

@UnforeseenOcean
Created January 24, 2020 17:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save UnforeseenOcean/3d9dbbb9c21d53fb872cb2720481fe98 to your computer and use it in GitHub Desktop.
Save UnforeseenOcean/3d9dbbb9c21d53fb872cb2720481fe98 to your computer and use it in GitHub Desktop.
Shitty Loading Bar
<h3 id="title">Click here to begin loading</h3>
<a href="#" onclick="toggleView()">Toggle View</a>
<canvas id="c" width="300" height="300"></canvas>
let points = [
// x,z dist
0.0,0, 0.0,
0.3,0, 0.3,
0.3,1, 1.3,
0.5,1, 1.5,
0.5,0, 2.5,
0.6,0, 2.6,
0.6,2, 4.6,
0.8,2, 4.8,
0.8,1, 5.8,
0.9,1, 5.9,
0.9,0, 6.9,
1.0,0, 7.0
];
const vertexShader = `#version 100
attribute vec2 position;
attribute float dist;
uniform float progress;
uniform float totalDist;
uniform mat4 projModelMat;
varying float v_dist;
varying float scaledDist;
void main() {
gl_Position = projModelMat * vec4(position.x,0.,position.y,1.);
v_dist = dist;
scaledDist = totalDist * progress;
}
`;
const fragmentShader = `#version 100
precision mediump float;
varying float scaledDist;
varying float v_dist;
void main() {
float alpha = 1. - step(scaledDist, v_dist);
gl_FragColor = vec4(mix(
vec3(.5,.5,.5),
vec3(0.,1.,0.),
alpha
),1.);
}
`;
let gl;
let vbo;
let shader;
let projMat = mat4.create();
let modelMat = mat4.create();
let projModelMat = mat4.create();
let totalLength = 0;
let start = 0;
let lastFrame = 0;
let maxTime = 10.0;
let elapsedTime = 0.0;
let isAnimating = false;
let cameraAngle = 0.25;
let isFixed = false;
function init() {
let canvas = document.querySelector("#c");
let mouseDown = false;
let lastMouseX = 0;
canvas.onmousedown = (e) => { mouseDown = true; lastMouseX = e.clientX; };
canvas.onmouseup = () => { mouseDown = false };
canvas.onmousemove = (e) => {
if(mouseDown) { cameraAngle = ((e.clientX - lastMouseX) / 50) % (Math.PI * 2) }
};
gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
// setup camera matrices
let aspect = canvas.width / canvas.height;
let scl = 3;
mat4.ortho(projMat, -scl * aspect, scl * aspect, -scl, scl, -10, 10);
mat4.identity(modelMat);
// setup state
gl.clearColor(0,0,0,0);
gl.enable(gl.DEPTH_TEST);
gl.cullFace(gl.BACK);
gl.lineWidth(Math.min(5,gl.getParameter(gl.ALIASED_LINE_WIDTH_RANGE)));
// load shader and get uniform/attribute locations
initShader();
shader.uniforms = {};
shader.attributes = {};
gl.useProgram(shader);
shader.uniforms["progress"] = gl.getUniformLocation(shader, "progress");
shader.uniforms["totalDist"] = gl.getUniformLocation(shader, "totalDist");
shader.uniforms["projModelMat"] = gl.getUniformLocation(shader, "projModelMat");
shader.attributes["position"] = gl.getAttribLocation(shader, "position");
shader.attributes["dist"] = gl.getAttribLocation(shader, "dist");
// calculate length
totalLength = points[points.length-1];
gl.uniform1f(shader.uniforms["totalDist"], totalLength);
// load to vbo
vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(points), gl.STATIC_DRAW);
gl.vertexAttribPointer(shader.attributes["position"], 2, gl.FLOAT, false, 3 * 4, 0);
gl.vertexAttribPointer(shader.attributes["dist"], 1, gl.FLOAT, false, 3 * 4, 2 * 4);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
// calculate start time and draws frame
start = Date.now();
lastFrame = (Date.now() - start) / 1000;
requestAnimationFrame(draw);
}
function draw() {
// calculate delta
let time = (Date.now() - start) / 1000;
let delta = time - lastFrame;
lastFrame = time;
// update model matrix
if(!isFixed) {
let cameraPos = [Math.cos(cameraAngle)*2.5,1,Math.sin(cameraAngle)*2.5];
mat4.lookAt(modelMat, cameraPos, [2,0,0], [0,1,0]);
} else {
mat4.identity(modelMat);
mat4.translate(modelMat, modelMat, [-4,0,4]);
}
mat4.scale(modelMat, modelMat, [4,1,1]);
// update progress
if(isAnimating) {
elapsedTime += delta;
if(elapsedTime >= maxTime) {
elapsedTime = maxTime;
isAnimating = false;
}
}
gl.uniform1f(shader.uniforms["progress"], elapsedTime / maxTime);
// calculate projModelMat
mat4.mul(projModelMat, projMat, modelMat);
gl.uniformMatrix4fv(shader.uniforms["projModelMat"], false, projModelMat);
// draw progress bar
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.enableVertexAttribArray(shader.attributes["position"]);
gl.enableVertexAttribArray(shader.attributes["dist"]);
gl.drawArrays(gl.LINE_STRIP, 0, points.length / 3);
gl.disableVertexAttribArray(shader.attributes["position"]);
gl.disableVertexAttribArray(shader.attributes["dist"]);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
// redraw frame
requestAnimationFrame(draw);
}
function initShader() {
shader = gl.createProgram();
vs = gl.createShader(gl.VERTEX_SHADER);
fs = gl.createShader(gl.FRAGMENT_SHADER);
// load vertex shader
gl.shaderSource(vs, vertexShader);
gl.compileShader(vs);
if(!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) {
console.error("vertex:", gl.getShaderInfoLog(vs));
}
// load fragment shader
gl.shaderSource(fs, fragmentShader);
gl.compileShader(fs);
if(!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) {
console.error("fragment:", gl.getShaderInfoLog(fs));
}
// link program
gl.attachShader(shader, vs);
gl.attachShader(shader, fs);
gl.linkProgram(shader);
if(!gl.getProgramParameter(shader, gl.LINK_STATUS)) {
console.error("linking:", gl.getProgramInfoLog(shader));
}
// delete shaders
gl.detachShader(shader, vs);
gl.detachShader(shader, fs);
gl.deleteShader(vs);
gl.deleteShader(fs);
}
document.getElementById("title").onclick = () => {
this.innerText = "Loading, please wait...";
isAnimating = true;
elapsedTime = 0.0;
};
function toggleView() {
isFixed = !isFixed;
}
init();
h3 {
color: white;
cursor: pointer;
}
canvas {
cursor: e-resize;
}
body {
background: black;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment