update some build/telemetry stuff
This commit is contained in:
parent
51f9f820d8
commit
0a67ccb040
25 changed files with 336 additions and 217 deletions
|
@ -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],
|
||||
|
|
|
@ -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}
|
||||
});
|
||||
`;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
@ -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
10
index.d.ts
vendored
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
},
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
@ -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
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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
17
src/renderer/texture.ts
Normal 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...");
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue