Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ad1f355
Move FES module out of core
limzykenneth Apr 9, 2026
2866dbc
Refactor and clean up
limzykenneth Apr 9, 2026
f5b7595
Work in progress proof of concept FES revamp using new translation
limzykenneth Apr 25, 2026
e0ea5e8
Implement new FES message printing for sketch verifier
limzykenneth May 2, 2026
81626e8
Refactor to not have functions attached to p5 unnecessarily
limzykenneth May 2, 2026
6e8052b
Use new FES instead of friendly file error
limzykenneth May 12, 2026
9875ee4
Replace all uses of old translator
limzykenneth May 12, 2026
cd5df86
Use zod/mini to save some bytes
limzykenneth May 13, 2026
190cc4a
Clean up unused code
limzykenneth May 15, 2026
b4e2bf7
More refactor to detangle spaghetti
limzykenneth May 21, 2026
ebc8a26
Fix stacktrace not printing correctly
limzykenneth May 23, 2026
367c3ac
Zod didn't have that much information in its error to make suggestion
limzykenneth May 23, 2026
0fa5cba
Still trying to make things simpler
limzykenneth May 28, 2026
99786b2
Consolidate top level use error with fes error monitor
limzykenneth May 30, 2026
f58c00d
Remove references to blocking error in FES
limzykenneth May 30, 2026
ddd8779
Implement a more minimal interface for FES message logging
limzykenneth Jun 4, 2026
ef8a76b
Rework styling API to fix translation not working properly
limzykenneth Jun 6, 2026
dde0fd0
Proof of concept mechanism for loading translations
limzykenneth Jun 6, 2026
59acb84
Implement low level API to extend parameter validation
limzykenneth Jun 7, 2026
bea3867
Centralise entry points definition
limzykenneth Jun 8, 2026
5c5da11
Swap translation package to use NPM registry version
limzykenneth Jun 9, 2026
cde4952
Merge branch 'dev-2.0' into modular-fes
limzykenneth Jun 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
"libtess": "^1.2.2",
"omggif": "^1.0.10",
"pako": "^2.1.0",
"zod": "^4.2.1"
"zod": "^4.2.1",
"tl-util": "npm:@limzykenneth/tl-util@0.0.1"
},
"devDependencies": {
"@eslint/compat": "^1.2.9",
Expand Down
237 changes: 7 additions & 230 deletions preview/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,241 +18,18 @@
<body>
<script type="module">
import p5 from '../src/app.js';
import rendererWebGPU from '../src/webgpu/p5.RendererWebGPU.js';

p5.registerAddon(rendererWebGPU);

const sketch = function (p) {
let fbo;
let sh, sh2;
let ssh;
let tex;
let font;
let redFilter;
let env;
let instance;

// Compute shader variables
let computeShader;
let particleBuffer;
let bouncingCirclesShader;
let circleGeometry;
const NUM_CIRCLES = 100;
const RADIUS = 2;

p.setup = async function () {
await p.createCanvas(400, 400, p.WEBGPU);
env = await p.loadImage('img/spheremap.jpg');
font = await p.loadFont(
'font/PlayfairDisplay.ttf'
);
fbo = p.createFramebuffer();

instance = p.buildGeometry(() => p.sphere(5));
circleGeometry = p.buildGeometry(() => p.sphere(RADIUS));

redFilter = p.baseFilterShader().modify(() => {
p.getColor((inputs, canvasContent) => {
let col = p.getTexture(canvasContent, inputs.texCoord);
col.g = col.r;
col.b = col.r;
return col;
})
}, { p })

tex = p.createImage(100, 100);
tex.loadPixels();
for (let x = 0; x < tex.width; x++) {
for (let y = 0; y < tex.height; y++) {
const off = (x + y * tex.width) * 4;
tex.pixels[off] = p.round((x / tex.width) * 255);
tex.pixels[off + 1] = p.round((y / tex.height) * 255);
tex.pixels[off + 2] = 0;
tex.pixels[off + 3] = 255;
}
}
tex.updatePixels();
fbo.draw(() => {
p.imageMode(p.CENTER);
p.image(tex, 0, 0, p.width, p.height);
});

sh = p.baseMaterialShader().modify(() => {
const time = p.uniformFloat(() => p.millis());
p.getWorldInputs((inputs) => {
inputs.position.y += 40 * p.sin(time * 0.005);
return inputs;
});
}, { p })
sh2 = p.baseMaterialShader().modify(() => {
p.getWorldInputs((inputs) => {
inputs.position.x += 20 * p.instanceID();
return inputs;
});
}, { p })

// Initialize storage buffers with random positions and velocities
const initialParticles = [];
for (let i = 0; i < NUM_CIRCLES; i++) {
initialParticles.push({
position: [p.random(-150, 150), p.random(-150, 150)],
velocity: [
0.1 * p.random(1, 3) * (p.random() > 0.5 ? 1 : -1),
0.1 * p.random(1, 3) * (p.random() > 0.5 ? 1 : -1)
]
})
}

particleBuffer = p.createStorage(initialParticles);

// Create compute shader for physics simulation
computeShader = p.buildComputeShader(() => {
const particles = p.uniformStorage('particles', particleBuffer);
const bounds = p.uniformVec2(() => [p.width / 2 - RADIUS, p.height / 2 - RADIUS]);
const deltaTime = p.uniformFloat(() => p.deltaTime * 0.1);

const idx = p.index.x;

// Read current position and velocity
let position = particles[idx].position;
let velocity = particles[idx].velocity;

// Update position
position += velocity * deltaTime;

// Bounce off boundaries
if (position.x > bounds.x || position.x < -bounds.x) {
velocity.x = -velocity.x;
position.x = p.clamp(position.x, -bounds.x, bounds.x);
}
if (position.y > bounds.y || position.y < -bounds.y) {
velocity.y = -velocity.y;
position.y = p.clamp(position.y, -bounds.y, bounds.y);
}

particles[idx].position = position;
particles[idx].velocity = velocity;
}, { p, RADIUS, particleBuffer });

// Shader for rendering bouncing circles from storage buffer
bouncingCirclesShader = p.baseMaterialShader().modify(() => {
const particles = p.uniformStorage('particles', particleBuffer);

p.getWorldInputs((inputs) => {
const instanceIdx = p.instanceID();
inputs.position.xy += particles[instanceIdx].position;
return inputs;
});
}, { p, particleBuffer });
p.setup = function () {
p.createCanvas(400, 400);
p.noLoop();
};

p.draw = function () {
// Run compute shader to update physics
debugger
p.compute(computeShader, NUM_CIRCLES);

p.clear();
p.rotateY(p.millis() * 0.001);
p.push();
//p.clip(() => p.rect(-50, -50, 200, 200));
/*p.orbitControl();
p.push();
p.textAlign(p.CENTER, p.CENTER);
p.textFont(font);
p.textSize(85)
p.fill('red')
p.noStroke()
p.rect(0, 0, 100, 100);
p.fill(0);
p.push()
p.rotate(p.millis() * 0.001)
p.text('Hello!', 0, 0);
p.pop()
p.pop();
return;*/
p.orbitControl();
const t = p.millis() * 0.002;
p.background(200);
p.panorama(env);
p.push();
p.imageLight(env);
p.shader(sh);
// p.strokeShader(ssh)
p.ambientLight(10);
//p.directionalLight(100, 100, 100, 0, 1, -1);
//p.pointLight(155, 155, 155, 0, -200, 500);
p.specularMaterial(255);
p.shininess(50);
p.metalness(100);
//p.stroke('white');
p.noStroke();
for (const [i, c] of ['red', 'gray', 'blue'].entries()) {
p.push();
p.fill(c);
p.translate(
p.width/3 * p.sin(t + i * Math.E),
0, //p.width/3 * p.sin(t * 0.9 + i * Math.E + 0.2),
p.width/3 * p.sin(t * 1.2 + i * Math.E + 0.3),
)
if (i % 2 === 0) {
if (i === 0) {
p.texture(fbo)
}
p.box(30);
} else {
p.sphere(30);
}
p.pop();
}
p.pop();

p.push();
p.shader(sh2);
p.noStroke();
p.fill('red');
p.model(instance, 10);
p.pop();

// Draw compute shader-driven bouncing circles
p.push();
p.shader(bouncingCirclesShader);
p.noStroke();
p.fill('#4ECDC4');
p.model(circleGeometry, NUM_CIRCLES);
p.pop();

// Test beginShape/endShape with immediate mode shapes
p.push();
p.translate(0, 100, 0);
p.fill('yellow');
p.noStroke();

// Draw a circle using beginShape/endShape
p.beginShape();
const numPoints = 16;
for (let i = 0; i < numPoints; i++) {
const angle = (i / numPoints) * Math.PI * 2;
const x = Math.cos(angle) * 50;
const y = Math.sin(angle) * 50;
p.vertex(x, y);
}
p.endShape(p.CLOSE);

p.translate(100, 0, 0);
p.fill('purple');

// Draw a square using beginShape/endShape
p.beginShape();
p.vertex(-30, -30);
p.vertex(30, -30);
p.vertex(30, 30);
p.vertex(-30, 30);
p.endShape(p.CLOSE);

p.pop();

// p.filter(p.BLUR, 10)
p.pop();
p.background(220);
p.fill(false);
p.line(0);
p.ellipse(200, 200, 100, 100);
};
};

Expand Down
7 changes: 3 additions & 4 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ color(p5);

// core
// currently, it only contains the test for parameter validation
import friendlyErrors from './core/friendly_errors';
import friendlyErrors from './friendly_errors';
friendlyErrors(p5);

// data
Expand Down Expand Up @@ -60,8 +60,7 @@ p5.registerAddon(shader);
import strands from './strands/p5.strands';
p5.registerAddon(strands);

import { waitForDocumentReady, waitingForTranslator, _globalInit } from './core/init';
Promise.all([waitForDocumentReady(), waitingForTranslator]).then(_globalInit);
import { waitForDocumentReady, _globalInit } from './core/init';
waitForDocumentReady().then(_globalInit);

export default p5;

Loading
Loading