@chromatic-coherence/generative-engine 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +145 -130
- package/dist/shaders.d.ts +2 -2
- package/dist/shaders.js +405 -345
- package/dist/world.d.ts +19 -1
- package/dist/world.js +29 -6
- package/package.json +44 -44
package/dist/world.d.ts
CHANGED
|
@@ -91,6 +91,11 @@ export declare class World {
|
|
|
91
91
|
private pFaceI;
|
|
92
92
|
private pDepthI;
|
|
93
93
|
private instanced;
|
|
94
|
+
/** W9 — the one wind that blows through every swaying instanced batch */
|
|
95
|
+
wind: {
|
|
96
|
+
dir: V3;
|
|
97
|
+
speed: number;
|
|
98
|
+
};
|
|
94
99
|
private post;
|
|
95
100
|
private ink;
|
|
96
101
|
private bg;
|
|
@@ -243,7 +248,20 @@ export declare class World {
|
|
|
243
248
|
/** W8 — GPU instancing: upload a Mesh ONCE and draw it at every given transform in a
|
|
244
249
|
* single instanced call (scene + shadow pass alike). A forest is one draw. Instances
|
|
245
250
|
* ride their group's fade / morph / transform like any other geometry. */
|
|
246
|
-
meshInstanced(geo: Mesh, instances: (M4 | TransformSpec)[], o: FaceOpts
|
|
251
|
+
meshInstanced(geo: Mesh, instances: (M4 | TransformSpec)[], o: FaceOpts & {
|
|
252
|
+
/** W9 GPU wind: per-instance sway computed in the vertex stage (shadows included).
|
|
253
|
+
* amp scales with vertex height; freq in rad/s; phases auto-scatter per instance. */
|
|
254
|
+
sway?: {
|
|
255
|
+
amp: number;
|
|
256
|
+
freq?: number;
|
|
257
|
+
};
|
|
258
|
+
/** W10 GPU flight: the batch IS a murmuration — per-bird orbit params generated
|
|
259
|
+
* here, positions evaluated in the vertex stage from time alone. The instance
|
|
260
|
+
* matrices become the shared flock frame (place / scale / steer the whole flock). */
|
|
261
|
+
flight?: boolean | {
|
|
262
|
+
lobes?: number;
|
|
263
|
+
};
|
|
264
|
+
}): void;
|
|
247
265
|
grow(fn: GrowFn): void;
|
|
248
266
|
drawLine(a: V3, b: V3, color: string, alpha: number, width?: number): void;
|
|
249
267
|
drawPath(pts: {
|
package/dist/world.js
CHANGED
|
@@ -34,6 +34,8 @@ export class World {
|
|
|
34
34
|
}
|
|
35
35
|
constructor(o) {
|
|
36
36
|
this.instanced = [];
|
|
37
|
+
/** W9 — the one wind that blows through every swaying instanced batch */
|
|
38
|
+
this.wind = { dir: v3(1, 0, 0.35), speed: 1 };
|
|
37
39
|
this.ink = false;
|
|
38
40
|
this.bg = [0.024, 0.016, 0.055];
|
|
39
41
|
this.transparent = false;
|
|
@@ -392,15 +394,31 @@ export class World {
|
|
|
392
394
|
for (let i = 0; i < P.length; i += 9) {
|
|
393
395
|
this.pushFace(store, v3(P[i], P[i + 1], P[i + 2]), v3(P[i + 3], P[i + 4], P[i + 5]), v3(P[i + 6], P[i + 7], P[i + 8]), o, v3(N[i], N[i + 1], N[i + 2]), v3(N[i + 3], N[i + 4], N[i + 5]), v3(N[i + 6], N[i + 7], N[i + 8]));
|
|
394
396
|
}
|
|
395
|
-
const mats = new Float32Array(instances.length *
|
|
396
|
-
|
|
397
|
+
const mats = new Float32Array(instances.length * 20); // mat4 + sway vec4, one stride
|
|
398
|
+
const lobes = typeof o.flight === "object" ? (o.flight.lobes ?? 3) : 3;
|
|
399
|
+
instances.forEach((m, i) => {
|
|
400
|
+
mats.set(m instanceof Float32Array ? m : mCompose(m), i * 20);
|
|
401
|
+
const ph = ((i * 2654435761) % 6283) / 1000; // scattered phase
|
|
402
|
+
if (o.flight) { // aIP = (a0, r0, ph, lobe)
|
|
403
|
+
mats[i * 20 + 16] = ((i * 40503) % 6283) / 1000;
|
|
404
|
+
mats[i * 20 + 17] = 40 + ((i * 9973) % 1000) / 5;
|
|
405
|
+
mats[i * 20 + 18] = ph;
|
|
406
|
+
mats[i * 20 + 19] = i % lobes;
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
mats[i * 20 + 16] = ph;
|
|
410
|
+
mats[i * 20 + 17] = (o.sway?.freq ?? 1.3) * (0.85 + ((i * 97) % 30) / 100);
|
|
411
|
+
mats[i * 20 + 18] = (o.sway?.amp ?? 0) * 0.01;
|
|
412
|
+
mats[i * 20 + 19] = 0;
|
|
413
|
+
}
|
|
414
|
+
});
|
|
397
415
|
const vbuf = gl.createBuffer();
|
|
398
416
|
gl.bindBuffer(gl.ARRAY_BUFFER, vbuf);
|
|
399
417
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(store), gl.STATIC_DRAW);
|
|
400
418
|
const ibuf = gl.createBuffer();
|
|
401
419
|
gl.bindBuffer(gl.ARRAY_BUFFER, ibuf);
|
|
402
420
|
gl.bufferData(gl.ARRAY_BUFFER, mats, gl.STATIC_DRAW);
|
|
403
|
-
this.instanced.push({ vbuf, ibuf, verts: store.length / FACE_STRIDE, count: instances.length });
|
|
421
|
+
this.instanced.push({ vbuf, ibuf, verts: store.length / FACE_STRIDE, count: instances.length, flight: !!o.flight });
|
|
404
422
|
}
|
|
405
423
|
grow(fn) { this.hooks.push(fn); }
|
|
406
424
|
// ── the living verbs (gathered per frame) ──
|
|
@@ -602,6 +620,7 @@ export class World {
|
|
|
602
620
|
return;
|
|
603
621
|
const gl = this.gl;
|
|
604
622
|
for (const rec of this.instanced) {
|
|
623
|
+
gl.uniform1f(p.u("uFlight"), rec.flight ? 1 : 0);
|
|
605
624
|
gl.bindBuffer(gl.ARRAY_BUFFER, rec.vbuf);
|
|
606
625
|
this.attrib(p, "aPos", 3, FACE_STRIDE, 0);
|
|
607
626
|
if (!depthOnly) {
|
|
@@ -615,12 +634,12 @@ export class World {
|
|
|
615
634
|
this.attrib(p, "aNorm2", 3, FACE_STRIDE, 15);
|
|
616
635
|
gl.bindBuffer(gl.ARRAY_BUFFER, rec.ibuf);
|
|
617
636
|
const locs = [];
|
|
618
|
-
for (let k = 0; k <
|
|
619
|
-
const loc = gl.getAttribLocation(p.prog, "aI" + k);
|
|
637
|
+
for (let k = 0; k < 5; k++) { // aI0..3 = the matrix, aIP = the sway params
|
|
638
|
+
const loc = gl.getAttribLocation(p.prog, k < 4 ? "aI" + k : "aIP");
|
|
620
639
|
if (loc < 0)
|
|
621
640
|
continue;
|
|
622
641
|
gl.enableVertexAttribArray(loc);
|
|
623
|
-
gl.vertexAttribPointer(loc, 4, gl.FLOAT, false,
|
|
642
|
+
gl.vertexAttribPointer(loc, 4, gl.FLOAT, false, 80, k * 16);
|
|
624
643
|
gl.vertexAttribDivisor(loc, 1);
|
|
625
644
|
locs.push(loc);
|
|
626
645
|
}
|
|
@@ -716,6 +735,8 @@ export class World {
|
|
|
716
735
|
if (this.instanced.length) {
|
|
717
736
|
this.pDepthI.use();
|
|
718
737
|
gl.uniformMatrix4fv(this.pDepthI.u("uVP"), false, this.svp);
|
|
738
|
+
gl.uniform1f(this.pDepthI.u("uT"), t * this.wind.speed);
|
|
739
|
+
gl.uniform3f(this.pDepthI.u("uWindDir"), this.wind.dir.x, this.wind.dir.y, this.wind.dir.z);
|
|
719
740
|
this.setGroups(this.pDepthI);
|
|
720
741
|
this.drawInstancedAll(this.pDepthI, true);
|
|
721
742
|
}
|
|
@@ -747,6 +768,8 @@ export class World {
|
|
|
747
768
|
this.pFaceI.use();
|
|
748
769
|
this.setVP(this.pFaceI);
|
|
749
770
|
this.setLights(this.pFaceI, fogK);
|
|
771
|
+
gl.uniform1f(this.pFaceI.u("uT"), t * this.wind.speed);
|
|
772
|
+
gl.uniform3f(this.pFaceI.u("uWindDir"), this.wind.dir.x, this.wind.dir.y, this.wind.dir.z);
|
|
750
773
|
this.drawInstancedAll(this.pFaceI, false);
|
|
751
774
|
}
|
|
752
775
|
// the light — additive, depth-TESTED but not written (ink: normal alpha blend)
|
package/package.json
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@chromatic-coherence/generative-engine",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "THE THIRD ENGINE — a zero-dependency WebGL2 graphics engine grown from generative-charts-3d: HDR + bloom + SSAO post chain, hardware-PCF shadow maps, a geometry stdlib, ribbon strokes, group transforms and morph targets. The charts API rides on top unchanged.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./dist/index.js",
|
|
7
|
-
"module": "./dist/index.js",
|
|
8
|
-
"types": "./dist/index.d.ts",
|
|
9
|
-
"exports": {
|
|
10
|
-
".": {
|
|
11
|
-
"types": "./dist/index.d.ts",
|
|
12
|
-
"import": "./dist/index.js"
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
"files": [
|
|
16
|
-
"dist",
|
|
17
|
-
"README.md",
|
|
18
|
-
"LICENSE"
|
|
19
|
-
],
|
|
20
|
-
"sideEffects": false,
|
|
21
|
-
"publishConfig": {
|
|
22
|
-
"access": "public"
|
|
23
|
-
},
|
|
24
|
-
"scripts": {
|
|
25
|
-
"build": "tsc -p tsconfig.json",
|
|
26
|
-
"test": "node test/run.mjs",
|
|
27
|
-
"prepublishOnly": "npm run build"
|
|
28
|
-
},
|
|
29
|
-
"keywords": [
|
|
30
|
-
"3d",
|
|
31
|
-
"webgl2",
|
|
32
|
-
"engine",
|
|
33
|
-
"graphics",
|
|
34
|
-
"bloom",
|
|
35
|
-
"ssao",
|
|
36
|
-
"shadows",
|
|
37
|
-
"zero-dependency"
|
|
38
|
-
],
|
|
39
|
-
"author": "Chromatic Coherence",
|
|
40
|
-
"license": "SEE LICENSE IN LICENSE",
|
|
41
|
-
"devDependencies": {
|
|
42
|
-
"typescript": "^5"
|
|
43
|
-
}
|
|
44
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@chromatic-coherence/generative-engine",
|
|
3
|
+
"version": "1.4.0",
|
|
4
|
+
"description": "THE THIRD ENGINE — a zero-dependency WebGL2 graphics engine grown from generative-charts-3d: HDR + bloom + SSAO post chain, hardware-PCF shadow maps, a geometry stdlib, ribbon strokes, group transforms and morph targets. The charts API rides on top unchanged.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE"
|
|
19
|
+
],
|
|
20
|
+
"sideEffects": false,
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc -p tsconfig.json",
|
|
26
|
+
"test": "node test/run.mjs",
|
|
27
|
+
"prepublishOnly": "npm run build"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"3d",
|
|
31
|
+
"webgl2",
|
|
32
|
+
"engine",
|
|
33
|
+
"graphics",
|
|
34
|
+
"bloom",
|
|
35
|
+
"ssao",
|
|
36
|
+
"shadows",
|
|
37
|
+
"zero-dependency"
|
|
38
|
+
],
|
|
39
|
+
"author": "Chromatic Coherence",
|
|
40
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"typescript": "^5"
|
|
43
|
+
}
|
|
44
|
+
}
|