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", ".wgsl": "text",
".vert": "text", ".vert": "text",
".frag": "text", ".frag": "text",
".html": "text",
".md": "text",
}, },
minify: process.env.MINIFY === "false" ? false : true, minify: process.env.MINIFY === "false" ? false : true,
plugins: [glslPlugin], 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 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 outFile = file.replace(".ply", ".ts");
const outString = ` const outString = `import { Mesh } from "../renderer/mesh";
import { Mesh } from "../renderer/mesh";
// prettier-ignore // 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({ export default new Mesh({
colors, colors: ${
faces, vertexConfig.colors ? `new Uint8Array(${JSON.stringify(colors)})` : "null"
},
faces: new Uint${facesBitDepth}Array(${JSON.stringify(facesArray)}),
name: ${JSON.stringify(file)}, name: ${JSON.stringify(file)},
normals, normals: ${
positions, vertexConfig.normals
uvs, ? `new Float32Array(${JSON.stringify(normals)})`
: "null"
},
positions: new Float32Array(${JSON.stringify(positions)}),
uvs: ${
vertexConfig.uvs ? `new Float32Array(${JSON.stringify(uvs)})` : "null"
},
vertexCount: ${vertexCount} vertexCount: ${vertexCount}
}); });
`; `;

View file

@ -1,4 +1,4 @@
<!DOCTYPE html> <!doctype html>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>com.mekanoe.art // ##name##</title> <title>com.mekanoe.art // ##name##</title>
<style> <style>
@ -9,6 +9,7 @@
overflow: hidden; overflow: hidden;
background-color: black; background-color: black;
color: white; color: white;
font-family: Atkinson Hyperlegible, sans-serif;
} }
main { main {
display: flex; display: flex;
@ -21,8 +22,7 @@
<main> <main>
<canvas id="canvas" width="1280" height="720"></canvas> <canvas id="canvas" width="1280" height="720"></canvas>
<div id="telemetry">XX.X FPS (XX.X ms)</div> <div id="telemetry">XX.X FPS (XX.X ms)</div>
<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##</nav>
</nav>
</main> </main>
<script src="/##name##/main.js" type="module"></script> <script src="/##name##/main.js" type="module"></script>

View file

@ -1,4 +1,4 @@
<!DOCTYPE html> <!doctype html>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>com.mekanoe.art // 003-scene</title> <title>com.mekanoe.art // 003-scene</title>
<style> <style>
@ -9,6 +9,7 @@
overflow: hidden; overflow: hidden;
background-color: black; background-color: black;
color: white; color: white;
font-family: Atkinson Hyperlegible, sans-serif;
} }
main { main {
display: flex; display: flex;
@ -21,8 +22,7 @@
<main> <main>
<canvas id="canvas" width="1280" height="720"></canvas> <canvas id="canvas" width="1280" height="720"></canvas>
<div id="telemetry">XX.X FPS (XX.X ms)</div> <div id="telemetry">XX.X FPS (XX.X ms)</div>
<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>
<a class="nav-left" href="/002-webgl-engine">⇠ 002-webgl-engine</a> <nav><a class="nav-left" href="/002-webgl-engine">⇠ 002-webgl-engine</a></nav>
</nav>
</main> </main>
<script src="/003-scene/main.js" type="module"></script> <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; 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 { nav {
position: fixed; position: fixed;
z-index: 10; z-index: 10;

10
index.d.ts vendored
View file

@ -20,3 +20,13 @@ declare module "*.frag" {
const content: string; const content: string;
export default content; 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", "main": "./hack/build.ts",
"scripts": { "scripts": {
"build": "bun $BUNFLAGS .", "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", "serve": "serve ./html",
"dev": "run-p serve build:watch" "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 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 light = new Transform([1, 1, 0]);
const transform = new Transform(v3(0), etoq([0, 0, 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); quat.rotateY(transform.rotation, transform.rotation, 0.001);
}); });
new Renderable( setTimeout(() => {
app, new Renderable(
transform2, app,
new MeshRenderer(app, trianglething, basic(app), camera, light).configure({}) transform2,
); new MeshRenderer(app, trianglething, basic(app), camera, light).configure(
new Renderable( {}
app, )
transform, );
new MeshRenderer(app, teapot, 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 #version 300 es
precision highp float; 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 vec2 uv0;
in vec3 normal; in vec3 normal;
in vec4 vertex_color;
in vec3 light_pos; in vec3 light_pos;
out vec4 fragColor; 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() { void main() {
vec3 normal = normalize(normal); vec3 normal = normalize(normal);
float light = dot(normal, light_pos); 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", light0: "u_light_0",
light0Color: "u_light_0_color", light0Color: "u_light_0_color",
time: "u_time", 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;
uniform mat4 u_object_to_world_inv; uniform mat4 u_object_to_world_inv;
uniform vec3 u_light_0; uniform vec3 u_light_0;
uniform vec4 u_light_0_color; // uniform vec4 u_light_0_color;
uniform float u_time; // uniform float u_time;
// uniform vec4 u_albedo;
in vec4 a_vertex; in vec4 a_vertex;
in vec2 a_uv0; in vec2 a_uv0;

View file

@ -1,28 +1,12 @@
import { Mesh } from "../renderer/mesh"; import { Mesh } from "../renderer/mesh";
// prettier-ignore // 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({ export default new Mesh({
colors, colors: null,
faces, faces: new Uint8Array([0,1,2,0,3,1]),
name: "src/meshes/plane.ply", name: "src/meshes/plane.ply",
normals, normals: null,
positions, positions: new Float32Array([1,-1,0,-1,1,0,-1,-1,0,1,1,0]),
uvs, uvs: new Float32Array([1,0,0,1,0,0,1,1]),
vertexCount: 4 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"; import { Mesh } from "../renderer/mesh";
// prettier-ignore // 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({ export default new Mesh({
colors, 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, 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", name: "src/meshes/trianglething.ply",
normals, 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, 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, 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 vertexCount: 31
}); });

File diff suppressed because one or more lines are too long

View file

@ -11,6 +11,54 @@
display: none; 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 { nav {
position: fixed; position: fixed;
z-index: 10; z-index: 10;

View file

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

View file

@ -21,6 +21,8 @@ export class MeshRenderer extends Behavior {
color?: WebGLBuffer; color?: WebGLBuffer;
faces?: WebGLBuffer; faces?: WebGLBuffer;
} = {}; } = {};
faceDataType: number;
colorDataType: number | null;
constructor( constructor(
public app: WebGLApp, public app: WebGLApp,
@ -31,6 +33,24 @@ export class MeshRenderer extends Behavior {
public config: MeshRendererConfig = {} public config: MeshRendererConfig = {}
) { ) {
super(app); 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) { configure(config: MeshRendererConfig) {
@ -93,7 +113,7 @@ export class MeshRenderer extends Behavior {
this.buffers.color, this.buffers.color,
shaderMap.attributes.vertexColor, shaderMap.attributes.vertexColor,
4, 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( mat4.perspective(
this.projectionMatrix, this.projectionMatrix,
this.app.config.fov || 45, this.app.config.fov || 45,
@ -185,7 +210,7 @@ export class MeshRenderer extends Behavior {
gl.drawElements( gl.drawElements(
this.config.drawMode ?? gl.TRIANGLES, this.config.drawMode ?? gl.TRIANGLES,
this.mesh.config.faces.length, this.mesh.config.faces.length,
gl.UNSIGNED_INT, this.faceDataType,
0 0
); );

View file

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

View file

@ -1,5 +1,3 @@
import { mat4, vec3 } from "gl-matrix";
import { Transform } from "./transform";
import { WebGLApp } from "./webgl"; import { WebGLApp } from "./webgl";
/** /**
@ -20,17 +18,21 @@ export type ShaderMapping<
uv0: Attr; uv0: Attr;
normal: Attr; normal: Attr;
vertexColor: Attr; vertexColor: Attr;
material?: { [key: string]: Attr }; material?: { [key: string]: Attr };
}; };
uniforms: { uniforms: {
view: Uniform; albedo: Uniform;
projection: Uniform;
objectToWorld: Uniform;
objectToWorldInv: Uniform;
light0: Uniform; light0: Uniform;
light0Color: Uniform; light0Color: Uniform;
objectToWorld: Uniform;
objectToWorldInv: Uniform;
projection: Uniform;
texture0: Uniform;
texture1: Uniform;
time: Uniform; time: Uniform;
view: Uniform;
}; };
}; };
@ -89,13 +91,16 @@ export class Shader {
vertexColor: this.attrib(config.attributes.vertexColor), vertexColor: this.attrib(config.attributes.vertexColor),
}, },
uniforms: { uniforms: {
albedo: this.uniform(config.uniforms.albedo),
light0: this.uniform(config.uniforms.light0), light0: this.uniform(config.uniforms.light0),
light0Color: this.uniform(config.uniforms.light0Color), light0Color: this.uniform(config.uniforms.light0Color),
objectToWorld: this.uniform(config.uniforms.objectToWorld), objectToWorld: this.uniform(config.uniforms.objectToWorld),
objectToWorldInv: this.uniform(config.uniforms.objectToWorldInv), objectToWorldInv: this.uniform(config.uniforms.objectToWorldInv),
projection: this.uniform(config.uniforms.projection), 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), 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 frameTimes: number[] = [];
public maxFrameTimes: number = 100; public maxFrameTimes: number = 100;
public lastFrameTime: number = 0; public lastFrameTime: number = 0;
public activeTriangles: number = 0;
public activeVertexes: number = 0;
public activeRenderers: number = 0;
constructor( constructor(
public app: WebGLApp, public app: WebGLApp,
selector = "#telemetry" selector = "#telemetry"
@ -25,29 +29,50 @@ export class Telemetry extends Behavior {
} }
} }
onStart() { async onStart() {
this.lastFrameTime = 0; this.lastFrameTime = 0;
this.frameTimes = []; this.frameTimes = [];
// Send this to the end of onStart execution
setTimeout(() => this.setText(), 0);
setInterval(() => { setInterval(() => {
const averageFrameTime = this.setText();
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
}`;
}, 1001); }, 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) { onAfterUpdate(time: number) {
const frameTime = time - this.lastFrameTime; const frameTime = time - this.lastFrameTime;
this.insertTime(frameTime); this.insertTime(frameTime);
this.lastFrameTime = time; 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; zFar?: number;
}; };
export type RenderHandle = (time: number, app: WebGLApp) => void; export type RenderHandle = (
time: number,
app: WebGLApp
) => void | Promise<void>;
export class WebGLApp { export class WebGLApp {
public canvas: HTMLCanvasElement; public canvas: HTMLCanvasElement;
public telemetry?: Telemetry; public telemetry?: Telemetry;
public gl: WebGL2RenderingContext; public gl: WebGL2RenderingContext;
private loadingMessages: Set<string> = new Set(["[noeidelon] [stage 2]"]);
public registry: { public registry: {
onBeforeUpdate: RenderHandle[]; onBeforeUpdate: RenderHandle[];
@ -71,6 +75,18 @@ export class WebGLApp {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 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) { onBeforeUpdate(handle: RenderHandle) {
this.registry.onBeforeUpdate.push(handle); this.registry.onBeforeUpdate.push(handle);
} }
@ -99,18 +115,34 @@ export class WebGLApp {
this.registry.onDraw.forEach((handle) => handle(time, this)); 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.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) { async oneShot(time: number = 0) {
this.doStart(time); await this.doStart(time);
this.doUpdate(time); this.doUpdate(time);
} }
async start() { async start() {
this.doStart(); await this.doStart();
const run = (time: number) => { const run = (time: number) => {
this.doUpdate(time); this.doUpdate(time);