switch to bun build instead of statics

This commit is contained in:
41666 2023-10-03 00:17:15 -04:00
parent 8cbe93d74d
commit adc3a38395
26 changed files with 357 additions and 230 deletions

View file

@ -1,31 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8" />
<title>com.mekanoe.art // 001-platform-provenance</title>
<style>
html,
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: black;
color: white;
}
main {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
</style>
<link rel="stylesheet" href="work.css" />
<main>
<canvas id="canvas" width="1280" height="720"></canvas>
<div id="telemetry">XX.X FPS (XX.X ms)</div>
</main>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/3.4.2/gl-matrix-min.min.js"
integrity="sha512-cR3oS5mKRWD+38vYi1CNJk1DLpi104ovuQBuVv9p7nNxeqzSNiHzlboK2BZQybmpTi1QNnQ5unYajpURcMjeZQ=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
<script src="/001-platform-provenance.js" type="module"></script>

View file

@ -1,71 +0,0 @@
import { Shader } from "./lib/shader.js";
import { BasicPlane } from "./lib/basic-plane.js";
import { App } from "./lib/app.js";
const app = new App({ fov: 20 });
const gl = app.gl;
const shader = new Shader(app)
.attach(
gl.VERTEX_SHADER,
`
attribute vec4 aVertexPosition;
attribute vec2 aTextureCoord;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
varying highp vec2 vTextureCoord;
void main() {
gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
vTextureCoord = aTextureCoord;
}
`
)
.attach(
gl.FRAGMENT_SHADER,
`
precision highp float;
uniform float uTime;
uniform float uSinTime;
uniform float uCosTime;
varying highp vec2 vTextureCoord;
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() {
float zComponent = uSinTime * 0.001 * 0.5 + 0.5;
vec3 hsv = rgb2hsv(vec3(vTextureCoord, zComponent));
hsv.x += uTime * 0.0001;
hsv.y = 1.0;
hsv.z = 1.0;
vec3 rgb = hsv2rgb(hsv);
gl_FragColor = vec4(rgb, 1.0);
gl_FragColor = clamp(gl_FragColor, 0.0, 1.0);
}
`
)
.link();
const plane = new BasicPlane(app);
plane.attachShader(shader);
app.loop();

View file

@ -1,31 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8" />
<title>com.mekanoe.art // 002-rainbow-trinity</title>
<style>
html,
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: black;
color: white;
}
main {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
</style>
<link rel="stylesheet" href="work.css" />
<main>
<canvas id="canvas" width="1280" height="720"></canvas>
<div id="telemetry">XX.X FPS (XX.X ms)</div>
</main>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/3.4.2/gl-matrix-min.min.js"
integrity="sha512-cR3oS5mKRWD+38vYi1CNJk1DLpi104ovuQBuVv9p7nNxeqzSNiHzlboK2BZQybmpTi1QNnQ5unYajpURcMjeZQ=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
<script src="/002-rainbow-trinity.js" type="module"></script>

View file

@ -1,74 +0,0 @@
import { Shader, colorUtils, commonFrag, commonVert } from "./lib/shader.js";
import { BasicPlane } from "./lib/basic-plane.js";
import { App } from "./lib/app.js";
const app = new App({ fov: 20 });
const gl = app.gl;
const shader = new Shader(app)
.attach(
gl.VERTEX_SHADER,
`
${commonVert}
varying highp vec2 vTextureCoord;
void main() {
gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
vTextureCoord = aTextureCoord;
}
`
)
.attach(
gl.FRAGMENT_SHADER,
`
${commonFrag}
${colorUtils}
varying highp vec2 vTextureCoord;
vec3 circle(vec2 pos, vec3 color) {
float radius = 0.75;
float dist = length(pos);
float circle = smoothstep(radius + 0.001, radius, dist);
return color * vec3(1.0 - circle);
}
vec3 colorRotator(vec3 color, float phase, vec2 uv) {
color.x += uSinTime * 0.0001 + uv.y;
vec3 hsv = rgb2hsv(color);
hsv.x += uSinTime * 0.001 * uv.y - phase;
hsv.y = 1.0;
hsv.z = 0.5;
vec3 rgb = hsv2rgb(hsv);
return rgb;
}
void main() {
float value = sin(uTime * 0.00025) * 0.5 + 0.5;
vec2 sv = vec2(1.0, 1.0);
vec3 triUpper = hsv2rgb(vec3(value, sv));
vec3 triLeft = hsv2rgb(vec3(value + 0.33, sv));
vec3 triRight = hsv2rgb(vec3(value + 0.66, sv));
vec2 uv = vTextureCoord * 2.0 - 1.0;
vec3 color = vec3(0.0);
// place 3 circles in a triangle
color += circle(vec2(uv.x, uv.y + 0.5), colorRotator(triUpper, 1.0, uv));
color += circle(vec2(uv.x - 0.5, uv.y - 0.33), colorRotator(triLeft, 0.667, uv));
color += circle(vec2(uv.x + 0.5, uv.y - 0.33), colorRotator(triRight, 0.333, uv));
// color = 1.0 - color;
gl_FragColor = vec4(color, 1.0);
gl_FragColor = clamp(gl_FragColor, 0.0, 1.0);
}
`
)
.link();
const plane = new BasicPlane(app);
plane.attachShader(shader);
app.loop();

View file

@ -1,52 +0,0 @@
* {
box-sizing: border-box;
transition: all 0.2s ease-in-out;
}
header {
display: flex;
font-size: 2.5rem;
align-items: center;
& .subtext {
font-size: 1rem;
margin-left: 0.5rem;
color: hsl(39, 68.6%, 31.2%);
& a:hover {
color: hsl(39, 100%, 80%);
}
}
}
a {
color: inherit;
text-decoration: none;
}
ul {
list-style: none;
padding: 0;
margin: 0;
padding-left: 3rem;
display: flex;
flex-direction: column;
font-size: 1.5rem;
}
li {
& a {
text-decoration: underline;
text-decoration-color: transparent;
}
&:hover {
color: hsl(39, 100%, 80%);
& a {
text-decoration-color: inherit;
}
}
&::before {
content: "▸";
margin-right: 0.5rem;
}
}

View file

@ -1,37 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8" />
<title>com.mekanoe.art //</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible&display=swap"
rel="stylesheet"
/>
<style>
html,
body {
font-family: "Atkinson Hyperlegible", sans-serif;
background-color: hsl(32, 19%, 14%);
color: hsl(39, 75%, 51%);
line-height: 1.5;
text-shadow: 1px 1px 3px hsl(38, 45%, 22%);
}
</style>
<link rel="stylesheet" href="index.css" />
<main>
<header>
<div>com.mekanoe.art //</div>
<div class="subtext">
<< noeidelon >>
<a href="https://github.com/mekanoe/noeidelon">[github]</a>
<a href="https://sapphic.engineer/noe" rel="me">[fedi]</a>
<br />a collection of 3D works
</div>
</header>
<section id="works">
<ul>
<li><a href="/002-rainbow-trinity">./002-rainbow-trinity</a></li>
<li><a href="/001-platform-provenance">./001-platform-provenance</a></li>
</ul>
</section>
</main>

View file

@ -1,122 +0,0 @@
import { Telemetry } from "./telemetry.js";
export class App {
constructor(
config = {
fov: 45,
}
) {
this._now = 0;
this.registry = {
onStart: [],
onUpdate: [],
onBeforeUpdate: [],
onAfterUpdate: [],
};
this.config = config;
this.canvas = document.querySelector("canvas");
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
this.gl = this.canvas.getContext("webgl2");
if (this.gl === null) {
document.querySelector(
"main"
).innerHTML = `<div><i>your browser didn't let me set up webgl</i></div>`;
throw new Error(
"Unable to initialize WebGL. Your browser or machine may not support it."
);
}
const gl = this.gl;
const fieldOfView = (this.config.fov * Math.PI) / 180; // in radians
const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
const zNear = 0.1;
const zFar = 100.0;
const projectionMatrix = glMatrix.mat4.create();
glMatrix.mat4.perspective(
projectionMatrix,
fieldOfView,
aspect,
zNear,
zFar
);
const modelViewMatrix = glMatrix.mat4.create();
glMatrix.mat4.translate(
modelViewMatrix,
modelViewMatrix,
[-0.0, 0.0, -6.0]
);
this.projectionMatrix = projectionMatrix;
this.modelViewMatrix = modelViewMatrix;
this.clear();
this.onBeforeUpdate(() => this.clear());
this.telemetry = new Telemetry(this);
}
clear() {
const gl = this.gl;
gl.clearColor(0.0, 0.0, 0.0, 1.0); // Clear to black, fully opaque
gl.clearDepth(1.0); // Clear everything
gl.enable(gl.DEPTH_TEST); // Enable depth testing
gl.depthFunc(gl.LEQUAL); // Near things obscure far things
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
}
onStart(fn) {
this.registry.onStart.push(fn);
}
onUpdate(fn) {
this.registry.onUpdate.push(fn);
}
onBeforeUpdate(fn) {
this.registry.onBeforeUpdate.push(fn);
}
onAfterUpdate(fn) {
this.registry.onAfterUpdate.push(fn);
}
start() {
this.registry.onStart.forEach((fn) => fn(this));
}
update() {
this.registry.onBeforeUpdate.forEach((fn) => fn(this));
this.registry.onUpdate.forEach((fn) => fn(this));
this.registry.onAfterUpdate.forEach((fn) => fn(this));
}
oneShot() {
requestAnimationFrame((now) => {
this._now = now;
this.start();
this.update();
});
}
loop() {
const run = (now) => {
this._now = now;
this.update();
requestAnimationFrame(run);
};
requestAnimationFrame((now) => {
run(now);
});
}
now() {
return this._now;
}
}

View file

@ -1,17 +0,0 @@
import { Object } from "./object.js";
export class BasicPlane extends Object {
constructor(app) {
super(app);
this.vertexPositions = new Float32Array([
-1.0, -1.0, +1.0, -1.0, -1.0, +1.0, +1.0, +1.0,
]);
this.positionBuffer = this.initBuffer(this.vertexPositions);
this.textureBuffer = this.initBuffer(
new Float32Array([0, 0, 1, 0, 0, 1, 1, 1])
);
this.app.onUpdate(() => this.draw2D());
}
}

View file

@ -1,68 +0,0 @@
export class Object {
constructor(app) {
this.gl = app.gl;
this.app = app;
this.vertexPositions = new Float32Array([]);
this.positionBuffer = null;
this.textureBuffer = null;
}
initBuffer(data, draw = this.gl.STATIC_DRAW) {
const buffer = this.gl.createBuffer();
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer);
this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(data), draw);
return buffer;
}
attachShader(shader) {
this.shader = shader;
this.vertexPosition = shader.location("aVertexPosition");
this.textureCoord = shader.location("aTextureCoord");
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionBuffer);
this.gl.vertexAttribPointer(
this.vertexPosition,
2,
this.gl.FLOAT,
false,
0,
0
);
this.gl.enableVertexAttribArray(this.vertexPosition);
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.textureBuffer);
this.gl.vertexAttribPointer(
this.textureCoord,
2,
this.gl.FLOAT,
false,
0,
0
);
this.gl.enableVertexAttribArray(this.textureCoord);
return this;
}
draw2D() {
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionBuffer);
this.shader.activate(this.app.projectionMatrix, this.app.modelViewMatrix);
this.gl.drawArrays(
this.gl.TRIANGLE_STRIP,
0,
this.vertexPositions.length / 2
);
}
draw3D() {
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionBuffer);
this.shader.activate(this.app.projectionMatrix, this.app.modelViewMatrix);
this.gl.drawArrays(
this.gl.TRIANGLE_STRIP,
0,
this.vertexPositions.length / 3
);
}
}

