summaryrefslogtreecommitdiff
path: root/assets/charsheet/charsheet.js
diff options
context:
space:
mode:
authorLLLL Colonq <llll@colonq>2026-02-17 05:21:03 -0500
committerLLLL Colonq <llll@colonq>2026-02-17 05:21:03 -0500
commitc45a68362c2f64781458f74309a235af8393255a (patch)
treef946a84f20c69e59a118121ff2eb7827d3cc6645 /assets/charsheet/charsheet.js
parente16ce1e5dbc6f0b1534abbbc774f4709c9804997 (diff)
Update
Diffstat (limited to 'assets/charsheet/charsheet.js')
-rw-r--r--assets/charsheet/charsheet.js206
1 files changed, 206 insertions, 0 deletions
diff --git a/assets/charsheet/charsheet.js b/assets/charsheet/charsheet.js
new file mode 100644
index 0000000..8c16137
--- /dev/null
+++ b/assets/charsheet/charsheet.js
@@ -0,0 +1,206 @@
+var GL = null;
+var VERTS = null;
+var IDXS = null;
+var ATTRIB_VERTEX = null;
+var ATTRIB_TEXCOORD = null;
+var UNIFORM_PROJECTION = null;
+var UNIFORM_VIEW = null;
+var UNIFORM_POSITION = null;
+var CUBE_ROTATION = 0.0;
+
+function showContents() {
+ let elem = document.getElementById("contents");
+ if (elem) {
+ elem.classList.remove("invisible");
+ elem.classList.add("contents-anim-unfold");
+ let timeout = 500;
+ for (let c of elem.children) {
+ setTimeout(
+ () => c.classList.add("opaque"),
+ timeout
+ );
+ timeout += 200;
+ }
+ }
+}
+
+function scaleName() {
+ let elem = document.getElementById("name");
+ if (elem && elem.firstElementChild) {
+ elem.firstElementChild.style = `transform: scale(1, 1)`;
+ let { width: pw, height: ph } = elem.getBoundingClientRect();
+ let { width: cw, height: ch } = elem.firstElementChild.getBoundingClientRect();
+ elem.firstElementChild.style = `transform: scale(${pw / cw}, ${ph / ch})`;
+ }
+}
+function setName(nm) {
+ let elem = document.getElementById("name");
+ if (elem && elem.firstElementChild) {
+ elem.firstElementChild.innerText = nm
+ scaleName();
+ new ResizeObserver(scaleName).observe(elem);
+ }
+}
+
+function uploadCube(gl) {
+ const verts = GL.createBuffer();
+ GL.bindBuffer(GL.ARRAY_BUFFER, verts);
+ const vertdata = [
+ // front
+ -0.5, -0.5, -0.5, 0, 0,
+ +0.5, -0.5, -0.5, 1.0, 0,
+ +0.5, +0.5, -0.5, 1.0, 1.0,
+ -0.5, +0.5, -0.5, 0, 1.0,
+ // right
+ +0.5, -0.5, -0.5, 0, 0,
+ +0.5, -0.5, +0.5, 1.0, 0,
+ +0.5, +0.5, +0.5, 1.0, 1.0,
+ +0.5, +0.5, -0.5, 0, 1.0,
+ // left
+ -0.5, -0.5, +0.5, 0, 0,
+ -0.5, -0.5, -0.5, 1.0, 0,
+ -0.5, +0.5, -0.5, 1.0, 1.0,
+ -0.5, +0.5, +0.5, 0, 1.0,
+ // top
+ -0.5, -0.5, +0.5, 0, 0,
+ +0.5, -0.5, +0.5, 1.0, 0,
+ +0.5, -0.5, -0.5, 1.0, 1.0,
+ -0.5, -0.5, -0.5, 0, 1.0,
+ // bottom
+ -0.5, +0.5, -0.5, 0, 0,
+ +0.5, +0.5, -0.5, 1.0, 0,
+ +0.5, +0.5, +0.5, 1.0, 1.0,
+ -0.5, +0.5, +0.5, 0, 1.0,
+ // back
+ +0.5, -0.5, +0.5, 0, 0,
+ -0.5, -0.5, +0.5, 1.0, 0,
+ -0.5, +0.5, +0.5, 1.0, 1.0,
+ +0.5, +0.5, +0.5, 0, 1.0
+ ];
+ GL.bufferData(GL.ARRAY_BUFFER, new Float32Array(vertdata), GL.STATIC_DRAW);
+ const quadidx = (p0, p1, p2, p3) => [p0, p1, p2, p2, p3, p0];
+ const idxs = GL.createBuffer();
+ GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, idxs);
+ const idxdata = [
+ quadidx(0, 1, 2, 3), // front
+ quadidx(4, 5, 6, 7), // right
+ quadidx(8, 9, 10, 11), // left
+ quadidx(12, 13, 14, 15), // top
+ quadidx(16, 17, 18, 19), // bottom
+ quadidx(20, 21, 22, 23) // back
+ ].flat();
+ GL.bufferData(GL.ELEMENT_ARRAY_BUFFER, new Uint16Array(idxdata), GL.STATIC_DRAW);
+ return { verts: verts, idxs: idxs };
+}
+function uploadShader(type, source) {
+ const shader = GL.createShader(type);
+ GL.shaderSource(shader, source);
+ GL.compileShader(shader);
+ if (!GL.getShaderParameter(shader, GL.COMPILE_STATUS)) {
+ alert(`shader compilation error: ${GL.getShaderInfoLog(shader)}`);
+ GL.deleteShader(shader);
+ return null;
+ }
+ return shader;
+}
+function uploadImage(url) {
+ const tex = GL.createTexture();
+ GL.bindTexture(GL.TEXTURE_2D, tex);
+ GL.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, 1, 1, 0, GL.RGBA, GL.UNSIGNED_BYTE, new Uint8Array([0, 0, 0, 1.0]));
+ const img = new Image();
+ img.onload = () => {
+ GL.bindTexture(GL.TEXTURE_2D, tex);
+ GL.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, GL.RGBA, GL.UNSIGNED_BYTE, img);
+ GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.NEAREST);
+ GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.NEAREST);
+ 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);
+ };
+ img.src = url;
+ return tex;
+}
+
+function initGL() {
+ const canvas = document.getElementById("canvas");
+ GL = canvas.getContext("webgl");
+ console.log(GL);
+ if (!GL) return;
+ console.log("initialized opengl");
+ GL.clearColor(1.0, 0.0, 0.0, 1.0);
+ GL.clearDepth(1.0);
+ GL.enable(GL.DEPTH_TEST);
+ GL.clear(GL.COLOR_BUFFER_BIT | GL.DEPTH_BUFFER_BIT);
+ const vertsrc = `
+ attribute vec3 vertex;
+ attribute vec2 texcoord;
+ uniform mat4 view;
+ uniform mat4 position;
+ uniform mat4 projection;
+ varying highp vec2 vertex_texcoord;
+ void main(void) {
+ gl_Position = projection * view * position * vec4(vertex, 1.0);
+ vertex_texcoord = texcoord;
+ }
+ `;
+ const fragsrc = `
+ varying highp vec2 vertex_texcoord;
+ uniform sampler2D texture_data;
+ void main(void) {
+ gl_FragColor = texture2D(texture_data, vertex_texcoord);
+ gl_FragColor.a = 1.0;
+ }
+ `;
+ const vshader = uploadShader(GL.VERTEX_SHADER, vertsrc);
+ const fshader = uploadShader(GL.FRAGMENT_SHADER, fragsrc);
+ const prog = GL.createProgram();
+ GL.attachShader(prog, vshader);
+ GL.attachShader(prog, fshader);
+ GL.linkProgram(prog);
+ if (!GL.getProgramParameter(prog, GL.LINK_STATUS)) {
+ alert(`shader linking error: ${gl.getProgramInfoLog(prog)}`);
+ return null;
+ }
+ GL.useProgram(prog);
+ ATTRIB_VERTEX = GL.getAttribLocation(prog, "vertex");
+ ATTRIB_TEXCOORD = GL.getAttribLocation(prog, "texcoord");
+ UNIFORM_PROJECTION = GL.getUniformLocation(prog, "projection");
+ UNIFORM_VIEW = GL.getUniformLocation(prog, "view");
+ UNIFORM_POSITION = GL.getUniformLocation(prog, "position");
+ const cube = uploadCube();
+ uploadImage("./assets/l.png");
+ VERTS = cube.verts;
+ IDXS = cube.idxs;
+ requestAnimationFrame(render);
+}
+
+function render() {
+ CUBE_ROTATION += 0.01;
+ CUBE_ROTATION %= 2.0 * Math.PI;
+ const projection = mat4.create();
+ mat4.perspective(projection, Math.PI / 4.0, GL.canvas.clientWidth / GL.canvas.clientHeight, 0.1, 100.0);
+ const view = mat4.create();
+ mat4.lookAt(view, [0.0, 0.0, -5.0], [0.0, 0.0, 0.0], [0.0, 1.0, 0.0]);
+ const position = mat4.create();
+ mat4.rotateX(position, position, Math.PI / 4.0);
+ mat4.rotateY(position, position, CUBE_ROTATION);
+ mat4.rotateZ(position, position, CUBE_ROTATION);
+ GL.bindBuffer(GL.ARRAY_BUFFER, VERTS);
+ GL.vertexAttribPointer(ATTRIB_VERTEX, 3, GL.FLOAT, false, 20, 0);
+ GL.enableVertexAttribArray(ATTRIB_VERTEX);
+ GL.vertexAttribPointer(ATTRIB_TEXCOORD, 2, GL.FLOAT, false, 20, 12);
+ GL.enableVertexAttribArray(ATTRIB_TEXCOORD);
+ GL.uniformMatrix4fv(UNIFORM_PROJECTION, false, projection);
+ GL.uniformMatrix4fv(UNIFORM_VIEW, false, view);
+ GL.uniformMatrix4fv(UNIFORM_POSITION, false, position);
+ GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, IDXS);
+ GL.drawElements(GL.TRIANGLES, 36, GL.UNSIGNED_SHORT, 0);
+ requestAnimationFrame(render);
+}
+
+initGL();
+setName("LCOLONQ");
+
+setTimeout(
+ () => showContents(),
+ 1000
+);