aboutsummaryrefslogtreecommitdiff
path: root/web/pw-frontend/src/lib/visualizer/webgl
diff options
context:
space:
mode:
authorIlion Beyst <ilion.beyst@gmail.com>2021-12-29 21:24:57 +0100
committerIlion Beyst <ilion.beyst@gmail.com>2021-12-29 21:25:29 +0100
commit0c6d978442b244ca3f29c1ffdd44b5007ae7ad93 (patch)
treebaae5fa459a49ecd362e548e0649e2f58c669a70 /web/pw-frontend/src/lib/visualizer/webgl
parent3eeaab6cec70e7a06a99a1ac2662974f71064bee (diff)
downloadplanetwars.dev-0c6d978442b244ca3f29c1ffdd44b5007ae7ad93.tar.xz
planetwars.dev-0c6d978442b244ca3f29c1ffdd44b5007ae7ad93.zip
separate out visualizer library
Diffstat (limited to 'web/pw-frontend/src/lib/visualizer/webgl')
-rw-r--r--web/pw-frontend/src/lib/visualizer/webgl/buffer.ts55
-rw-r--r--web/pw-frontend/src/lib/visualizer/webgl/index.ts122
-rw-r--r--web/pw-frontend/src/lib/visualizer/webgl/renderer.ts157
-rw-r--r--web/pw-frontend/src/lib/visualizer/webgl/shader.ts327
-rw-r--r--web/pw-frontend/src/lib/visualizer/webgl/text.ts192
-rw-r--r--web/pw-frontend/src/lib/visualizer/webgl/texture.ts106
-rw-r--r--web/pw-frontend/src/lib/visualizer/webgl/util.ts229
-rw-r--r--web/pw-frontend/src/lib/visualizer/webgl/vertexBufferLayout.ts115
8 files changed, 0 insertions, 1303 deletions
diff --git a/web/pw-frontend/src/lib/visualizer/webgl/buffer.ts b/web/pw-frontend/src/lib/visualizer/webgl/buffer.ts
deleted file mode 100644
index 2739fbe..0000000
--- a/web/pw-frontend/src/lib/visualizer/webgl/buffer.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-
-export class Buffer {
- buffer: WebGLBuffer;
- data: any;
- count: number;
- type: number;
-
- constructor(gl: WebGLRenderingContext, data: number[], type: number) {
- this.buffer = gl.createBuffer();
- this.type = type;
-
- if (data)
- this.updateData(gl, data);
- }
-
- _toArray(data: number[]): any {
- return new Float32Array(data);
- }
-
- updateData(gl: WebGLRenderingContext, data: number[]) {
- this.data = data;
- this.count = data.length;
- gl.bindBuffer(this.type, this.buffer);
- gl.bufferData(this.type, this._toArray(data), gl.STATIC_DRAW);
- }
-
- bind(gl: WebGLRenderingContext) {
- gl.bindBuffer(this.type, this.buffer);
- }
-
- getCount(): number {
- return this.count;
- }
-}
-
-export class VertexBuffer extends Buffer {
- constructor(gl: WebGLRenderingContext, data: any) {
- super(gl, data, gl.ARRAY_BUFFER);
- }
-
- _toArray(data: number[]): any {
- return new Float32Array(data);
- }
-}
-
-
-export class IndexBuffer extends Buffer {
- constructor(gl: WebGLRenderingContext, data: any) {
- super(gl, data, gl.ELEMENT_ARRAY_BUFFER);
- }
-
- _toArray(data: number[]): any {
- return new Uint16Array(data);
- }
-}
diff --git a/web/pw-frontend/src/lib/visualizer/webgl/index.ts b/web/pw-frontend/src/lib/visualizer/webgl/index.ts
deleted file mode 100644
index fdb7886..0000000
--- a/web/pw-frontend/src/lib/visualizer/webgl/index.ts
+++ /dev/null
@@ -1,122 +0,0 @@
-import { Uniform4f, Uniform1f, Uniform2f, ShaderFactory, UniformMatrix3fv, Uniform3f } from './shader';
-import { resizeCanvasToDisplaySize, FPSCounter, onload2promise, Resizer, url_to_mesh } from "./util";
-import { VertexBuffer, IndexBuffer } from './buffer';
-import { VertexArray, VertexBufferLayout } from './vertexBufferLayout';
-import { Renderer } from './renderer';
-import { Texture } from './texture';
-
-const URL = window.location.origin+window.location.pathname;
-const LOCATION = URL.substring(0, URL.lastIndexOf("/") + 1);
-
-async function create_texture_from_svg(gl: WebGLRenderingContext, name: string, path: string, width: number, height: number): Promise<Texture> {
-
- const [mesh, factory] = await Promise.all([
- url_to_mesh(path),
- ShaderFactory.create_factory(LOCATION + "static/shaders/frag/static_color.glsl", LOCATION + "static/shaders/vert/svg.glsl")
- ]);
-
- const program = factory.create_shader(gl);
- const renderer = new Renderer();
-
- var positionBuffer = new VertexBuffer(gl, mesh.positions);
- var layout = new VertexBufferLayout();
- layout.push(gl.FLOAT, 3, 4, "a_position");
-
- const vao = new VertexArray();
- vao.addBuffer(positionBuffer, layout);
-
- program.bind(gl);
- vao.bind(gl, program);
-
- var indexBuffer = new IndexBuffer(gl, mesh.cells);
- indexBuffer.bind(gl);
-
- renderer.addToDraw(indexBuffer, vao, program, {});
-
- return Texture.fromRenderer(gl, name, width, height, renderer);
-}
-
-
-async function main() {
-
- // Get A WebGL context
- var canvas = <HTMLCanvasElement>document.getElementById("c");
- const resolution = [canvas.width, canvas.height];
-
- const resizer = new Resizer(canvas, [-10, -10, 20, 20], true);
-
- var gl = canvas.getContext("webgl");
- if (!gl) {
- return;
- }
-
- const mesh = await url_to_mesh("static/res/images/earth.svg");
- console.log(Math.max(...mesh.positions), Math.min(...mesh.positions));
- const renderer = new Renderer();
-
- const factory = await ShaderFactory.create_factory(LOCATION + "static/shaders/frag/static_color.glsl", LOCATION + "static/shaders/vert/simple.glsl");
- const program = factory.create_shader(gl);
-
- var positionBuffer = new VertexBuffer(gl, mesh.positions);
- var layout = new VertexBufferLayout();
- layout.push(gl.FLOAT, 3, 4, "a_position");
- // layout.push(gl.FLOAT, 2, 4, "a_tex");
-
- const vao = new VertexArray();
- vao.addBuffer(positionBuffer, layout);
-
- resizeCanvasToDisplaySize(<HTMLCanvasElement>gl.canvas);
-
- // Tell WebGL how to convert from clip space to pixels
- gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
-
- // Clear the canvas
- gl.clearColor(0, 0, 0, 0);
- gl.clear(gl.COLOR_BUFFER_BIT);
-
- gl.enable(gl.BLEND);
- gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
-
- program.bind(gl);
- vao.bind(gl, program);
-
- var indexBuffer = new IndexBuffer(gl, mesh.cells);
- indexBuffer.bind(gl);
-
- renderer.addToDraw(indexBuffer, vao, program, {});
-
- const counter = new FPSCounter();
-
- const step = function (time: number) {
-
- // console.log(resizer.get_viewbox());
-
- program.uniform(gl, "u_time", new Uniform1f(time * 0.001));
- program.uniform(gl, "u_mouse", new Uniform2f(resizer.get_mouse_pos()));
- program.uniform(gl, "u_viewbox", new Uniform4f(resizer.get_viewbox()));
- program.uniform(gl, "u_resolution", new Uniform2f(resolution));
- program.uniform(gl, "u_trans", new UniformMatrix3fv([1, 0, 0, 0, 1, 0, 0, 0, 1]));
- program.uniform(gl, "u_color", new Uniform3f(1.0, 0.5, 0.0));
-
- renderer.render(gl);
-
- counter.frame(time);
- requestAnimationFrame(step);
- }
-
- requestAnimationFrame(step);
-}
-
-
-main();
-
-document.getElementById("loader").classList.remove("loading");
-
-// const loader = document.getElementById("loader");
-// setInterval(() => {
-// if (loader.classList.contains("loading")) {
-// loader.classList.remove("loading")
-// } else {
-// loader.classList.add("loading");
-// }
-// }, 2000);
diff --git a/web/pw-frontend/src/lib/visualizer/webgl/renderer.ts b/web/pw-frontend/src/lib/visualizer/webgl/renderer.ts
deleted file mode 100644
index c3b219f..0000000
--- a/web/pw-frontend/src/lib/visualizer/webgl/renderer.ts
+++ /dev/null
@@ -1,157 +0,0 @@
-import type { IndexBuffer } from './buffer';
-import type { VertexArray } from './vertexBufferLayout';
-import type { Texture } from './texture';
-import type { Dictionary } from './util';
-import type { Shader, Uniform } from './shader';
-import { Uniform1i } from './shader';
-
-function sortedIndex(array, value) {
- var low = 0,
- high = array.length;
-
- while (low < high) {
- var mid = (low + high) >>> 1;
- if (array[mid] < value) low = mid + 1;
- else high = mid;
- }
- return low;
-}
-
-export interface Renderable {
- getUniforms() : Dictionary<Uniform>;
- render(gl: WebGLRenderingContext): void;
- updateVAOBuffer(gl: WebGLRenderingContext, index: number, data: number[]);
- updateIndexBuffer(gl: WebGLRenderingContext, data: number[]);
-}
-
-export class DefaultRenderable implements Renderable {
- ibo: IndexBuffer;
- va: VertexArray;
- shader: Shader;
- textures: Texture[];
- uniforms: Dictionary<Uniform>;
-
- constructor(
- ibo: IndexBuffer,
- va: VertexArray,
- shader: Shader,
- textures: Texture[],
- uniforms: Dictionary<Uniform>,
- ) {
- this.ibo = ibo;
- this.va = va;
- this.shader = shader;
- this.textures = textures;
- this.uniforms = uniforms;
- }
-
- getUniforms(): Dictionary<Uniform> {
- return this.uniforms;
- }
-
- updateVAOBuffer(gl: WebGLRenderingContext, index: number, data: number[]) {
- this.va.updateBuffer(gl, index, data);
- }
-
- updateIndexBuffer(gl: WebGLRenderingContext, data: number[]) {
- this.ibo.updateData(gl, data);
- }
-
- render(gl: WebGLRenderingContext): void {
-
- const indexBuffer = this.ibo;
- const vertexArray = this.va;
- const uniforms = this.uniforms;
-
- const shader = this.shader;
- const textures = this.textures;
- let texLocation = 0;
-
- for (let texture of textures) {
-
- shader.uniform(gl, texture.name, new Uniform1i(texLocation));
- texture.bind(gl, texLocation);
-
- texLocation ++;
- // if (texLocation > maxTextures) {
- // console.error("Using too many textures, this is not supported yet\nUndefined behaviour!");
- // }
- }
-
- if (vertexArray && shader && uniforms) {
- for(let key in uniforms) {
- shader.uniform(gl, key, uniforms[key]);
- }
-
- vertexArray.bind(gl, shader);
-
- if (indexBuffer) {
- indexBuffer.bind(gl);
- gl.drawElements(gl.TRIANGLES, indexBuffer.getCount(), gl.UNSIGNED_SHORT, 0);
- } else {
- console.error("IndexBuffer is required to render, for now");
- }
- }
-
- }
-}
-
-export class Renderer {
- renderables: { [id: number] : [Renderable, boolean][]; };
- renderable_layers: number[];
-
- constructor() {
- this.renderables = {};
- this.renderable_layers = [];
- }
-
- updateUniform(i: number, f: (uniforms: Dictionary<Uniform>) => void, layer=0, ) {
- f(this.renderables[layer][i][0].getUniforms());
- }
-
- disableRenderable(i: number, layer=0) {
- this.renderables[layer][i][1] = false;
- }
-
- enableRenderable(i: number, layer=0) {
- this.renderables[layer][i][1] = true;
- }
-
- addRenderable(item: Renderable, layer=0): number {
- if(!this.renderables[layer]) {
- const idx = sortedIndex(this.renderable_layers, layer);
- this.renderable_layers.splice(idx, 0, layer);
- this.renderables[layer] = [];
- }
-
- this.renderables[layer].push([item, true]);
- return this.renderables[layer].length - 1;
- }
-
- addToDraw(indexBuffer: IndexBuffer, vertexArray: VertexArray, shader: Shader, uniforms?: Dictionary<Uniform>, texture?: Texture[], layer=0): number {
- return this.addRenderable(
- new DefaultRenderable(
- indexBuffer,
- vertexArray,
- shader,
- texture || [],
- uniforms || {},
- ), layer
- );
- }
-
- render(gl: WebGLRenderingContext, frameBuffer?: WebGLFramebuffer, width?: number, height?: number) {
- gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
- gl.viewport(0, 0, width || gl.canvas.width, height || gl.canvas.height);
- gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
-
- const maxTextures = gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS);
-
- for (let layer of this.renderable_layers) {
- for (let [r, e] of this.renderables[layer]) {
- if (!e) continue;
- r.render(gl);
- }
- }
- }
-}
diff --git a/web/pw-frontend/src/lib/visualizer/webgl/shader.ts b/web/pw-frontend/src/lib/visualizer/webgl/shader.ts
deleted file mode 100644
index 942c4c2..0000000
--- a/web/pw-frontend/src/lib/visualizer/webgl/shader.ts
+++ /dev/null
@@ -1,327 +0,0 @@
-import type { Dictionary } from './util';
-
-function error(msg: string) {
- console.error(msg);
-}
-
-const defaultShaderType = [
- "VERTEX_SHADER",
- "FRAGMENT_SHADER"
-];
-
-/// Create Shader from Source string
-function loadShader(
- gl: WebGLRenderingContext,
- shaderSource: string,
- shaderType: number,
- opt_errorCallback: any,
-): WebGLShader {
- var errFn = opt_errorCallback || error;
- // Create the shader object
- var shader = gl.createShader(shaderType);
-
- // Load the shader source
- gl.shaderSource(shader, shaderSource);
-
- // Compile the shader
- gl.compileShader(shader);
-
- // Check the compile status
- var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
- if (!compiled) {
- // Something went wrong during compilation; get the error
- var lastError = gl.getShaderInfoLog(shader);
- errFn("*** Error compiling shader '" + shader + "':" + lastError);
- gl.deleteShader(shader);
- return null;
- }
-
- return shader;
-}
-
-/// Actually Create Program with Shader's
-function createProgram(
- gl: WebGLRenderingContext,
- shaders: WebGLShader[],
- opt_attribs: string[],
- opt_locations: number[],
- opt_errorCallback: any,
-): WebGLProgram {
- var errFn = opt_errorCallback || error;
- var program = gl.createProgram();
- shaders.forEach(function (shader) {
- gl.attachShader(program, shader);
- });
- if (opt_attribs) {
- opt_attribs.forEach(function (attrib, ndx) {
- gl.bindAttribLocation(
- program,
- opt_locations ? opt_locations[ndx] : ndx,
- attrib);
- });
- }
- gl.linkProgram(program);
-
- // Check the link status
- var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
- if (!linked) {
- // something went wrong with the link
- var lastError = gl.getProgramInfoLog(program);
- errFn("Error in program linking:" + lastError);
-
- gl.deleteProgram(program);
- return null;
- }
- return program;
-}
-
-export class ShaderFactory {
- frag_source: string;
- vert_source: string;
-
- static async create_factory(frag_url: string, vert_url: string): Promise<ShaderFactory> {
- const sources = await Promise.all([
- fetch(frag_url).then((r) => r.text()),
- fetch(vert_url).then((r) => r.text()),
- ]);
-
- return new ShaderFactory(sources[0], sources[1]);
- }
-
- constructor(frag_source: string, vert_source: string ) {
- this.frag_source = frag_source;
- this.vert_source = vert_source;
- }
-
- create_shader(
- gl: WebGLRenderingContext,
- context?: Dictionary<string>,
- opt_attribs?: string[],
- opt_locations?: number[],
- opt_errorCallback?: any,
- ): Shader {
- let vert = this.vert_source.slice();
- let frag = this.frag_source.slice();
- for (let key in context) {
- vert = vert.replace(new RegExp("\\$" + key, 'g'), context[key]);
- frag = frag.replace(new RegExp("\\$" + key, 'g'), context[key]);
- }
-
- const shaders = [
- loadShader(gl, vert, gl.VERTEX_SHADER, opt_errorCallback),
- loadShader(gl, frag, gl.FRAGMENT_SHADER, opt_errorCallback),
- ];
-
- return new Shader(createProgram(gl, shaders, opt_attribs, opt_locations, opt_errorCallback));
- }
-}
-
-export class Shader {
- shader: WebGLProgram;
- uniformCache: Dictionary<WebGLUniformLocation>;
- attribCache: Dictionary<number>;
-
- static async createProgramFromUrls(
- gl: WebGLRenderingContext,
- vert_url: string,
- frag_url: string,
- context?: Dictionary<string>,
- opt_attribs?: string[],
- opt_locations?: number[],
- opt_errorCallback?: any,
- ): Promise<Shader> {
- const sources = (await Promise.all([
- fetch(vert_url).then((r) => r.text()),
- fetch(frag_url).then((r) => r.text()),
- ])).map(x => {
- for (let key in context) {
- x = x.replace(new RegExp("\\$" + key, 'g'), context[key]);
- }
- return x;
- });
-
- const shaders = [
- loadShader(gl, sources[0], 35633, opt_errorCallback),
- loadShader(gl, sources[1], 35632, opt_errorCallback),
- ];
- return new Shader(createProgram(gl, shaders, opt_attribs, opt_locations, opt_errorCallback));
- }
-
- constructor(shader: WebGLProgram) {
- this.shader = shader;
- this.uniformCache = {};
- this.attribCache = {};
- }
-
- bind(gl: WebGLRenderingContext) {
- gl.useProgram(this.shader);
- }
-
- // Different locations have different types :/
- getUniformLocation(gl: WebGLRenderingContext, name: string): WebGLUniformLocation {
- if (this.uniformCache[name] === undefined) {
- this.uniformCache[name] = gl.getUniformLocation(this.shader, name);
- }
-
- return this.uniformCache[name];
- }
-
- getAttribLocation(gl: WebGLRenderingContext, name: string): number {
- if (this.attribCache[name] === undefined) {
- this.attribCache[name] = gl.getAttribLocation(this.shader, name);
- }
-
- return this.attribCache[name];
- }
-
- uniform<T extends Uniform>(
- gl: WebGLRenderingContext,
- name: string,
- uniform: T,
- ) {
- this.bind(gl);
- const location = this.getUniformLocation(gl, name);
- if (location < 0) {
- console.error("No location found with name " + name);
- }
-
- uniform.setUniform(gl, location);
- }
-
- clear(gl: WebGLRenderingContext) {
- gl.deleteProgram(this.shader);
- }
-}
-
-export interface Uniform {
- setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation): void;
-}
-
-export class Uniform2fv implements Uniform {
- data: number[] | Float32Array;
- constructor(data: number[] | Float32Array) {
- this.data = data;
- }
-
- setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
- gl.uniform2fv(location, this.data);
- }
-}
-
-export class Uniform3fv implements Uniform {
- data: number[] | Float32Array;
- constructor(data: number[] | Float32Array) {
- this.data = data;
- }
-
- setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
- gl.uniform3fv(location, this.data);
- }
-}
-
-export class Uniform3f implements Uniform {
- x: number;
- y: number;
- z: number;
-
- constructor(x: number, y: number, z: number) {
- this.x = x;
- this.y = y;
- this.z = z;
- }
-
- setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
- gl.uniform3f(location, this.x ,this.y, this.z);
- }
-}
-
-export class Uniform1iv implements Uniform {
- data: number[] | Int32List;
- constructor(data: number[] | Int32List) {
- this.data = data;
- }
-
- setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
- gl.uniform1iv(location, this.data);
- }
-}
-
-export class Uniform1i implements Uniform {
- texture: number;
-
- constructor(texture: number) {
- this.texture = texture;
- }
-
- setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
- gl.uniform1i(location, this.texture);
- }
-}
-
-export class Uniform1f implements Uniform {
- texture: number;
-
- constructor(texture: number) {
- this.texture = texture;
- }
-
- setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
- gl.uniform1f(location, this.texture);
- }
-}
-
-export class Uniform2f implements Uniform {
- x: number;
- y: number;
-
- constructor(xy: number[]) {
- this.x = xy[0];
- this.y = xy[1];
- }
-
- setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
- gl.uniform2f(location, this.x, this.y);
- }
-}
-
-export class Uniform4f implements Uniform {
- v0: number;
- v1: number;
- v2: number;
- v3: number;
-
- constructor(xyzw: number[]) {
- this.v0 = xyzw[0];
- this.v1 = xyzw[1];
- this.v2 = xyzw[2];
- this.v3 = xyzw[3];
- }
-
- setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
- gl.uniform4f(location, this.v0, this.v1, this.v2, this.v3);
- }
-}
-
-export class UniformMatrix3fv implements Uniform {
- data: number[] | Float32Array;
- constructor(data: number[] | Float32Array) {
- this.data = data;
- }
-
- setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
- gl.uniformMatrix3fv(location, false, this.data);
- }
-}
-
-export class UniformBool implements Uniform {
- data: boolean;
- constructor(data: boolean) {
- this.data = data;
- }
-
- setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
- gl.uniform1i(location, this.data ? 1 : 0);
- }
-}
-
-export default Shader; \ No newline at end of file
diff --git a/web/pw-frontend/src/lib/visualizer/webgl/text.ts b/web/pw-frontend/src/lib/visualizer/webgl/text.ts
deleted file mode 100644
index 3f1cec6..0000000
--- a/web/pw-frontend/src/lib/visualizer/webgl/text.ts
+++ /dev/null
@@ -1,192 +0,0 @@
-import type { Dictionary } from "./util";
-import type { Shader, UniformMatrix3fv } from "./shader";
-import { Texture } from "./texture";
-import { DefaultRenderable } from "./renderer";
-import { IndexBuffer, VertexBuffer } from "./buffer";
-import { VertexBufferLayout, VertexArray } from "./vertexBufferLayout";
-
-
-export enum Align {
- Begin,
- End,
- Middle,
-}
-
-export class GlypInfo {
- x: number;
- y: number;
- width: number;
-}
-
-export class FontInfo {
- letterHeight: number;
- spaceWidth: number;
- spacing: number;
- textureWidth: number;
- textureHeight: number;
- glyphInfos: Dictionary<GlypInfo>;
-}
-
-export class LabelFactory {
- texture: Texture;
- font: FontInfo;
- shader: Shader;
-
- constructor(gl: WebGLRenderingContext, loc: string, font: FontInfo, shader: Shader) {
- this.texture = Texture.fromImage(gl, loc, 'font');
- this.font = font;
- this.shader = shader;
- }
-
- build(gl: WebGLRenderingContext, transform?: UniformMatrix3fv): Label {
- return new Label(gl, this.shader, this.texture, this.font, transform);
- }
-}
-
-export class Label {
- inner: DefaultRenderable;
-
- font: FontInfo;
-
- constructor(gl: WebGLRenderingContext, shader: Shader, tex: Texture, font: FontInfo, transform?: UniformMatrix3fv) {
- this.font = font;
-
- const uniforms = transform ? { "u_trans": transform, "u_trans_next": transform, } : {};
- const ib = new IndexBuffer(gl, []);
- const vb_pos = new VertexBuffer(gl, []);
- const vb_tex = new VertexBuffer(gl, []);
-
- const layout_pos = new VertexBufferLayout();
- layout_pos.push(gl.FLOAT, 2, 4, "a_position");
-
- const layout_tex = new VertexBufferLayout();
- layout_tex.push(gl.FLOAT, 2, 4, "a_texCoord");
-
- const vao = new VertexArray();
- vao.addBuffer(vb_pos, layout_pos);
- vao.addBuffer(vb_tex, layout_tex);
-
- this.inner = new DefaultRenderable(ib, vao, shader, [tex], uniforms);
- }
-
- getRenderable(): DefaultRenderable {
- return this.inner;
- }
-
- setText(gl: WebGLRenderingContext, text: string, h_align = Align.Begin, v_align = Align.Begin) {
- const idxs = [];
- const verts_pos = [];
- const verts_tex = [];
-
- const letterHeight = this.font.letterHeight / this.font.textureHeight;
- let xPos = 0;
-
- switch (h_align) {
- case Align.Begin:
- break;
- case Align.End:
- xPos = -1 * [...text].map(n => this.font.glyphInfos[n] ? this.font.glyphInfos[n].width : this.font.spaceWidth).reduce((a, b) => a + b, 0) / this.font.letterHeight;
- break;
- case Align.Middle:
- xPos = -1 * [...text].map(n => this.font.glyphInfos[n] ? this.font.glyphInfos[n].width : this.font.spaceWidth).reduce((a, b) => a + b, 0) / this.font.letterHeight / 2;
- break;
- }
- let yStart = 0;
- switch (v_align) {
- case Align.Begin:
- break;
- case Align.End:
- yStart = 1;
- break;
- case Align.Middle:
- yStart = 0.5;
- break;
- }
-
- let j = 0;
- for (let i = 0; i < text.length; i++) {
- const info = this.font.glyphInfos[text[i]];
- if (info) {
- const dx = info.width / this.font.letterHeight;
- const letterWidth = info.width / this.font.textureWidth;
- const x0 = info.x / this.font.textureWidth;
- const y0 = info.y / this.font.textureHeight;
- verts_pos.push(xPos, yStart);
- verts_pos.push(xPos + dx, yStart);
- verts_pos.push(xPos, yStart-1);
- verts_pos.push(xPos + dx, yStart-1);
-
- verts_tex.push(x0, y0);
- verts_tex.push(x0 + letterWidth, y0);
- verts_tex.push(x0, y0 + letterHeight);
- verts_tex.push(x0 + letterWidth, y0 + letterHeight);
-
- xPos += dx;
-
- idxs.push(j+0, j+1, j+2, j+1, j+2, j+3);
- j += 4;
- } else {
- // Just move xPos
- xPos += this.font.spaceWidth / this.font.letterHeight;
- }
- }
-
- this.inner.updateIndexBuffer(gl, idxs);
- this.inner.updateVAOBuffer(gl, 0, verts_pos);
- this.inner.updateVAOBuffer(gl, 1, verts_tex);
- }
-}
-
-export function defaultLabelFactory(gl: WebGLRenderingContext, shader: Shader): LabelFactory {
- const fontInfo = {
- letterHeight: 8,
- spaceWidth: 8,
- spacing: -1,
- textureWidth: 64,
- textureHeight: 40,
- glyphInfos: {
- 'a': { x: 0, y: 0, width: 8, },
- 'b': { x: 8, y: 0, width: 8, },
- 'c': { x: 16, y: 0, width: 8, },
- 'd': { x: 24, y: 0, width: 8, },
- 'e': { x: 32, y: 0, width: 8, },
- 'f': { x: 40, y: 0, width: 8, },
- 'g': { x: 48, y: 0, width: 8, },
- 'h': { x: 56, y: 0, width: 8, },
- 'i': { x: 0, y: 8, width: 8, },
- 'j': { x: 8, y: 8, width: 8, },
- 'k': { x: 16, y: 8, width: 8, },
- 'l': { x: 24, y: 8, width: 8, },
- 'm': { x: 32, y: 8, width: 8, },
- 'n': { x: 40, y: 8, width: 8, },
- 'o': { x: 48, y: 8, width: 8, },
- 'p': { x: 56, y: 8, width: 8, },
- 'q': { x: 0, y: 16, width: 8, },
- 'r': { x: 8, y: 16, width: 8, },
- 's': { x: 16, y: 16, width: 8, },
- 't': { x: 24, y: 16, width: 8, },
- 'u': { x: 32, y: 16, width: 8, },
- 'v': { x: 40, y: 16, width: 8, },
- 'w': { x: 48, y: 16, width: 8, },
- 'x': { x: 56, y: 16, width: 8, },
- 'y': { x: 0, y: 24, width: 8, },
- 'z': { x: 8, y: 24, width: 8, },
- '0': { x: 16, y: 24, width: 8, },
- '1': { x: 24, y: 24, width: 8, },
- '2': { x: 32, y: 24, width: 8, },
- '3': { x: 40, y: 24, width: 8, },
- '4': { x: 48, y: 24, width: 8, },
- '5': { x: 56, y: 24, width: 8, },
- '6': { x: 0, y: 32, width: 8, },
- '7': { x: 8, y: 32, width: 8, },
- '8': { x: 16, y: 32, width: 8, },
- '9': { x: 24, y: 32, width: 8, },
- '-': { x: 32, y: 32, width: 8, },
- '*': { x: 40, y: 32, width: 8, },
- '!': { x: 48, y: 32, width: 8, },
- '?': { x: 56, y: 32, width: 8, },
- },
- };
-
- return new LabelFactory(gl, '/static/res/assets/font.png', fontInfo, shader);
-}
diff --git a/web/pw-frontend/src/lib/visualizer/webgl/texture.ts b/web/pw-frontend/src/lib/visualizer/webgl/texture.ts
deleted file mode 100644
index 9d6adcf..0000000
--- a/web/pw-frontend/src/lib/visualizer/webgl/texture.ts
+++ /dev/null
@@ -1,106 +0,0 @@
-import type { Renderer } from "./renderer";
-
-export class Texture {
- texture: WebGLTexture;
- width: number;
- height: number;
- loaded: boolean;
- name: string;
-
- static fromImage(
- gl: WebGLRenderingContext,
- path: string,
- name: string,
- ): Texture {
- const out = new Texture(gl, name);
-
- const image = new Image();
- image.onload = out.setImage.bind(out, gl, image);
- image.onerror = error;
- image.src = path;
-
- return out;
- }
-
- static fromRenderer(
- gl: WebGLRenderingContext,
- name: string,
- width: number,
- height: number,
- renderer: Renderer
- ): Texture {
- const out = new Texture(gl, name);
- out.width = width;
- out.height = height;
-
- gl.texImage2D(
- gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0,
- gl.RGBA, gl.UNSIGNED_BYTE, null);
-
- const fb = gl.createFramebuffer();
- gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
-
- const attachmentPoint = gl.COLOR_ATTACHMENT0;
- gl.framebufferTexture2D(gl.FRAMEBUFFER, attachmentPoint, gl.TEXTURE_2D, out.texture, 0);
-
- renderer.render(gl, fb, width, height);
-
- out.loaded = true;
-
- return out;
- }
-
- constructor(
- gl: WebGLRenderingContext,
- name: string,
- ) {
- this.loaded = false;
- this.name = name;
-
- this.texture = gl.createTexture();
- this.bind(gl);
-
- 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.NEAREST);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
-
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA,
- gl.UNSIGNED_BYTE, new Uint8Array([255, 0, 0, 255]));
- }
-
- setImage(gl: WebGLRenderingContext, image: HTMLImageElement) {
- this.bind(gl);
- this.width = image.width;
- this.height = image.height;
-
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
-
- this.unbind(gl);
-
- this.loaded = true;
- }
-
- bind(gl: WebGLRenderingContext, location=0) {
- gl.activeTexture(gl.TEXTURE0 + location);
- gl.bindTexture(gl.TEXTURE_2D, this.texture);
- }
-
- unbind(gl: WebGLRenderingContext) {
- gl.bindTexture(gl.TEXTURE_2D, null);
- }
-
-
- getWidth(): number {
- return this.width;
- }
-
- getHeight(): number {
- return this.height;
- }
-}
-
-function error(e: any) {
- console.error("IMAGE LOAD ERROR");
- console.error(e);
-}
diff --git a/web/pw-frontend/src/lib/visualizer/webgl/util.ts b/web/pw-frontend/src/lib/visualizer/webgl/util.ts
deleted file mode 100644
index 3ed2b4d..0000000
--- a/web/pw-frontend/src/lib/visualizer/webgl/util.ts
+++ /dev/null
@@ -1,229 +0,0 @@
-import { parse as parsePath } from 'extract-svg-path';
-import svgMesh3d from 'svg-mesh-3d';
-
-export interface Dictionary<T> {
- [Key: string]: T;
-}
-
-
-interface OnLoadable {
- onload: any;
-}
-
-export function onload2promise<T extends OnLoadable>(obj: T): Promise<T> {
- return new Promise(resolve => {
- obj.onload = () => resolve(obj);
- });
-}
-
-export function resizeCanvasToDisplaySize(
- canvas: HTMLCanvasElement,
- multiplier?: number,
-): boolean {
- multiplier = multiplier || 1;
- var width = canvas.clientWidth * multiplier | 0;
- var height = canvas.clientHeight * multiplier | 0;
- if (canvas.width !== width || canvas.height !== height) {
- canvas.width = width;
- canvas.height = height;
- return true;
- }
- return false;
-}
-
-export class FPSCounter {
- last: number;
- count: number;
- _delta: number;
- _prev: number;
-
- _frame_start: number;
- _total_frametime: number;
-
- constructor() {
- this.last = 0;
- this.count = 0;
- this._delta = 0;
- this._prev = 0;
- }
-
- frame(now: number) {
- this._frame_start = performance.now();
- this.count += 1;
- this._delta = now - this._prev;
- this._prev = now;
-
- if (now - this.last > 1000) {
- this.last = now;
- console.log(`${this.count} fps, ${(this._total_frametime / this.count).toFixed(2)}ms avg per frame`);
- this.count = 0;
- this._total_frametime = 0;
- }
- }
-
- frame_end() {
- this._total_frametime += (performance.now() - this._frame_start);
- }
-
- delta(now: number): number {
- return this._delta;
- }
-}
-
-export class Resizer {
- hoovering = false;
- dragging = false;
-
- mouse_pos = [0, 0];
- last_drag = [0, 0];
-
- viewbox: number[];
- orig_viewbox: number[];
-
- el_box: number[];
-
- scaleX = 1;
- scaleY = 1;
-
- constructor(el: HTMLCanvasElement, viewbox: number[], keep_aspect_ratio=false) {
- viewbox = [-viewbox[0] - viewbox[2], - viewbox[1] - viewbox[3], viewbox[2], viewbox[3]];
- this.viewbox = [...viewbox];
- this.el_box = [el.width, el.height];
-
- if (keep_aspect_ratio) {
- const or_width = this.viewbox[2];
- const or_height = this.viewbox[3];
-
- const width_percentage = this.viewbox[2] / el.width;
- const height_percentage = this.viewbox[3] / el.height;
-
- if (width_percentage < height_percentage) {
- // width should be larger
- this.viewbox[2] = height_percentage * el.width;
- } else {
- // height should be larger
- this.viewbox[3] = width_percentage * el.height;
- }
-
- this.viewbox[0] -= (this.viewbox[2] - or_width) / 2;
- this.viewbox[1] -= (this.viewbox[3] - or_height) / 2;
-
- this.scaleX = this.viewbox[2] / this.viewbox[3];
- }
-
- this.orig_viewbox = [...this.viewbox];
-
- el.addEventListener("mouseenter", this.mouseenter.bind(this), { capture: false, passive: true});
- el.addEventListener("mouseleave", this.mouseleave.bind(this), { capture: false, passive: true});
- el.addEventListener("mousemove", this.mousemove.bind(this), { capture: false, passive: true});
- el.addEventListener("mousedown", this.mousedown.bind(this), { capture: false, passive: true});
- el.addEventListener("mouseup", this.mouseup.bind(this), { capture: false, passive: true});
-
- window.addEventListener('wheel', this.wheel.bind(this), { capture: false, passive: true});
- }
-
- _clip_viewbox() {
- this.viewbox[0] = Math.max(this.viewbox[0], this.orig_viewbox[0]);
- this.viewbox[1] = Math.max(this.viewbox[1], this.orig_viewbox[1]);
-
- this.viewbox[0] = Math.min(this.viewbox[0] + this.viewbox[2], this.orig_viewbox[0] + this.orig_viewbox[2]) - this.viewbox[2];
- this.viewbox[1] = Math.min(this.viewbox[1] + this.viewbox[3], this.orig_viewbox[1] + this.orig_viewbox[3]) - this.viewbox[3];
- }
-
- mouseenter() {
- this.hoovering = true;
- }
-
- mouseleave() {
- this.hoovering = false;
- }
-
- mousemove(e: MouseEvent) {
- this.mouse_pos = [e.offsetX, this.el_box[1] - e.offsetY];
-
- if (this.dragging) {
- const scaleX = this.viewbox[2] / this.el_box[0];
- const scaleY = this.viewbox[3] / this.el_box[1];
-
- this.viewbox[0] += (this.last_drag[0] - this.mouse_pos[0]) * scaleX;
- this.viewbox[1] += (this.last_drag[1] - this.mouse_pos[1]) * scaleY;
-
- this.last_drag = [...this.mouse_pos];
-
- this._clip_viewbox();
- }
- }
-
- mousedown() {
- this.dragging = true;
- this.last_drag = [...this.mouse_pos];
- }
-
- mouseup() {
- this.dragging = false;
- }
-
- wheel(e: WheelEvent) {
- if (this.hoovering) {
- const delta = e.deltaY > 0 ? 0.1 * this.viewbox[2] : -0.1 * this.viewbox[2];
- const dx = delta * this.scaleX;
- const dy = delta * this.scaleY;
-
- const mouse_dx = this.mouse_pos[0] / this.el_box[0];
- const mouse_dy = this.mouse_pos[1] / this.el_box[1];
-
- this._zoom([dx, dy], [mouse_dx, mouse_dy]);
- }
- }
-
- _zoom(deltas: number[], center: number[]) {
- this.viewbox[2] += deltas[0];
- this.viewbox[0] -= deltas[0] * center[0];
- this.viewbox[2] = Math.min(this.viewbox[2], this.orig_viewbox[2]);
-
- this.viewbox[3] += deltas[1];
- this.viewbox[1] -= deltas[1] * center[1];
- this.viewbox[3] = Math.min(this.viewbox[3], this.orig_viewbox[3]);
-
- this._clip_viewbox();
- }
-
- get_viewbox(): number[] {
- return this.viewbox;
- }
-
- get_mouse_pos(): number[] {
- return this.mouse_pos;
- }
-}
-
-export class Mesh {
- cells: number[];
- positions: number[];
-
- constructor(mesh: any) {
- this.cells = mesh.cells.flat();
- this.positions = mesh.positions.flat();
- }
-}
-
-export async function url_to_mesh(url: string): Promise<Mesh> {
-
- return new Promise(function(resolve) {
- fetch(url)
- .then(resp => resp.text())
- .then(data => {
- // var div = document.createElement('div');
- // div.innerHTML = data;
- // var svg = div.querySelector('svg');
-
- var svgPath = parsePath(data);
- var mesh = svgMesh3d(svgPath, {
- delaunay: false,
- scale: 10,
- });
-
- resolve(new Mesh(mesh));
- })
- });
-}
diff --git a/web/pw-frontend/src/lib/visualizer/webgl/vertexBufferLayout.ts b/web/pw-frontend/src/lib/visualizer/webgl/vertexBufferLayout.ts
deleted file mode 100644
index f44ed47..0000000
--- a/web/pw-frontend/src/lib/visualizer/webgl/vertexBufferLayout.ts
+++ /dev/null
@@ -1,115 +0,0 @@
-import type { VertexBuffer } from './buffer';
-import type { Shader } from './shader';
-
-export class VertexBufferElement {
- type: number;
- amount: number;
- type_size: number;
- normalized: boolean;
- index: string;
-
- constructor(
- type: number,
- amount: number,
- type_size: number,
- index: string,
- normalized: boolean,
- ) {
- this.type = type;
- this.amount = amount;
- this.type_size = type_size;
- this.normalized = normalized;
- this.index = index;
- }
-}
-
-export class VertexBufferLayout {
- elements: VertexBufferElement[];
- stride: number;
- offset: number;
-
- constructor(offset = 0) {
- this.elements = [];
- this.stride = 0;
- this.offset = offset;
- }
-
- // Maybe wrong normalized type
- push(
- type: number,
- amount: number,
- type_size: number,
- index: string,
- normalized = false,
- ) {
- this.elements.push(new VertexBufferElement(type, amount, type_size, index, normalized));
- this.stride += amount * type_size;
- }
-
- getElements(): VertexBufferElement[] {
- return this.elements;
- }
-
- getStride(): number {
- return this.stride;
- }
-}
-
-// glEnableVertexAttribArray is to specify what location of the current program the follow data is needed
-// glVertexAttribPointer tells gl that that data is at which location in the supplied data
-export class VertexArray {
- // There is no renderer ID, always at bind buffers and use glVertexAttribPointer
- buffers: VertexBuffer[];
- layouts: VertexBufferLayout[];
-
- constructor() {
- this.buffers = [];
- this.layouts = [];
- }
-
- addBuffer(vb: VertexBuffer, layout: VertexBufferLayout) {
- this.buffers.push(vb);
- this.layouts.push(layout);
- }
-
- updateBuffer(gl: WebGLRenderingContext, index: number, data: number[]) {
- this.buffers[index].updateData(gl, data);
- }
-
- /// Bind buffers providing program data
- bind(gl: WebGLRenderingContext, shader: Shader) {
- shader.bind(gl);
- for(let i = 0; i < this.buffers.length; i ++) {
- const buffer = this.buffers[i];
- const layout = this.layouts[i];
-
- buffer.bind(gl);
- const elements = layout.getElements();
- let offset = layout.offset;
-
- for (let j = 0; j < elements.length; j ++) {
- const element = elements[j];
- const location = shader.getAttribLocation(gl, element.index);
-
- if (location >= 0) {
- gl.enableVertexAttribArray(location);
- gl.vertexAttribPointer(
- location, element.amount, element.type,
- element.normalized, layout.stride, offset
- );
- }
-
- offset += element.amount * element.type_size;
- }
- }
- }
-
- /// Undo bind operation
- unbind(gl: WebGLRenderingContext) {
- this.layouts.forEach((layout) => {
- layout.getElements().forEach((_, index) => {
- gl.disableVertexAttribArray(index);
- });
- })
- }
-}