View file

@ -1,107 +0,0 @@
export class Shader {
constructor(app) {
this.gl = app.gl;
this.app = app;
this.program = this.gl.createProgram();
}
attach(type, source) {
console.log("attaching shader", { type, source });
const shader = this.gl.createShader(type);
this.gl.shaderSource(shader, source);
this.gl.compileShader(shader);
if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
throw new Error(
"An error occurred compiling the shaders: " +
this.gl.getShaderInfoLog(shader)
);
}
this.gl.attachShader(this.program, shader);
return this;
}
link() {
this.gl.linkProgram(this.program);
if (!this.gl.getProgramParameter(this.program, this.gl.LINK_STATUS)) {
throw new Error(
"Unable to initialize the shader program: " +
this.gl.getProgramInfoLog(this.program)
);
}
console.log("shader linked");
return this;
}
location(name) {
if (name[0] === "a") {
return this.gl.getAttribLocation(this.program, name);
} else if (name[0] === "u") {
return this.gl.getUniformLocation(this.program, name);
}
}
updateTime() {
const time = this.app.now();
const sinTime = Math.sin(time);
const cosTime = Math.cos(time);
this.gl.uniform1f(this.location("uTime"), time);
this.gl.uniform1f(this.location("uSinTime"), sinTime);
this.gl.uniform1f(this.location("uCosTime"), cosTime);
}
activate(projectionMatrix, modelViewMatrix) {
this.gl.useProgram(this.program);
this.gl.uniformMatrix4fv(
this.location("uProjectionMatrix"),
false,
projectionMatrix
);
this.gl.uniformMatrix4fv(
this.location("uModelViewMatrix"),
false,
modelViewMatrix
);
this.updateTime();
}
}
export const colorUtils = `
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);
}
`;
export const commonFrag = `
precision highp float;
uniform float uTime;
uniform float uSinTime;
uniform float uCosTime;
`;
export const commonVert = `
attribute vec4 aVertexPosition;
attribute vec2 aTextureCoord;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
`;

View file

@ -1,43 +0,0 @@
export class Telemetry {
constructor(app, selector = "#telemetry") {
this.app = app;
this.el = document.querySelector(selector);
if (this.el && location.search.includes("telemetry")) {
this.el.style.display = "block";
this.app.onAfterUpdate(() => this.onAfterUpdate());
}
this.frameTimes = [];
this.maxFrameTimes = 100;
this.lastFrameTime = 0;
}
insertTime(time) {
this.frameTimes.push(time);
if (this.frameTimes.length > this.maxFrameTimes) {
this.frameTimes.shift();
}
}
onAfterUpdate() {
const frameTime = this.app.now() - this.lastFrameTime;
this.insertTime(frameTime);
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.lastFrameTime = this.app.now();
}
}

View file

@ -1,12 +0,0 @@
#telemetry {
position: absolute;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.5);
color: white;
font: monospace;
z-index: 100;
padding: 10px;
font-size: 12px;
display: none;
}