update some build/telemetry stuff

This commit is contained in:
41666 2023-10-13 16:59:46 -04:00
parent 51f9f820d8
commit 0a67ccb040
25 changed files with 336 additions and 217 deletions

View file

@ -27,6 +27,8 @@ const results = await Bun.build({
".wgsl": "text",
".vert": "text",
".frag": "text",
".html": "text",
".md": "text",
},
minify: process.env.MINIFY === "false" ? false : true,
plugins: [glslPlugin],

View file

@ -214,42 +214,32 @@ export const convertMeshes = async () => {
: [];
const facesArray: number[] = faces.flatMap((f) => [f.a, f.b, f.c]);
const facesMaxValue = facesArray.reduce(
(acc, face) => (face > acc ? face : acc),
0
);
const facesBitDepth =
facesMaxValue <= 0xff ? 8 : facesMaxValue <= 0xffff ? 16 : 32;
const outFile = file.replace(".ply", ".ts");
const outString = `
import { Mesh } from "../renderer/mesh";
const outString = `import { Mesh } from "../renderer/mesh";
// prettier-ignore
const positions = new Float32Array(${JSON.stringify(positions)});
// prettier-ignore
const colors = ${
vertexConfig.colors ? `new Uint8Array(${JSON.stringify(colors)})` : "null"
};
// prettier-ignore
const uvs = ${
vertexConfig.uvs ? `new Float32Array(${JSON.stringify(uvs)})` : "null"
};
// prettier-ignore
const normals = ${
vertexConfig.normals
? `new Float32Array(${JSON.stringify(normals)})`
: "null"
};
// prettier-ignore
const faces = new Uint32Array(${JSON.stringify(facesArray)});
export default new Mesh({
colors,
faces,
colors: ${
vertexConfig.colors ? `new Uint8Array(${JSON.stringify(colors)})` : "null"
},
faces: new Uint${facesBitDepth}Array(${JSON.stringify(facesArray)}),
name: ${JSON.stringify(file)},
normals,
positions,
uvs,
normals: ${
vertexConfig.normals
? `new Float32Array(${JSON.stringify(normals)})`
: "null"
},
positions: new Float32Array(${JSON.stringify(positions)}),
uvs: ${
vertexConfig.uvs ? `new Float32Array(${JSON.stringify(uvs)})` : "null"
},
vertexCount: ${vertexCount}
});
`;

View file

@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<meta charset="utf-8" />
<title>com.mekanoe.art // ##name##</title>
<style>
@ -9,6 +9,7 @@
overflow: hidden;
background-color: black;
color: white;
font-family: Atkinson Hyperlegible, sans-serif;
}
main {
display: flex;
@ -21,8 +22,7 @@
<main>
<canvas id="canvas" width="1280" height="720"></canvas>
<div id="telemetry">XX.X FPS (XX.X ms)</div>
<nav>
##nav##
</nav>
<div id="loading" class="loading-active"><div id="loading-text">[noeidelon] [stage 1]<br />bootstrapping...<span id="stage1-error"><br />this is taking a while...</span><span id="stage1-error2"><br />[panic] <span style="color: red">heck wtf</span></span></div></div>
<nav>##nav##</nav>
</main>
<script src="/##name##/main.js" type="module"></script>

View file

@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<meta charset="utf-8" />
<title>com.mekanoe.art // 003-scene</title>
<style>
@ -9,6 +9,7 @@
overflow: hidden;
background-color: black;
color: white;
font-family: Atkinson Hyperlegible, sans-serif;
}
main {
display: flex;
@ -21,8 +22,7 @@
<main>
<canvas id="canvas" width="1280" height="720"></canvas>
<div id="telemetry">XX.X FPS (XX.X ms)</div>
<nav>
<a class="nav-left" href="/002-webgl-engine">⇠ 002-webgl-engine</a>
</nav>
<div id="loading" class="loading-active"><div id="loading-text">[noeidelon] [stage 1]<br />bootstrapping...<span id="stage1-error"><br />this is taking a while...</span><span id="stage1-error2"><br />[panic] <span style="color: red">heck wtf</span></span></div></div>
<nav><a class="nav-left" href="/002-webgl-engine">⇠ 002-webgl-engine</a></nav>
</main>
<script src="/003-scene/main.js" type="module"></script>

File diff suppressed because one or more lines are too long

View file

@ -11,6 +11,54 @@
display: none;
}
#loading {
display: none;
z-index: 110;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
align-items: center;
justify-content: center;
text-align: center;
font-family: 'Fira Code', 'Fira Mono', monospace;
&.loading-active {
display: flex;
}
& #loading-text {
background-color: black;
padding: 1em;
border-radius: 8px;
max-width: 80vw;
word-wrap: break-word;
& #stage1-error {
opacity: 0;
animation: opacity_0_1 1ms 5s forwards 1;
color: orange;
}
& #stage1-error2 {
opacity: 0;
animation: opacity_0_1 1ms 10s forwards 1;
}
}
}
@keyframes opacity_0_1 {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
nav {
position: fixed;
z-index: 10;

10
index.d.ts vendored
View file

@ -20,3 +20,13 @@ declare module "*.frag" {
const content: string;
export default content;
}
declare module "*.html" {
const content: string;
export default content;
}
declare module "*.md" {
const content: string;
export default content;
}

View file

@ -4,7 +4,7 @@
"main": "./hack/build.ts",
"scripts": {
"build": "bun $BUNFLAGS .",
"build:watch": "nodemon -e ts,js,frag,vert,glsl,ply",
"build:watch": "MINIFY=false nodemon -e ts,js,frag,vert,glsl,ply",
"serve": "serve ./html",
"dev": "run-p serve build:watch"
},

View file

@ -9,7 +9,7 @@ import { basic } from "../common-shaders/basic";
const app = new WebGLApp({ fov: 45 });
const camera = new Transform([3, 3, 5], etoq([-15, 26, 0]));
const camera = new Transform([3, 3, 5], etoq([-15, 40, 0]));
const light = new Transform([1, 1, 0]);
const transform = new Transform(v3(0), etoq([0, 0, 0]));
@ -19,15 +19,19 @@ app.onUpdate(() => {
quat.rotateY(transform.rotation, transform.rotation, 0.001);
});
new Renderable(
app,
transform2,
new MeshRenderer(app, trianglething, basic(app), camera, light).configure({})
);
new Renderable(
app,
transform,
new MeshRenderer(app, teapot, basic(app), camera, light).configure({})
);
setTimeout(() => {
new Renderable(
app,
transform2,
new MeshRenderer(app, trianglething, basic(app), camera, light).configure(
{}
)
);
new Renderable(
app,
transform,
new MeshRenderer(app, teapot, basic(app), camera, light).configure({})
);
app.start();
app.start();
}, 7000);

View file

@ -1,42 +1,28 @@
#version 300 es
precision highp float;
uniform float u_time;
// uniform mat4 u_view;
// uniform mat4 u_projection;
// uniform mat4 u_object_to_world;
// uniform mat4 u_object_to_world_inv;
// uniform vec3 u_light_0;
// uniform vec4 u_light_0_color;
// uniform float u_time;
// uniform vec4 u_albedo;
in vec2 uv0;
in vec3 normal;
in vec4 vertex_color;
in vec3 light_pos;
out vec4 fragColor;
vec3 rgb2hsv(vec3 c) {
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
vec3 hsv2rgb(vec3 c) {
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
void main() {
vec3 normal = normalize(normal);
float light = dot(normal, light_pos);
float zComponent = sin(u_time) * 0.004 * 0.5 + 0.5;
vec3 hsv = rgb2hsv(vec3(uv0, zComponent));
hsv.x += u_time * 0.0004;
hsv.y = 1.0;
hsv.z = 1.0;
vec3 rgb = hsv2rgb(hsv);
fragColor = vec4(rgb, 1.0);
fragColor *= max(light, 0.1);
fragColor = vec4(1.0);
fragColor.rgb *= max(light, 0.1);
}

View file

@ -19,6 +19,9 @@ export const basicShaderConfig: ShaderConfig = {
light0: "u_light_0",
light0Color: "u_light_0_color",
time: "u_time",
albedo: "u_albedo",
texture0: "u_texture_0",
texture1: "u_texture_1",
},
};

View file

@ -4,8 +4,9 @@ uniform mat4 u_projection;
uniform mat4 u_object_to_world;
uniform mat4 u_object_to_world_inv;
uniform vec3 u_light_0;
uniform vec4 u_light_0_color;
uniform float u_time;
// uniform vec4 u_light_0_color;
// uniform float u_time;
// uniform vec4 u_albedo;
in vec4 a_vertex;
in vec2 a_uv0;

View file

@ -1,28 +1,12 @@
import { Mesh } from "../renderer/mesh";
// prettier-ignore
const positions = new Float32Array([1,-1,0,-1,1,0,-1,-1,0,1,1,0]);
// prettier-ignore
const colors = null;
// prettier-ignore
const uvs = new Float32Array([1,0,0,1,0,0,1,1]);
// prettier-ignore
const normals = null;
// prettier-ignore
const faces = new Uint32Array([0,1,2,0,3,1]);
export default new Mesh({
colors,
faces,
colors: null,
faces: new Uint8Array([0,1,2,0,3,1]),
name: "src/meshes/plane.ply",
normals,
positions,
uvs,
normals: null,
positions: new Float32Array([1,-1,0,-1,1,0,-1,-1,0,1,1,0]),
uvs: new Float32Array([1,0,0,1,0,0,1,1]),
vertexCount: 4
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,28 +1,12 @@
import { Mesh } from "../renderer/mesh";
// prettier-ignore
const positions = new Float32Array([0,2.609,0,-0.368004,2.9959495,0.50652,-0.595448,2.9959495,-0.19346951,0,2.609,0,0.368004,2.9959495,0.50652,0,2.609,0,-0.595448,2.9959495,-0.19346951,0,2.9959495,-0.6260975,0,2.609,0,0.595448,2.9959495,-0.19346951,0,2.609,0,0,3.6220505,0.6260975,-0.595448,3.6220505,0.19346951,-0.368004,3.6220505,-0.50652,0.368004,3.6220505,-0.50652,0.595448,3.6220505,0.19346951,-0.368004,3.6220505,-0.50652,0,4.0090003,0,0,4.0090003,0,0,4.0090003,0,0,4.0090003,0,0,4.0090003,0,1,0,0,0,2.5,0,-4.3711392e-8,0,1,-1,0,-8.7422784e-8,-4.3711392e-8,0,1,1.19248815e-8,0,-1,1,0,0,1.19248815e-8,0,-1,-1,0,-8.7422784e-8]);
// prettier-ignore
const colors = new Uint8Array([0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255]);
// prettier-ignore
const uvs = new Float32Array([0.00013659838,0.8180941,0.15755458,0.7272099,0.1575546,0.9089782,0.00013659043,0.6363257,0.15755458,0.54544157,0.0001365666,0.09102075,0.15755455,0.00013656964,0.15755457,0.18190491,0.00013657454,0.2727891,0.15755457,0.36367324,0.00013658249,0.45455742,0.31497157,0.6363257,0.31497157,0.8180941,0.31497154,0.09102073,0.31497154,0.27278906,0.31497154,0.45455742,0.31497157,0.9998634,0.47238955,0.72720987,0.47238958,0.9089782,0.47238955,0.1819049,0.47238955,0.36367324,0.47238955,0.54544157,0.8119813,0.33945516,0.642322,0.16979587,0.8119813,0.00013659486,0.47266275,0.00013660162,0.81198126,0.6790469,0.47266275,0.33972836,0.47266272,0.6790469,0.47266275,0.33945513,0.81198126,0.3397284]);
// prettier-ignore
const normals = new Float32Array([0,-1,8.3803394e-7,-0.5257306,-0.44721383,0.723607,-0.8506533,-0.44721213,-0.2763879,0,-1,8.3803394e-7,0.5257306,-0.4472139,0.723607,0,-1,8.3803394e-7,-0.8506533,-0.44721213,-0.2763879,0,-0.44721153,-0.89442825,0,-1,8.3803394e-7,0.8506533,-0.4472122,-0.27638793,0,-1,8.3803394e-7,0,0.44721153,0.89442825,-0.8506533,0.44721216,0.27638793,-0.5257306,0.4472139,-0.72360694,0.5257306,0.4472139,-0.72360694,0.85065323,0.4472122,0.2763879,-0.5257306,0.4472139,-0.72360694,0,1,-8.165459e-7,0,1,-8.165459e-7,0,1,-8.165459e-7,0,1,-8.165459e-7,0,1,-8.165459e-7,0.8999471,-0.43599886,2.4163015e-7,-5.150958e-8,1,0,-3.0203772e-8,-0.4359989,0.8999472,-0.8999471,-0.4359989,-2.4291313e-7,-3.0203772e-8,-0.4359989,0.8999472,0,-0.43599886,-0.8999471,0.8999471,-0.43599886,2.4163015e-7,0,-0.43599886,-0.8999471,-0.8999471,-0.4359989,-2.4291313e-7]);
// prettier-ignore
const faces = new Uint32Array([0,1,2,1,3,4,5,6,7,8,7,9,10,9,4,1,4,11,2,1,12,7,6,13,9,7,14,4,9,15,1,11,12,2,12,16,7,13,14,9,14,15,4,15,11,12,11,17,16,12,18,14,13,19,15,14,20,11,15,21,22,23,24,24,23,25,26,27,28,25,23,29,29,23,22,26,30,27]);
export default new Mesh({
colors,
faces,
colors: new Uint8Array([0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255]),
faces: new Uint8Array([0,1,2,1,3,4,5,6,7,8,7,9,10,9,4,1,4,11,2,1,12,7,6,13,9,7,14,4,9,15,1,11,12,2,12,16,7,13,14,9,14,15,4,15,11,12,11,17,16,12,18,14,13,19,15,14,20,11,15,21,22,23,24,24,23,25,26,27,28,25,23,29,29,23,22,26,30,27]),
name: "src/meshes/trianglething.ply",
normals,
positions,
uvs,
normals: new Float32Array([0,-1,8.3803394e-7,-0.5257306,-0.44721383,0.723607,-0.8506533,-0.44721213,-0.2763879,0,-1,8.3803394e-7,0.5257306,-0.4472139,0.723607,0,-1,8.3803394e-7,-0.8506533,-0.44721213,-0.2763879,0,-0.44721153,-0.89442825,0,-1,8.3803394e-7,0.8506533,-0.4472122,-0.27638793,0,-1,8.3803394e-7,0,0.44721153,0.89442825,-0.8506533,0.44721216,0.27638793,-0.5257306,0.4472139,-0.72360694,0.5257306,0.4472139,-0.72360694,0.85065323,0.4472122,0.2763879,-0.5257306,0.4472139,-0.72360694,0,1,-8.165459e-7,0,1,-8.165459e-7,0,1,-8.165459e-7,0,1,-8.165459e-7,0,1,-8.165459e-7,0.8999471,-0.43599886,2.4163015e-7,-5.150958e-8,1,0,-3.0203772e-8,-0.4359989,0.8999472,-0.8999471,-0.4359989,-2.4291313e-7,-3.0203772e-8,-0.4359989,0.8999472,0,-0.43599886,-0.8999471,0.8999471,-0.43599886,2.4163015e-7,0,-0.43599886,-0.8999471,-0.8999471,-0.4359989,-2.4291313e-7]),
positions: new Float32Array([0,2.609,0,-0.368004,2.9959495,0.50652,-0.595448,2.9959495,-0.19346951,0,2.609,0,0.368004,2.9959495,0.50652,0,2.609,0,-0.595448,2.9959495,-0.19346951,0,2.9959495,-0.6260975,0,2.609,0,0.595448,2.9959495,-0.19346951,0,2.609,0,0,3.6220505,0.6260975,-0.595448,3.6220505,0.19346951,-0.368004,3.6220505,-0.50652,0.368004,3.6220505,-0.50652,0.595448,3.6220505,0.19346951,-0.368004,3.6220505,-0.50652,0,4.0090003,0,0,4.0090003,0,0,4.0090003,0,0,4.0090003,0,0,4.0090003,0,1,0,0,0,2.5,0,-4.3711392e-8,0,1,-1,0,-8.7422784e-8,-4.3711392e-8,0,1,1.19248815e-8,0,-1,1,0,0,1.19248815e-8,0,-1,-1,0,-8.7422784e-8]),
uvs: new Float32Array([0.00013659838,0.8180941,0.15755458,0.7272099,0.1575546,0.9089782,0.00013659043,0.6363257,0.15755458,0.54544157,0.0001365666,0.09102075,0.15755455,0.00013656964,0.15755457,0.18190491,0.00013657454,0.2727891,0.15755457,0.36367324,0.00013658249,0.45455742,0.31497157,0.6363257,0.31497157,0.8180941,0.31497154,0.09102073,0.31497154,0.27278906,0.31497154,0.45455742,0.31497157,0.9998634,0.47238955,0.72720987,0.47238958,0.9089782,0.47238955,0.1819049,0.47238955,0.36367324,0.47238955,0.54544157,0.8119813,0.33945516,0.642322,0.16979587,0.8119813,0.00013659486,0.47266275,0.00013660162,0.81198126,0.6790469,0.47266275,0.33972836,0.47266272,0.6790469,0.47266275,0.33945513,0.81198126,0.3397284]),
vertexCount: 31
});

File diff suppressed because one or more lines are too long

View file

@ -11,6 +11,54 @@
display: none;
}
#loading {
display: none;
z-index: 110;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
align-items: center;
justify-content: center;
text-align: center;
font-family: 'Fira Code', 'Fira Mono', monospace;
&.loading-active {
display: flex;
}
& #loading-text {
background-color: black;
padding: 1em;
border-radius: 8px;
max-width: 80vw;
word-wrap: break-word;
& #stage1-error {
opacity: 0;
animation: opacity_0_1 1ms 5s forwards 1;
color: orange;
}
& #stage1-error2 {
opacity: 0;
animation: opacity_0_1 1ms 10s forwards 1;
}
}
}
@keyframes opacity_0_1 {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
nav {
position: fixed;
z-index: 10;

View file

@ -1,7 +1,10 @@
import { Shader } from "./shader";
import { Shader, ShaderConfig } from "./shader";
export type MaterialConfig = {
shader: Shader;
uniforms: {
[key: string]: (gl: WebGL2RenderingContext, material: Material) => void;
};
};
export class Material {

View file

@ -21,6 +21,8 @@ export class MeshRenderer extends Behavior {
color?: WebGLBuffer;
faces?: WebGLBuffer;
} = {};
faceDataType: number;
colorDataType: number | null;
constructor(
public app: WebGLApp,
@ -31,6 +33,24 @@ export class MeshRenderer extends Behavior {
public config: MeshRendererConfig = {}
) {
super(app);
this.faceDataType = this.getDataType(mesh.config.faces);
this.colorDataType = mesh.config.colors
? this.getDataType(mesh.config.colors)
: null;
}
getDataType(array: Uint16Array | Uint32Array | Uint8Array) {
switch (array.BYTES_PER_ELEMENT) {
case 1:
return 5121; // uint8 UNSIGNED_BYTE
case 2:
return 5123; // uint16 UNSIGNED_SHORT
case 4:
return 5125; // uint32 UNSIGNED_INT
default:
return 5126; // float32 FLOAT
}
}
configure(config: MeshRendererConfig) {
@ -93,7 +113,7 @@ export class MeshRenderer extends Behavior {
this.buffers.color,
shaderMap.attributes.vertexColor,
4,
this.app.gl.UNSIGNED_BYTE
this.colorDataType || this.app.gl.UNSIGNED_BYTE
);
}
@ -158,7 +178,12 @@ export class MeshRenderer extends Behavior {
);
}
onStart() {
onStart(_: never, app: WebGLApp) {
app.loading("baking vectors");
app.telemetry?.addRenderers(1);
app.telemetry?.addTriangles(this.mesh.config.faces.length);
app.telemetry?.addVertexes(this.mesh.config.vertexCount);
mat4.perspective(
this.projectionMatrix,
this.app.config.fov || 45,
@ -185,7 +210,7 @@ export class MeshRenderer extends Behavior {
gl.drawElements(
this.config.drawMode ?? gl.TRIANGLES,
this.mesh.config.faces.length,
gl.UNSIGNED_INT,
this.faceDataType,
0
);

View file

@ -1,6 +1,6 @@
export type MeshConfig = {
colors: Uint8Array | null;
faces: Uint32Array;
colors: Uint8Array | Uint16Array | null;
faces: Uint32Array | Uint16Array | Uint8Array;
name: string;
normals: Float32Array | null;
positions: Float32Array;

View file

@ -1,5 +1,3 @@
import { mat4, vec3 } from "gl-matrix";
import { Transform } from "./transform";
import { WebGLApp } from "./webgl";
/**
@ -20,17 +18,21 @@ export type ShaderMapping<
uv0: Attr;
normal: Attr;
vertexColor: Attr;
material?: { [key: string]: Attr };
};
uniforms: {
view: Uniform;
projection: Uniform;
objectToWorld: Uniform;
objectToWorldInv: Uniform;
albedo: Uniform;
light0: Uniform;
light0Color: Uniform;
objectToWorld: Uniform;
objectToWorldInv: Uniform;
projection: Uniform;
texture0: Uniform;
texture1: Uniform;
time: Uniform;
view: Uniform;
};
};
@ -89,13 +91,16 @@ export class Shader {
vertexColor: this.attrib(config.attributes.vertexColor),
},
uniforms: {
albedo: this.uniform(config.uniforms.albedo),
light0: this.uniform(config.uniforms.light0),
light0Color: this.uniform(config.uniforms.light0Color),
objectToWorld: this.uniform(config.uniforms.objectToWorld),
objectToWorldInv: this.uniform(config.uniforms.objectToWorldInv),
projection: this.uniform(config.uniforms.projection),
view: this.uniform(config.uniforms.view),
texture0: this.uniform(config.uniforms.texture0),
texture1: this.uniform(config.uniforms.texture1),
time: this.uniform(config.uniforms.time),
view: this.uniform(config.uniforms.view),
},
};
}

View file

@ -6,6 +6,10 @@ export class Telemetry extends Behavior {
public frameTimes: number[] = [];
public maxFrameTimes: number = 100;
public lastFrameTime: number = 0;
public activeTriangles: number = 0;
public activeVertexes: number = 0;
public activeRenderers: number = 0;
constructor(
public app: WebGLApp,
selector = "#telemetry"
@ -25,29 +29,50 @@ export class Telemetry extends Behavior {
}
}
onStart() {
async onStart() {
this.lastFrameTime = 0;
this.frameTimes = [];
// Send this to the end of onStart execution
setTimeout(() => this.setText(), 0);
setInterval(() => {
const averageFrameTime =
this.frameTimes.reduce((a, b) => a + b, 0) / this.frameTimes.length;
const framesPerSecond = 1000 / averageFrameTime;
this.el.innerHTML = `${framesPerSecond.toFixed(
1
)} FPS (${averageFrameTime.toFixed(3)} ms)<br />bU: ${
this.app.registry.onBeforeUpdate.length
} | U: ${this.app.registry.onUpdate.length} | aU: ${
this.app.registry.onAfterUpdate.length
}`;
this.setText();
}, 1001);
}
setText() {
const averageFrameTime =
this.frameTimes.reduce((a, b) => a + b, 0) / this.frameTimes.length;
const framesPerSecond = 1000 / averageFrameTime;
this.el.innerHTML = `${framesPerSecond.toFixed(
1
)} FPS (${averageFrameTime.toFixed(3)} ms)<br />update :: b: ${
this.app.registry.onBeforeUpdate.length
} | u: ${this.app.registry.onUpdate.length} | a: ${
this.app.registry.onAfterUpdate.length
} | d: ${this.app.registry.onDraw.length}<br />render :: mr: ${
this.activeRenderers
} | v: ${this.activeVertexes} | t: ${this.activeTriangles}`;
}
onAfterUpdate(time: number) {
const frameTime = time - this.lastFrameTime;
this.insertTime(frameTime);
this.lastFrameTime = time;
}
addTriangles(n: number) {
this.activeTriangles += n;
}
addVertexes(n: number) {
this.activeVertexes += n;
}
addRenderers(n: number) {
this.activeRenderers += n;
}
}

17
src/renderer/texture.ts Normal file
View file

@ -0,0 +1,17 @@
import { Behavior } from "./behavior";
import { WebGLApp } from "./webgl";
export class Texture extends Behavior {
public texture: Uint8Array | null = null;
constructor(
public app: WebGLApp,
public url: string
) {
super(app);
}
async onStart(_: never, app: WebGLApp) {
app.loading("Fetching textures...");
}
}

View file

@ -7,12 +7,16 @@ export type WebGPUAppConfig = {
zFar?: number;
};
export type RenderHandle = (time: number, app: WebGLApp) => void;
export type RenderHandle = (
time: number,
app: WebGLApp
) => void | Promise<void>;
export class WebGLApp {
public canvas: HTMLCanvasElement;
public telemetry?: Telemetry;
public gl: WebGL2RenderingContext;
private loadingMessages: Set<string> = new Set(["[noeidelon] [stage 2]"]);
public registry: {
onBeforeUpdate: RenderHandle[];
@ -71,6 +75,18 @@ export class WebGLApp {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
}
loading(message: string) {
this.loadingMessages.add(message.toLowerCase());
(document.querySelector("#loading-text") as HTMLDivElement).innerHTML = [
...this.loadingMessages,
].join("<br />");
}
ready() {
document.querySelector("#loading")?.classList.remove("loading-active");
}
onBeforeUpdate(handle: RenderHandle) {
this.registry.onBeforeUpdate.push(handle);
}
@ -99,18 +115,34 @@ export class WebGLApp {
this.registry.onDraw.forEach((handle) => handle(time, this));
}
doStart(time: number = 0) {
async doStart(time: number = 0) {
this.loading("setting launch parameters");
this.clear();
this.registry.onStart.forEach((handle) => handle(time, this));
try {
for (const fn of this.registry.onStart) {
await fn(time, this);
}
} catch (e) {
this.loading(
`[panic] <span style="color: red">failed to start noeidelon</span>`
);
if (this.telemetry) {
this.loading(`<span style="color: purple">${e}</span>`);
}
return;
}
this.ready();
}
async oneShot(time: number = 0) {
this.doStart(time);
await this.doStart(time);
this.doUpdate(time);
}
async start() {
this.doStart();
await this.doStart();
const run = (time: number) => {
this.doUpdate(time);