pixi-effects 0.41.0 → 0.43.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/CHANGELOG.md +16 -0
- package/README.md +5 -5
- package/ai/chat-template.html +3 -3
- package/dist/{Base-Jgkud1Aw.d.ts → Base-DKFQtqzW.d.ts} +1 -1
- package/dist/{Base-DQWIJ6bJ.d.cts → Base-lb5Uhaqu.d.cts} +1 -1
- package/dist/Controller.d.cts +2 -2
- package/dist/Controller.d.ts +2 -2
- package/dist/{Movie-CwqRLOzE.d.ts → Movie-B_qQIYV6.d.ts} +47 -4
- package/dist/{Movie-DWtxRiJ2.d.cts → Movie-BdUm2Mc9.d.cts} +47 -4
- package/dist/{chunk-Y2N6U3X5.js → chunk-6N5ZBUOU.js} +169 -8
- package/dist/chunk-6N5ZBUOU.js.map +1 -0
- package/dist/{chunk-RN5FWGGM.cjs → chunk-BEGOKE7Q.cjs} +169 -8
- package/dist/chunk-BEGOKE7Q.cjs.map +1 -0
- package/dist/index.cjs +25 -25
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +1 -1
- package/dist/loader.css +1 -1
- package/dist/present.cjs +1 -1
- package/dist/present.d.cts +2 -2
- package/dist/present.d.ts +2 -2
- package/dist/present.js +1 -1
- package/dist/three.cjs +115 -24
- package/dist/three.cjs.map +1 -1
- package/dist/three.d.cts +28 -2
- package/dist/three.d.ts +28 -2
- package/dist/three.js +117 -26
- package/dist/three.js.map +1 -1
- package/dist/{types-DIh93lFb.d.cts → types-DiNHtdrS.d.cts} +19 -0
- package/dist/{types-DIh93lFb.d.ts → types-DiNHtdrS.d.ts} +19 -0
- package/docs/api.md +23 -3
- package/docs/dsl.md +3 -2
- package/llms-full.txt +147 -17
- package/package.json +2 -1
- package/skills/pixi-effects/SKILL.md +2 -1
- package/skills/pixi-effects/reference/cheatsheet.md +2 -0
- package/skills/pixi-effects/reference/recipes.md +117 -11
- package/skills/pixi-effects/template.html +6 -6
- package/dist/chunk-RN5FWGGM.cjs.map +0 -1
- package/dist/chunk-Y2N6U3X5.js.map +0 -1
package/dist/three.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Sequence, buildScope, evaluateExpr, registerSequenceType } from './chunk-4QVQ5UJJ.js';
|
|
2
2
|
import './chunk-32MMNDDN.js';
|
|
3
3
|
import './chunk-BXOCEZ4U.js';
|
|
4
|
-
import { Texture, Sprite } from 'pixi.js';
|
|
5
|
-
import { WebGLRenderer, Scene, PerspectiveCamera, Raycaster, Vector2, Box3,
|
|
4
|
+
import { Texture, Sprite, TextureSource } from 'pixi.js';
|
|
5
|
+
import { WebGLRenderer, Scene, PerspectiveCamera, Raycaster, Vector2, Vector3, Quaternion, Plane, Box3, RenderTarget, Group, AnimationMixer, LoopOnce, LoopRepeat, AmbientLight, DirectionalLight, SpotLight, PointLight, Color, SRGBColorSpace, Fog } from 'three';
|
|
6
6
|
|
|
7
7
|
// src/three/defaults.ts
|
|
8
8
|
var pageRenderer = "webgl";
|
|
@@ -159,7 +159,7 @@ function trackThree(kind) {
|
|
|
159
159
|
live[kind]++;
|
|
160
160
|
if (live[kind] > WARN_ABOVE[kind] && !warned.has(kind)) {
|
|
161
161
|
warned.add(kind);
|
|
162
|
-
console.warn(`pixi-effects: ${live[kind]} three layers are alive with renderer: '${kind}', and a browser keeps ${LIMIT[kind]} for the whole page; layers beyond that draw nothing, without an error. Put several objects in one three layer, destroy layers that are over, ` + (kind === "webgl" ? `or use renderer: 'webgpu' for some (its limit is about 32)` : `or use renderer: 'webgl' for some of them (a different pool of contexts)`));
|
|
162
|
+
console.warn(`pixi-effects: ${live[kind]} three layers are alive with renderer: '${kind}', and a browser keeps ${LIMIT[kind]} for the whole page; layers beyond that draw nothing, without an error. Put several objects in one three layer, destroy layers that are over, ` + (kind === "webgl" ? `or use renderer: 'webgpu' for some (in a movie PixiJS draws on WebGPU they share its GPU device and have no limit; otherwise it is about 32)` : `or use renderer: 'webgl' for some of them (a different pool of contexts), or leave shareGpu on in a movie PixiJS draws on WebGPU (the layers then share its device)`));
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
165
|
function releaseThree(kind) {
|
|
@@ -176,6 +176,11 @@ var ThreeSequence = class extends Sequence {
|
|
|
176
176
|
backend = null;
|
|
177
177
|
_gpu = false;
|
|
178
178
|
// renderer: 'webgpu': async init and async render
|
|
179
|
+
/** True when the layer draws on PixiJS's own GPU device into a texture PixiJS samples directly (no canvas of its own, no copy, no share of the page's context cap). */
|
|
180
|
+
sharedGpu = false;
|
|
181
|
+
_rt = null;
|
|
182
|
+
// the texture a shared layer draws into
|
|
183
|
+
_sharedTexture = null;
|
|
179
184
|
_scene = null;
|
|
180
185
|
_camera = null;
|
|
181
186
|
_ctx = null;
|
|
@@ -187,6 +192,8 @@ var ThreeSequence = class extends Sequence {
|
|
|
187
192
|
_fogMirror = null;
|
|
188
193
|
_warnedSpace = /* @__PURE__ */ new Set();
|
|
189
194
|
_tracked = false;
|
|
195
|
+
/** Set when this layer lets its renderer go on purpose: the context loss that follows is its own doing, not the browser's. */
|
|
196
|
+
_closing = false;
|
|
190
197
|
get _threeSpec() {
|
|
191
198
|
return this.spec;
|
|
192
199
|
}
|
|
@@ -219,31 +226,43 @@ var ThreeSequence = class extends Sequence {
|
|
|
219
226
|
} catch (err) {
|
|
220
227
|
throw new Error(`pixi-effects: renderer: 'webgpu' needs three 0.17x or later with "three/webgpu" in the import map (${err instanceof Error ? err.message : err})`);
|
|
221
228
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
229
|
+
let shared = spec.shareGpu === false ? void 0 : this.root.gpu;
|
|
230
|
+
for (; ; ) {
|
|
231
|
+
renderer = new mod.WebGPURenderer(shared ? { device: shared.device, alpha: true, antialias } : { canvas, alpha: true, antialias });
|
|
232
|
+
this._renderer = renderer;
|
|
233
|
+
if (!shared) this._track();
|
|
234
|
+
const warn = console.warn;
|
|
235
|
+
let noGpu = false;
|
|
236
|
+
console.warn = (...args) => {
|
|
237
|
+
if (/WebGPU is not available/.test(String(args[0]))) noGpu = true;
|
|
238
|
+
else warn.apply(console, args);
|
|
239
|
+
};
|
|
240
|
+
try {
|
|
241
|
+
await renderer.init();
|
|
242
|
+
if (shared) {
|
|
243
|
+
renderer.setSize(Math.round(width * resolution), Math.round(height * resolution), false);
|
|
244
|
+
renderer.setClearColor(0, 0);
|
|
245
|
+
this._prepareShared(renderer, shared, width, height, resolution, antialias);
|
|
246
|
+
}
|
|
247
|
+
this.backend = noGpu ? "webgl2" : "webgpu";
|
|
248
|
+
break;
|
|
249
|
+
} catch (err) {
|
|
250
|
+
this._disposeRenderer();
|
|
251
|
+
if (!shared) throw err;
|
|
252
|
+
console.warn(`pixi-effects: three layer${spec.name ? ` "${spec.name}"` : ""}: could not draw on PixiJS's GPU device (${err instanceof Error ? err.message : err}); it uses a canvas of its own (shareGpu: false does this on purpose)`);
|
|
253
|
+
shared = void 0;
|
|
254
|
+
this._closing = false;
|
|
255
|
+
} finally {
|
|
256
|
+
console.warn = warn;
|
|
257
|
+
}
|
|
238
258
|
}
|
|
239
|
-
this.backend = noGpu ? "webgl2" : "webgpu";
|
|
240
259
|
} else {
|
|
241
260
|
renderer = new WebGLRenderer({ canvas, alpha: true, antialias });
|
|
242
261
|
this._renderer = renderer;
|
|
243
262
|
this._track();
|
|
244
263
|
let said = false;
|
|
245
264
|
canvas.addEventListener("webglcontextlost", () => {
|
|
246
|
-
if (said) return;
|
|
265
|
+
if (said || this._closing) return;
|
|
247
266
|
said = true;
|
|
248
267
|
console.warn(`pixi-effects: three layer${spec.name ? ` "${spec.name}"` : ""}: the browser took this layer's WebGL context away (a page keeps about 16 for all its layers, PixiJS and shader layers: too many were alive), so the layer draws nothing. Put several objects in one three layer, or destroy layers that are over`);
|
|
249
268
|
});
|
|
@@ -270,7 +289,7 @@ var ThreeSequence = class extends Sequence {
|
|
|
270
289
|
if (!("camera" in this._objects)) this._objects.camera = this._camera;
|
|
271
290
|
if (this._gpu) this._checkWebGpuMaterials(scene, spec.name);
|
|
272
291
|
this._draw(0);
|
|
273
|
-
const texture = Texture.from(canvas);
|
|
292
|
+
const texture = this._sharedTexture ?? Texture.from(canvas);
|
|
274
293
|
const sprite = new Sprite({ texture, label: spec.name });
|
|
275
294
|
sprite.cullable = true;
|
|
276
295
|
sprite.width = width;
|
|
@@ -306,7 +325,7 @@ var ThreeSequence = class extends Sequence {
|
|
|
306
325
|
}
|
|
307
326
|
}
|
|
308
327
|
this._draw(t);
|
|
309
|
-
this.target?.texture.source.update();
|
|
328
|
+
if (!this.sharedGpu) this.target?.texture.source.update();
|
|
310
329
|
}
|
|
311
330
|
/**
|
|
312
331
|
* `movie.pick`: a ray through the point (u, v) of the layer's picture (0..1, v down) from the layer's camera, and what it meets first: the object's name (its own, or its nearest
|
|
@@ -334,6 +353,36 @@ var ThreeSequence = class extends Sequence {
|
|
|
334
353
|
}
|
|
335
354
|
return null;
|
|
336
355
|
}
|
|
356
|
+
/**
|
|
357
|
+
* `hit.three.grab(plane)`: drag a grabbed point of the scene. Returns a function of a point (u, v) of the layer's picture (0..1, v down) that gives where the pointer's ray through the layer's
|
|
358
|
+
* camera meets a plane through the grabbed point, and how far that is from the grabbed point (`delta`): move the object by it and it follows the pointer exactly. `plane`: `'screen'` (facing the
|
|
359
|
+
* camera: the default), `'floor'` (horizontal, the three y up), `'wall'` (z constant), or a normal `[x, y, z]`. null where the ray never meets it (a floor seen edge-on, behind the camera).
|
|
360
|
+
*/
|
|
361
|
+
dragPlane(point, plane = "screen") {
|
|
362
|
+
const grabbed = new Vector3(...point);
|
|
363
|
+
let normal;
|
|
364
|
+
if (plane === "floor") normal = new Vector3(0, 1, 0);
|
|
365
|
+
else if (plane === "wall") normal = new Vector3(0, 0, 1);
|
|
366
|
+
else if (Array.isArray(plane)) normal = new Vector3(...plane).normalize();
|
|
367
|
+
else {
|
|
368
|
+
const turn = new Quaternion();
|
|
369
|
+
this._camera?.updateMatrixWorld();
|
|
370
|
+
this._camera?.getWorldQuaternion(turn);
|
|
371
|
+
normal = new Vector3(0, 0, 1).applyQuaternion(turn);
|
|
372
|
+
}
|
|
373
|
+
const surface = new Plane().setFromNormalAndCoplanarPoint(normal, grabbed);
|
|
374
|
+
return (u, v) => {
|
|
375
|
+
const scene = this._scene, camera = this._camera;
|
|
376
|
+
if (!scene || !camera) return null;
|
|
377
|
+
scene.updateMatrixWorld();
|
|
378
|
+
camera.updateMatrixWorld();
|
|
379
|
+
const ray = new Raycaster();
|
|
380
|
+
ray.setFromCamera(new Vector2(u * 2 - 1, -(v * 2 - 1)), camera);
|
|
381
|
+
const at = ray.ray.intersectPlane(surface, new Vector3());
|
|
382
|
+
if (!at) return null;
|
|
383
|
+
return { point: at.toArray(), delta: at.clone().sub(grabbed).toArray() };
|
|
384
|
+
};
|
|
385
|
+
}
|
|
337
386
|
/**
|
|
338
387
|
* The determinism check (`check`, `movie.review()`): the scene drawn at a few moments in two orders, with one draw thrown away first, and the pictures compared, as the canvas layer
|
|
339
388
|
* does. A layer whose same frame is not the same picture (a clock, `Math.random`, a mixer advanced with `update(dt)`, any state that builds up from call to call) is reported.
|
|
@@ -366,7 +415,7 @@ var ThreeSequence = class extends Sequence {
|
|
|
366
415
|
try {
|
|
367
416
|
this._followSpace(t);
|
|
368
417
|
this._threeSpec.update?.(t, ctx);
|
|
369
|
-
this._draw(t);
|
|
418
|
+
this._draw(t, true);
|
|
370
419
|
g.clearRect(0, 0, w, h);
|
|
371
420
|
g.drawImage(source, 0, 0);
|
|
372
421
|
} catch {
|
|
@@ -469,10 +518,45 @@ var ThreeSequence = class extends Sequence {
|
|
|
469
518
|
* follow each other in one task (a seek, an export) would all show the lights of the last animation frame: a lamp keyframed with `three.lamp.intensity` would not move.
|
|
470
519
|
* So before each render the layer advances the node frame itself, and gives `time` the layer's own time (not three's wall clock).
|
|
471
520
|
*/
|
|
472
|
-
_draw(t) {
|
|
521
|
+
_draw(t, toCanvas = false) {
|
|
473
522
|
if (!this._renderer || !this._scene || !this._camera) return;
|
|
474
523
|
if (this._gpu) this._advanceNodeFrame(t);
|
|
475
|
-
|
|
524
|
+
if (!this._rt || toCanvas) {
|
|
525
|
+
this._renderer.render(this._scene, this._camera);
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
const r = this._renderer;
|
|
529
|
+
r.setOutputRenderTarget(this._rt);
|
|
530
|
+
try {
|
|
531
|
+
this._renderer.render(this._scene, this._camera);
|
|
532
|
+
} finally {
|
|
533
|
+
r.setOutputRenderTarget(null);
|
|
534
|
+
r.setRenderTarget(null);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* A shared layer's texture: a render target of the layer's size, drawn into once (the GPU texture exists only after a draw) and adopted by a PixiJS texture source. Throws when something
|
|
539
|
+
* is not as this expects (the build then makes the layer again on a canvas of its own). Done before `setup`, so nothing the author made yet depends on the renderer.
|
|
540
|
+
*/
|
|
541
|
+
_prepareShared(renderer, shared, width, height, resolution, antialias) {
|
|
542
|
+
const w = Math.round(width * resolution), h = Math.round(height * resolution);
|
|
543
|
+
const rt = new RenderTarget(w, h, { depthBuffer: true, samples: antialias ? 4 : 0 });
|
|
544
|
+
this._rt = rt;
|
|
545
|
+
const r = renderer;
|
|
546
|
+
if (typeof r.setOutputRenderTarget !== "function") throw new Error("this three has no setOutputRenderTarget");
|
|
547
|
+
r.setOutputRenderTarget(rt);
|
|
548
|
+
try {
|
|
549
|
+
renderer.render(new Scene(), new PerspectiveCamera());
|
|
550
|
+
} finally {
|
|
551
|
+
r.setOutputRenderTarget(null);
|
|
552
|
+
r.setRenderTarget(null);
|
|
553
|
+
}
|
|
554
|
+
const gpuTexture = r.backend?.get?.(rt.texture)?.texture;
|
|
555
|
+
if (!gpuTexture || typeof gpuTexture.createView !== "function") throw new Error("three keeps no GPU texture for a render target");
|
|
556
|
+
const source = new TextureSource({ width: w, height: h, format: gpuTexture.format, label: "three layer (shared GPU)" });
|
|
557
|
+
shared.adopt(source, gpuTexture);
|
|
558
|
+
this._sharedTexture = new Texture({ source });
|
|
559
|
+
this.sharedGpu = true;
|
|
476
560
|
}
|
|
477
561
|
/**
|
|
478
562
|
* The author chose renderer: 'webgpu'. Three's WebGPU renderer turns materials into node materials: a ShaderMaterial / RawShaderMaterial cannot run there (three logs an error on
|
|
@@ -555,6 +639,7 @@ var ThreeSequence = class extends Sequence {
|
|
|
555
639
|
}
|
|
556
640
|
_disposeRenderer() {
|
|
557
641
|
if (!this._renderer) return;
|
|
642
|
+
this._closing = true;
|
|
558
643
|
if (this._tracked) {
|
|
559
644
|
this._tracked = false;
|
|
560
645
|
releaseThree(this._gpu ? "webgpu" : "webgl");
|
|
@@ -566,6 +651,11 @@ var ThreeSequence = class extends Sequence {
|
|
|
566
651
|
console.warn("pixi-effects: three renderer dispose threw \u2014", err);
|
|
567
652
|
}
|
|
568
653
|
this._renderer = null;
|
|
654
|
+
try {
|
|
655
|
+
this._rt?.dispose();
|
|
656
|
+
} catch {
|
|
657
|
+
}
|
|
658
|
+
this._rt = null;
|
|
569
659
|
}
|
|
570
660
|
destroy() {
|
|
571
661
|
const spec = this._threeSpec;
|
|
@@ -588,6 +678,7 @@ var ThreeSequence = class extends Sequence {
|
|
|
588
678
|
this._objects = {};
|
|
589
679
|
super.destroy();
|
|
590
680
|
texture?.destroy(true);
|
|
681
|
+
this._sharedTexture = null;
|
|
591
682
|
}
|
|
592
683
|
};
|
|
593
684
|
function resolveDim(v, scope) {
|