@supersoniks/concorde 4.9.97-visual-stack.0 → 4.9.98-visual-stack.1
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/build-infos.json +1 -1
- package/concorde-3d.bundle.js +201 -152
- package/concorde-3d.es.js +14621 -13823
- package/concorde-core.bundle.js +1 -1
- package/concorde-core.es.js +1 -1
- package/concorde-hugging-face-infer.bundle.js +1 -1
- package/concorde-hugging-face-infer.es.js +1 -1
- package/concorde-shader.bundle.js +31 -20
- package/concorde-shader.es.js +3236 -2865
- package/concorde-webgpu.bundle.js +43 -32
- package/concorde-webgpu.es.js +2977 -2618
- package/dist/concorde-3d.bundle.js +201 -152
- package/dist/concorde-3d.es.js +14621 -13823
- package/dist/concorde-core.bundle.js +1 -1
- package/dist/concorde-core.es.js +1 -1
- package/dist/concorde-hugging-face-infer.bundle.js +1 -1
- package/dist/concorde-hugging-face-infer.es.js +1 -1
- package/dist/concorde-shader.bundle.js +31 -20
- package/dist/concorde-shader.es.js +3236 -2865
- package/dist/concorde-webgpu.bundle.js +43 -32
- package/dist/concorde-webgpu.es.js +2977 -2618
- package/dist/js/core/components/functional/3d/3d.js +100 -2
- package/dist/js/core/components/functional/3d/3d.js.map +1 -1
- package/dist/js/core/components/functional/3d/constants.js +3 -0
- package/dist/js/core/components/functional/3d/constants.js.map +1 -1
- package/dist/js/core/components/functional/3d/ensure.js +6 -3
- package/dist/js/core/components/functional/3d/ensure.js.map +1 -1
- package/dist/js/core/components/functional/3d/form-params.js +2 -0
- package/dist/js/core/components/functional/3d/form-params.js.map +1 -1
- package/dist/js/core/components/functional/3d/frame-source.js +22 -0
- package/dist/js/core/components/functional/3d/frame-source.js.map +1 -0
- package/dist/js/core/components/functional/3d/life.js +2 -1
- package/dist/js/core/components/functional/3d/life.js.map +1 -1
- package/dist/js/core/components/functional/3d/out-publish.js +3 -2
- package/dist/js/core/components/functional/3d/out-publish.js.map +1 -1
- package/dist/js/core/components/functional/3d/playback.js +6 -1
- package/dist/js/core/components/functional/3d/playback.js.map +1 -1
- package/dist/js/core/components/functional/3d/post-bind.js +207 -0
- package/dist/js/core/components/functional/3d/post-bind.js.map +1 -0
- package/dist/js/core/components/functional/3d/post-channels.js +39 -0
- package/dist/js/core/components/functional/3d/post-channels.js.map +1 -0
- package/dist/js/core/components/functional/3d/post-fx.js +495 -0
- package/dist/js/core/components/functional/3d/post-fx.js.map +1 -0
- package/dist/js/core/components/functional/3d/props.js +142 -0
- package/dist/js/core/components/functional/3d/props.js.map +1 -1
- package/dist/js/core/components/functional/3d/reload.js +5 -0
- package/dist/js/core/components/functional/3d/reload.js.map +1 -1
- package/dist/js/core/components/functional/3d/runtime.js +80 -3
- package/dist/js/core/components/functional/3d/runtime.js.map +1 -1
- package/dist/js/core/components/functional/3d/scene-runtime.js +1 -1
- package/dist/js/core/components/functional/3d/scene-runtime.js.map +1 -1
- package/dist/js/core/components/functional/3d/tune.js +21 -0
- package/dist/js/core/components/functional/3d/tune.js.map +1 -1
- package/dist/js/core/components/functional/3d/updated.js +13 -1
- package/dist/js/core/components/functional/3d/updated.js.map +1 -1
- package/dist/js/core/components/functional/shader/gl-runtime.js +280 -31
- package/dist/js/core/components/functional/shader/gl-runtime.js.map +1 -1
- package/dist/js/core/components/functional/shader/shader.js +207 -61
- package/dist/js/core/components/functional/shader/shader.js.map +1 -1
- package/dist/js/core/components/functional/shader/shadertoy-prelude.js +39 -5
- package/dist/js/core/components/functional/shader/shadertoy-prelude.js.map +1 -1
- package/dist/js/core/components/functional/shader/types.js +58 -7
- package/dist/js/core/components/functional/shader/types.js.map +1 -1
- package/dist/js/core/components/functional/webgpu/gl-fallback.js +27 -6
- package/dist/js/core/components/functional/webgpu/gl-fallback.js.map +1 -1
- package/dist/js/core/components/functional/webgpu/gpu-runtime.js +115 -13
- package/dist/js/core/components/functional/webgpu/gpu-runtime.js.map +1 -1
- package/dist/js/core/components/functional/webgpu/helpers.js +8 -2
- package/dist/js/core/components/functional/webgpu/helpers.js.map +1 -1
- package/dist/js/core/components/functional/webgpu/webgpu.js +43 -1
- package/dist/js/core/components/functional/webgpu/webgpu.js.map +1 -1
- package/dist/js/core/utils/mediaRef.js +86 -0
- package/dist/js/core/utils/mediaRef.js.map +1 -1
- package/dist/types/core/components/functional/3d/3d.d.ts +31 -3
- package/dist/types/core/components/functional/3d/3d.d.ts.map +1 -1
- package/dist/types/core/components/functional/3d/constants.d.ts +1 -1
- package/dist/types/core/components/functional/3d/constants.d.ts.map +1 -1
- package/dist/types/core/components/functional/3d/ensure.d.ts +3 -0
- package/dist/types/core/components/functional/3d/ensure.d.ts.map +1 -1
- package/dist/types/core/components/functional/3d/form-params.d.ts.map +1 -1
- package/dist/types/core/components/functional/3d/frame-source.d.ts +23 -0
- package/dist/types/core/components/functional/3d/frame-source.d.ts.map +1 -0
- package/dist/types/core/components/functional/3d/life.d.ts +2 -0
- package/dist/types/core/components/functional/3d/life.d.ts.map +1 -1
- package/dist/types/core/components/functional/3d/out-publish.d.ts +1 -0
- package/dist/types/core/components/functional/3d/out-publish.d.ts.map +1 -1
- package/dist/types/core/components/functional/3d/playback.d.ts +9 -0
- package/dist/types/core/components/functional/3d/playback.d.ts.map +1 -1
- package/dist/types/core/components/functional/3d/post-bind.d.ts +52 -0
- package/dist/types/core/components/functional/3d/post-bind.d.ts.map +1 -0
- package/dist/types/core/components/functional/3d/post-channels.d.ts +40 -0
- package/dist/types/core/components/functional/3d/post-channels.d.ts.map +1 -0
- package/dist/types/core/components/functional/3d/post-fx.d.ts +73 -0
- package/dist/types/core/components/functional/3d/post-fx.d.ts.map +1 -0
- package/dist/types/core/components/functional/3d/props.d.ts +42 -0
- package/dist/types/core/components/functional/3d/props.d.ts.map +1 -1
- package/dist/types/core/components/functional/3d/reload.d.ts +3 -0
- package/dist/types/core/components/functional/3d/reload.d.ts.map +1 -1
- package/dist/types/core/components/functional/3d/runtime.d.ts +16 -1
- package/dist/types/core/components/functional/3d/runtime.d.ts.map +1 -1
- package/dist/types/core/components/functional/3d/scene-runtime.d.ts +1 -1
- package/dist/types/core/components/functional/3d/scene-runtime.d.ts.map +1 -1
- package/dist/types/core/components/functional/3d/tune.d.ts +5 -0
- package/dist/types/core/components/functional/3d/tune.d.ts.map +1 -1
- package/dist/types/core/components/functional/3d/types.d.ts +16 -0
- package/dist/types/core/components/functional/3d/types.d.ts.map +1 -1
- package/dist/types/core/components/functional/3d/updated.d.ts.map +1 -1
- package/dist/types/core/components/functional/shader/gl-runtime.d.ts +53 -2
- package/dist/types/core/components/functional/shader/gl-runtime.d.ts.map +1 -1
- package/dist/types/core/components/functional/shader/shader.d.ts +41 -9
- package/dist/types/core/components/functional/shader/shader.d.ts.map +1 -1
- package/dist/types/core/components/functional/shader/shadertoy-prelude.d.ts +16 -2
- package/dist/types/core/components/functional/shader/shadertoy-prelude.d.ts.map +1 -1
- package/dist/types/core/components/functional/shader/types.d.ts +35 -5
- package/dist/types/core/components/functional/shader/types.d.ts.map +1 -1
- package/dist/types/core/components/functional/webgpu/gl-fallback.d.ts +4 -0
- package/dist/types/core/components/functional/webgpu/gl-fallback.d.ts.map +1 -1
- package/dist/types/core/components/functional/webgpu/gpu-runtime.d.ts +14 -0
- package/dist/types/core/components/functional/webgpu/gpu-runtime.d.ts.map +1 -1
- package/dist/types/core/components/functional/webgpu/helpers.d.ts +1 -0
- package/dist/types/core/components/functional/webgpu/helpers.d.ts.map +1 -1
- package/dist/types/core/components/functional/webgpu/webgpu.d.ts +11 -1
- package/dist/types/core/components/functional/webgpu/webgpu.d.ts.map +1 -1
- package/dist/types/core/utils/mediaRef.d.ts +34 -0
- package/dist/types/core/utils/mediaRef.d.ts.map +1 -1
- package/package.json +49 -1
- package/src/core/components/functional/3d/3d.md +46 -3
- package/src/core/components/functional/3d/3d.spec.ts +42 -0
- package/src/core/components/functional/3d/3d.ts +112 -3
- package/src/core/components/functional/3d/constants.ts +3 -0
- package/src/core/components/functional/3d/ensure.ts +11 -3
- package/src/core/components/functional/3d/form-params.ts +2 -0
- package/src/core/components/functional/3d/frame-source.ts +30 -0
- package/src/core/components/functional/3d/life.ts +4 -1
- package/src/core/components/functional/3d/out-publish.ts +4 -3
- package/src/core/components/functional/3d/playback.ts +13 -1
- package/src/core/components/functional/3d/post-bind.ts +262 -0
- package/src/core/components/functional/3d/post-channels.spec.ts +36 -0
- package/src/core/components/functional/3d/post-channels.ts +69 -0
- package/src/core/components/functional/3d/post-fx.ts +594 -0
- package/src/core/components/functional/3d/props.ts +45 -0
- package/src/core/components/functional/3d/reload.ts +8 -0
- package/src/core/components/functional/3d/runtime.ts +93 -4
- package/src/core/components/functional/3d/scene-runtime.ts +3 -0
- package/src/core/components/functional/3d/tune.ts +21 -0
- package/src/core/components/functional/3d/types.ts +14 -0
- package/src/core/components/functional/3d/updated.ts +17 -1
- package/src/core/components/functional/shader/gl-runtime.ts +374 -36
- package/src/core/components/functional/shader/shader.md +36 -11
- package/src/core/components/functional/shader/shader.spec.ts +350 -3
- package/src/core/components/functional/shader/shader.ts +236 -59
- package/src/core/components/functional/shader/shadertoy-prelude.ts +49 -5
- package/src/core/components/functional/shader/types.ts +92 -13
- package/src/core/components/functional/webgpu/gl-fallback.ts +28 -4
- package/src/core/components/functional/webgpu/gpu-runtime.ts +154 -18
- package/src/core/components/functional/webgpu/helpers.ts +8 -2
- package/src/core/components/functional/webgpu/webgpu.md +13 -2
- package/src/core/components/functional/webgpu/webgpu.spec.ts +37 -0
- package/src/core/components/functional/webgpu/webgpu.ts +48 -1
- package/src/core/utils/mediaRef.spec.ts +61 -0
- package/src/core/utils/mediaRef.ts +108 -0
- package/src/docs/_misc/visual-stack.md +37 -3
- package/src/docs/components/docs-demo-sources.ts +42 -0
- package/src/docs/docs.ts +3 -0
- package/src/docs/example/docs-3d-post-depth-demo.ts +68 -0
- package/src/docs/example/docs-3d-shader-live-demo.ts +98 -0
- package/src/docs/example/docs-3d-webgpu-live-demo.ts +83 -0
- package/src/docs/example/docs-harris-webgpu-demo.ts +53 -55
- package/src/docs/search/docs-search.json +2583 -863
- package/src/tsconfig.json +36 -0
- package/src/tsconfig.tsbuildinfo +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { css, html, LitElement } from "lit";
|
|
2
2
|
import { customElement, property, state } from "lit/decorators.js";
|
|
3
3
|
import HTML from "@supersoniks/concorde/core/utils/HTML";
|
|
4
|
-
import { revokeMediaUrls, toMediaUrl } from "@supersoniks/concorde/core/utils/mediaRef";
|
|
4
|
+
import { revokeMediaUrls, toMediaUrl, mediaElementKey, lookupLiveElement, FrameConsumerRegistry } from "@supersoniks/concorde/core/utils/mediaRef";
|
|
5
5
|
import { PublisherManager } from "@supersoniks/concorde/utils";
|
|
6
6
|
import {
|
|
7
7
|
parseChannelSource,
|
|
@@ -9,6 +9,8 @@ import {
|
|
|
9
9
|
} from "./gl-runtime";
|
|
10
10
|
import {
|
|
11
11
|
PassChannels,
|
|
12
|
+
ReleaseOffscreen,
|
|
13
|
+
ShaderBufferFormat,
|
|
12
14
|
ShaderCompileError,
|
|
13
15
|
ShaderExtractItem,
|
|
14
16
|
ShaderExtractOutput,
|
|
@@ -18,17 +20,61 @@ import {
|
|
|
18
20
|
ShaderRoi,
|
|
19
21
|
ShaderSources,
|
|
20
22
|
SonicShaderOutput,
|
|
23
|
+
channelsUseSelf,
|
|
21
24
|
findPeaks,
|
|
22
25
|
meanRgba,
|
|
26
|
+
parseBufferFormat,
|
|
23
27
|
parseExtractPass,
|
|
24
28
|
parseHoverParam,
|
|
29
|
+
parseReleaseOffscreen,
|
|
25
30
|
roiToPixels,
|
|
31
|
+
rgbaToUint8,
|
|
32
|
+
shouldReleaseWhenOffscreen,
|
|
26
33
|
} from "./types";
|
|
27
34
|
|
|
28
35
|
const tagName = "sonic-shader";
|
|
29
36
|
|
|
30
37
|
const MAX_PATCH_PX = 128;
|
|
31
38
|
|
|
39
|
+
/** Clés qui forcent une recompilation / recreate FBO. */
|
|
40
|
+
const PROGRAM_KEYS = [
|
|
41
|
+
"image",
|
|
42
|
+
"bufferA",
|
|
43
|
+
"bufferB",
|
|
44
|
+
"bufferC",
|
|
45
|
+
"bufferD",
|
|
46
|
+
"common",
|
|
47
|
+
"bufferFormat",
|
|
48
|
+
] as const;
|
|
49
|
+
|
|
50
|
+
/** Clés qui ne font que re-lier les textures (pas de rebuild). */
|
|
51
|
+
const CHANNEL_KEYS = [
|
|
52
|
+
"channel0",
|
|
53
|
+
"channel1",
|
|
54
|
+
"channel2",
|
|
55
|
+
"channel3",
|
|
56
|
+
"imageCh0",
|
|
57
|
+
"imageCh1",
|
|
58
|
+
"imageCh2",
|
|
59
|
+
"imageCh3",
|
|
60
|
+
"bufferACh0",
|
|
61
|
+
"bufferACh1",
|
|
62
|
+
"bufferACh2",
|
|
63
|
+
"bufferACh3",
|
|
64
|
+
"bufferBCh0",
|
|
65
|
+
"bufferBCh1",
|
|
66
|
+
"bufferBCh2",
|
|
67
|
+
"bufferBCh3",
|
|
68
|
+
"bufferCCh0",
|
|
69
|
+
"bufferCCh1",
|
|
70
|
+
"bufferCCh2",
|
|
71
|
+
"bufferCCh3",
|
|
72
|
+
"bufferDCh0",
|
|
73
|
+
"bufferDCh1",
|
|
74
|
+
"bufferDCh2",
|
|
75
|
+
"bufferDCh3",
|
|
76
|
+
] as const;
|
|
77
|
+
|
|
32
78
|
/**
|
|
33
79
|
* Champs méta publiés vers le out-dataProvider.
|
|
34
80
|
* `param0…3` sont exclus du gate « consommateur » : un `sonic-input name="param0"`
|
|
@@ -104,16 +150,24 @@ function toNum(v: unknown, fallback: number): number {
|
|
|
104
150
|
return fallback;
|
|
105
151
|
}
|
|
106
152
|
|
|
107
|
-
/** Valeur canal depuis DP : string (url
|
|
153
|
+
/** Valeur canal depuis DP : string (url, buffer-a, #id) | MediaRef → url | { element }. */
|
|
108
154
|
function channelFormValue(value: unknown): string | undefined {
|
|
109
155
|
if (value === null || value === "") return "";
|
|
110
156
|
if (typeof value === "string") return value.trim();
|
|
111
157
|
const url = toMediaUrl(value);
|
|
112
158
|
if (url) return url;
|
|
113
|
-
if (value && typeof value === "object")
|
|
159
|
+
if (value && typeof value === "object") {
|
|
160
|
+
const el = (value as { element?: unknown }).element;
|
|
161
|
+
const key = mediaElementKey(el);
|
|
162
|
+
if (key) return key;
|
|
163
|
+
return undefined;
|
|
164
|
+
}
|
|
114
165
|
return "";
|
|
115
166
|
}
|
|
116
167
|
|
|
168
|
+
/** Exposé pour tests. */
|
|
169
|
+
export { channelFormValue };
|
|
170
|
+
|
|
117
171
|
function parseRois(value: unknown): ShaderRoi[] {
|
|
118
172
|
if (!Array.isArray(value)) return [];
|
|
119
173
|
const out: ShaderRoi[] = [];
|
|
@@ -286,12 +340,32 @@ export class SonicShader extends LitElement {
|
|
|
286
340
|
/** Vitesse d’easing hover on/off (1/s, défaut 10). */
|
|
287
341
|
@property({ type: Number, attribute: "hover-speed" }) hoverSpeed = 10;
|
|
288
342
|
/**
|
|
289
|
-
*
|
|
290
|
-
*
|
|
343
|
+
* Hors viewport : libère textures/FBO (garde le contexte).
|
|
344
|
+
* `auto` (défaut) : ne libère pas si une passe lit `self`.
|
|
345
|
+
* `true` / `false` forcent le comportement.
|
|
291
346
|
*/
|
|
292
|
-
@property({
|
|
293
|
-
|
|
347
|
+
@property({
|
|
348
|
+
attribute: "release-offscreen",
|
|
349
|
+
converter: {
|
|
350
|
+
fromAttribute: (value: string | null) => parseReleaseOffscreen(value),
|
|
351
|
+
toAttribute: (value: ReleaseOffscreen) => {
|
|
352
|
+
if (value === "auto") return "auto";
|
|
353
|
+
if (value === false) return "false";
|
|
354
|
+
return "";
|
|
355
|
+
},
|
|
356
|
+
},
|
|
357
|
+
})
|
|
358
|
+
releaseOffscreen: ReleaseOffscreen = "auto";
|
|
294
359
|
@property({ type: Number, attribute: "dpr-max" }) dprMax = 2;
|
|
360
|
+
/**
|
|
361
|
+
* Format des buffers A–D : `rgba8` (défaut) | `rgba16f` | `rgba32f`.
|
|
362
|
+
* Attribut reflété `active-buffer-format` = format réellement utilisé.
|
|
363
|
+
*/
|
|
364
|
+
@property({ attribute: "buffer-format" })
|
|
365
|
+
bufferFormat: ShaderBufferFormat | string = "rgba8";
|
|
366
|
+
/** Format actif après repli éventuel (lecture seule, reflect). */
|
|
367
|
+
@property({ attribute: "active-buffer-format", reflect: true })
|
|
368
|
+
activeBufferFormat: ShaderBufferFormat = "rgba8";
|
|
295
369
|
|
|
296
370
|
/** Generic float uniforms `uParam0`…`uParam3` (no shader rebuild). */
|
|
297
371
|
@property({ type: Number, attribute: "param0" }) param0 = 0;
|
|
@@ -364,6 +438,8 @@ export class SonicShader extends LitElement {
|
|
|
364
438
|
private startTime = 0;
|
|
365
439
|
private lastTime = 0;
|
|
366
440
|
private frame = 0;
|
|
441
|
+
/** Incrémenté après chaque render (contrat SonicFrameSource). */
|
|
442
|
+
frameSeq = 0;
|
|
367
443
|
private mouseVec: [number, number, number, number] = [0, 0, 0, 0];
|
|
368
444
|
/** Cible pointeur (px drawing buffer, origine bas-gauche). */
|
|
369
445
|
private mouseTarget: [number, number] = [0, 0];
|
|
@@ -389,6 +465,9 @@ export class SonicShader extends LitElement {
|
|
|
389
465
|
private resizeObserver: ResizeObserver | null = null;
|
|
390
466
|
private intersectionObserver: IntersectionObserver | null = null;
|
|
391
467
|
private rebuildToken = 0;
|
|
468
|
+
/** Annule un `rebindChannels` en vol si rebuild / release intervient. */
|
|
469
|
+
private rebindToken = 0;
|
|
470
|
+
private frameConsumers = new FrameConsumerRegistry();
|
|
392
471
|
private ready = false;
|
|
393
472
|
private formPublisher: ReturnType<typeof PublisherManager.get> | null = null;
|
|
394
473
|
private outPublisher: ReturnType<typeof PublisherManager.get> | null = null;
|
|
@@ -469,9 +548,11 @@ export class SonicShader extends LitElement {
|
|
|
469
548
|
}
|
|
470
549
|
this.pendingRevokeUrls = [];
|
|
471
550
|
this.stopLoop();
|
|
551
|
+
this.frameConsumers.clear();
|
|
472
552
|
this.resizeObserver?.disconnect();
|
|
473
553
|
this.intersectionObserver?.disconnect();
|
|
474
554
|
this.rebuildToken++;
|
|
555
|
+
this.rebindToken++;
|
|
475
556
|
this.ready = false;
|
|
476
557
|
this.releasing = true;
|
|
477
558
|
this.runtime?.dispose(true); // libère le slot navigateur
|
|
@@ -495,7 +576,7 @@ export class SonicShader extends LitElement {
|
|
|
495
576
|
this.bindOutPublisher();
|
|
496
577
|
this.bindExtractPublisher();
|
|
497
578
|
requestAnimationFrame(() => {
|
|
498
|
-
if (this.inView || !this.
|
|
579
|
+
if (this.inView || !this.wantsReleaseOffscreen()) {
|
|
499
580
|
void this.ensureRuntime();
|
|
500
581
|
}
|
|
501
582
|
});
|
|
@@ -503,44 +584,19 @@ export class SonicShader extends LitElement {
|
|
|
503
584
|
|
|
504
585
|
protected updated(changed: Map<string, unknown>) {
|
|
505
586
|
if (!this.runtime) return;
|
|
506
|
-
const
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
"bufferB",
|
|
510
|
-
"bufferC",
|
|
511
|
-
"bufferD",
|
|
512
|
-
"common",
|
|
513
|
-
"channel0",
|
|
514
|
-
"channel1",
|
|
515
|
-
"channel2",
|
|
516
|
-
"channel3",
|
|
517
|
-
"imageCh0",
|
|
518
|
-
"imageCh1",
|
|
519
|
-
"imageCh2",
|
|
520
|
-
"imageCh3",
|
|
521
|
-
"bufferACh0",
|
|
522
|
-
"bufferACh1",
|
|
523
|
-
"bufferACh2",
|
|
524
|
-
"bufferACh3",
|
|
525
|
-
"bufferBCh0",
|
|
526
|
-
"bufferBCh1",
|
|
527
|
-
"bufferBCh2",
|
|
528
|
-
"bufferBCh3",
|
|
529
|
-
"bufferCCh0",
|
|
530
|
-
"bufferCCh1",
|
|
531
|
-
"bufferCCh2",
|
|
532
|
-
"bufferCCh3",
|
|
533
|
-
"bufferDCh0",
|
|
534
|
-
"bufferDCh1",
|
|
535
|
-
"bufferDCh2",
|
|
536
|
-
"bufferDCh3",
|
|
537
|
-
];
|
|
538
|
-
if (shaderKeys.some((k) => changed.has(k))) {
|
|
587
|
+
const programChanged = PROGRAM_KEYS.some((k) => changed.has(k));
|
|
588
|
+
const channelChanged = CHANNEL_KEYS.some((k) => changed.has(k));
|
|
589
|
+
if (programChanged) {
|
|
539
590
|
void this.rebuild();
|
|
591
|
+
} else if (channelChanged) {
|
|
592
|
+
void this.rebindChannels();
|
|
540
593
|
}
|
|
541
594
|
if (changed.has("play")) {
|
|
542
595
|
this.syncPlayback();
|
|
543
596
|
}
|
|
597
|
+
if (changed.has("releaseOffscreen") || channelChanged) {
|
|
598
|
+
this.syncVisibility();
|
|
599
|
+
}
|
|
544
600
|
if (
|
|
545
601
|
changed.has("dataProvider") ||
|
|
546
602
|
changed.has("outDataProvider") ||
|
|
@@ -686,6 +742,7 @@ export class SonicShader extends LitElement {
|
|
|
686
742
|
*/
|
|
687
743
|
private releaseRuntime() {
|
|
688
744
|
this.rebuildToken++;
|
|
745
|
+
this.rebindToken++;
|
|
689
746
|
this.stopLoop();
|
|
690
747
|
this.ready = false;
|
|
691
748
|
this.releasing = true;
|
|
@@ -702,6 +759,27 @@ export class SonicShader extends LitElement {
|
|
|
702
759
|
);
|
|
703
760
|
}
|
|
704
761
|
|
|
762
|
+
/** Contrat SonicFrameSource — canvas lisible pour un autre sonic-shader. */
|
|
763
|
+
getFrameCanvas(): HTMLCanvasElement | null {
|
|
764
|
+
if (!this.ready || !this.runtime || this.runtime.isLost) return null;
|
|
765
|
+
return this.getCanvas();
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
/** Résout `#id` dans getRootNode() puis document ; clés live `__sonic_frame_`. */
|
|
769
|
+
private lookupElement(key: string): Element | null {
|
|
770
|
+
if (!key.startsWith("#")) return null;
|
|
771
|
+
const live = lookupLiveElement(key);
|
|
772
|
+
if (live) return live;
|
|
773
|
+
const id = key.slice(1);
|
|
774
|
+
if (!id || id.startsWith("__sonic_frame_")) return null;
|
|
775
|
+
const root = this.getRootNode();
|
|
776
|
+
if (root instanceof Document || root instanceof ShadowRoot) {
|
|
777
|
+
const el = root.getElementById(id);
|
|
778
|
+
if (el) return el;
|
|
779
|
+
}
|
|
780
|
+
return typeof document !== "undefined" ? document.getElementById(id) : null;
|
|
781
|
+
}
|
|
782
|
+
|
|
705
783
|
private bindContextEvents() {
|
|
706
784
|
const canvas = this.getCanvas();
|
|
707
785
|
canvas?.addEventListener("webglcontextlost", this.onContextLost);
|
|
@@ -721,6 +799,7 @@ export class SonicShader extends LitElement {
|
|
|
721
799
|
e.preventDefault();
|
|
722
800
|
if (this.releasing) return;
|
|
723
801
|
this.rebuildToken++;
|
|
802
|
+
this.rebindToken++;
|
|
724
803
|
this.stopLoop();
|
|
725
804
|
this.ready = false;
|
|
726
805
|
this.runtime = null;
|
|
@@ -735,7 +814,8 @@ export class SonicShader extends LitElement {
|
|
|
735
814
|
if (this.runtime && !this.runtime.isLost) return;
|
|
736
815
|
this.runtime = null;
|
|
737
816
|
await this.updateComplete;
|
|
738
|
-
if (!this.isConnected || (!this.inView && this.
|
|
817
|
+
if (!this.isConnected || (!this.inView && this.wantsReleaseOffscreen()))
|
|
818
|
+
return;
|
|
739
819
|
|
|
740
820
|
const canvas = this.getCanvas();
|
|
741
821
|
if (!canvas) return;
|
|
@@ -743,6 +823,10 @@ export class SonicShader extends LitElement {
|
|
|
743
823
|
try {
|
|
744
824
|
this.errorMessage = "";
|
|
745
825
|
this.runtime = new ShaderToyRuntime(canvas);
|
|
826
|
+
this.runtime.setElementResolver((key) => this.lookupElement(key));
|
|
827
|
+
this.activeBufferFormat = this.runtime.setBufferFormat(
|
|
828
|
+
parseBufferFormat(this.bufferFormat),
|
|
829
|
+
);
|
|
746
830
|
this.bindContextEvents();
|
|
747
831
|
this.syncSize();
|
|
748
832
|
await this.rebuild();
|
|
@@ -752,7 +836,7 @@ export class SonicShader extends LitElement {
|
|
|
752
836
|
}
|
|
753
837
|
|
|
754
838
|
private syncVisibility() {
|
|
755
|
-
if (!this.inView && this.
|
|
839
|
+
if (!this.inView && this.wantsReleaseOffscreen()) {
|
|
756
840
|
this.releaseRuntime();
|
|
757
841
|
return;
|
|
758
842
|
}
|
|
@@ -827,8 +911,84 @@ export class SonicShader extends LitElement {
|
|
|
827
911
|
return urls;
|
|
828
912
|
}
|
|
829
913
|
|
|
914
|
+
private collectElementKeys(
|
|
915
|
+
channels: Map<ShaderPassId, PassChannels>,
|
|
916
|
+
): string[] {
|
|
917
|
+
const keys: string[] = [];
|
|
918
|
+
for (const chs of channels.values()) {
|
|
919
|
+
for (const c of chs) {
|
|
920
|
+
if (c.kind === "element") keys.push(c.key);
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
return [...new Set(keys)];
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
/** Enregistre les producteurs live (`sonic-3d`…) pour play-offscreen auto. */
|
|
927
|
+
private syncFrameConsumers(channels: Map<ShaderPassId, PassChannels>) {
|
|
928
|
+
const els = this.collectElementKeys(channels).map((k) =>
|
|
929
|
+
this.lookupElement(k),
|
|
930
|
+
);
|
|
931
|
+
this.frameConsumers.sync(els);
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
/** Map canaux courante (tous les passes). */
|
|
935
|
+
private collectPassChannels(): Map<ShaderPassId, PassChannels> {
|
|
936
|
+
const channels = new Map<ShaderPassId, PassChannels>();
|
|
937
|
+
for (const pass of [
|
|
938
|
+
"bufferA",
|
|
939
|
+
"bufferB",
|
|
940
|
+
"bufferC",
|
|
941
|
+
"bufferD",
|
|
942
|
+
"image",
|
|
943
|
+
] as ShaderPassId[]) {
|
|
944
|
+
channels.set(pass, this.buildChannels(pass));
|
|
945
|
+
}
|
|
946
|
+
return channels;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
/** `true` si hors viewport on doit libérer textures/FBO. */
|
|
950
|
+
private wantsReleaseOffscreen(): boolean {
|
|
951
|
+
return shouldReleaseWhenOffscreen(
|
|
952
|
+
this.releaseOffscreen,
|
|
953
|
+
channelsUseSelf(this.collectPassChannels().values()),
|
|
954
|
+
);
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
/**
|
|
958
|
+
* Re-lie les canaux sans recompiler ni vider les FBO (Vague A Lot 2).
|
|
959
|
+
*/
|
|
960
|
+
private async rebindChannels() {
|
|
961
|
+
if (!this.runtime || this.runtime.isLost || !this.image.trim()) return;
|
|
962
|
+
if (!this.ready) {
|
|
963
|
+
void this.rebuild();
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
966
|
+
const token = ++this.rebindToken;
|
|
967
|
+
const channels = this.collectPassChannels();
|
|
968
|
+
try {
|
|
969
|
+
const urls = this.collectUrls(channels);
|
|
970
|
+
await this.runtime.ensureTextures(urls);
|
|
971
|
+
for (const key of this.collectElementKeys(channels)) {
|
|
972
|
+
this.runtime.ensureElementTexture(key);
|
|
973
|
+
}
|
|
974
|
+
if (token !== this.rebindToken || !this.runtime || this.runtime.isLost) {
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
977
|
+
this.syncFrameConsumers(channels);
|
|
978
|
+
const aspectHint =
|
|
979
|
+
this.channel0.startsWith("#") ? "" : this.channel0 || urls[0];
|
|
980
|
+
this.applyAspectRatio(aspectHint);
|
|
981
|
+
this.runtime.setPassChannels(channels);
|
|
982
|
+
this.syncSize();
|
|
983
|
+
} catch (err) {
|
|
984
|
+
if (token !== this.rebindToken) return;
|
|
985
|
+
this.emitError(err);
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
|
|
830
989
|
private async rebuild() {
|
|
831
990
|
if (!this.runtime || this.runtime.isLost || !this.image.trim()) return;
|
|
991
|
+
this.rebindToken++;
|
|
832
992
|
const token = ++this.rebuildToken;
|
|
833
993
|
this.errorMessage = "";
|
|
834
994
|
const sources: ShaderSources = {
|
|
@@ -839,24 +999,24 @@ export class SonicShader extends LitElement {
|
|
|
839
999
|
bufferC: this.bufferC,
|
|
840
1000
|
bufferD: this.bufferD,
|
|
841
1001
|
};
|
|
842
|
-
const channels =
|
|
843
|
-
for (const pass of [
|
|
844
|
-
"bufferA",
|
|
845
|
-
"bufferB",
|
|
846
|
-
"bufferC",
|
|
847
|
-
"bufferD",
|
|
848
|
-
"image",
|
|
849
|
-
] as ShaderPassId[]) {
|
|
850
|
-
channels.set(pass, this.buildChannels(pass));
|
|
851
|
-
}
|
|
1002
|
+
const channels = this.collectPassChannels();
|
|
852
1003
|
try {
|
|
853
1004
|
this.syncSize();
|
|
1005
|
+
this.activeBufferFormat = this.runtime.setBufferFormat(
|
|
1006
|
+
parseBufferFormat(this.bufferFormat),
|
|
1007
|
+
);
|
|
854
1008
|
const urls = this.collectUrls(channels);
|
|
855
1009
|
await this.runtime.ensureTextures(urls);
|
|
1010
|
+
for (const key of this.collectElementKeys(channels)) {
|
|
1011
|
+
this.runtime.ensureElementTexture(key);
|
|
1012
|
+
}
|
|
856
1013
|
if (token !== this.rebuildToken || !this.runtime || this.runtime.isLost) {
|
|
857
1014
|
return;
|
|
858
1015
|
}
|
|
859
|
-
this.
|
|
1016
|
+
this.syncFrameConsumers(channels);
|
|
1017
|
+
const aspectHint =
|
|
1018
|
+
this.channel0.startsWith("#") ? "" : this.channel0 || urls[0];
|
|
1019
|
+
this.applyAspectRatio(aspectHint);
|
|
860
1020
|
this.syncSize();
|
|
861
1021
|
this.runtime.setSources(sources, channels);
|
|
862
1022
|
if (token !== this.rebuildToken || !this.runtime || this.runtime.isLost) {
|
|
@@ -964,6 +1124,7 @@ export class SonicShader extends LitElement {
|
|
|
964
1124
|
mouse: this.mouseVec,
|
|
965
1125
|
params,
|
|
966
1126
|
});
|
|
1127
|
+
this.frameSeq++;
|
|
967
1128
|
this.maybePublishOut(now, time, params);
|
|
968
1129
|
void this.maybeExtract(now, time);
|
|
969
1130
|
}
|
|
@@ -1262,8 +1423,8 @@ export class SonicShader extends LitElement {
|
|
|
1262
1423
|
: this.runtime.readBufferRect(pass, px.x, px.y, px.w, px.h);
|
|
1263
1424
|
if (!rect) continue;
|
|
1264
1425
|
// Copie : le buffer WebGL peut être réutilisé / invalidé ensuite
|
|
1265
|
-
const rgba =
|
|
1266
|
-
const mean = meanRgba(
|
|
1426
|
+
const rgba = rgbaToUint8(rect.data);
|
|
1427
|
+
const mean = meanRgba(rect.data);
|
|
1267
1428
|
const item: ShaderExtractItem = {
|
|
1268
1429
|
id: roi.id || `${source}-${px.x}-${px.y}`,
|
|
1269
1430
|
x: this.round3(rect.x / bufW),
|
|
@@ -1360,7 +1521,11 @@ export class SonicShader extends LitElement {
|
|
|
1360
1521
|
if (typeof score === "number") item.score = this.round3(score);
|
|
1361
1522
|
if (this.extractBitmaps) {
|
|
1362
1523
|
const token = this.rebuildToken;
|
|
1363
|
-
const url = await rgbaToBlobUrl(
|
|
1524
|
+
const url = await rgbaToBlobUrl(
|
|
1525
|
+
rgbaToUint8(rect.data),
|
|
1526
|
+
rect.width,
|
|
1527
|
+
rect.height,
|
|
1528
|
+
);
|
|
1364
1529
|
if (token !== this.rebuildToken || !this.isConnected) {
|
|
1365
1530
|
if (url) revokeMediaUrls([url]);
|
|
1366
1531
|
return null;
|
|
@@ -1531,10 +1696,12 @@ export class SonicShader extends LitElement {
|
|
|
1531
1696
|
}
|
|
1532
1697
|
}
|
|
1533
1698
|
|
|
1534
|
-
export { parseChannelSource, ShaderToyRuntime } from "./gl-runtime";
|
|
1699
|
+
export { parseChannelSource, ShaderToyRuntime, shouldUploadElementFrame, resolveBufferGlFormat, resetBufferFormatWarnFlag } from "./gl-runtime";
|
|
1535
1700
|
export { buildFragmentSource } from "./shadertoy-prelude";
|
|
1536
1701
|
export type {
|
|
1537
1702
|
ChannelSource,
|
|
1703
|
+
ReleaseOffscreen,
|
|
1704
|
+
ShaderBufferFormat,
|
|
1538
1705
|
ShaderExtractItem,
|
|
1539
1706
|
ShaderExtractOutput,
|
|
1540
1707
|
ShaderExtractPass,
|
|
@@ -1548,17 +1715,27 @@ export type {
|
|
|
1548
1715
|
SonicShaderConfig,
|
|
1549
1716
|
SonicShaderOutput,
|
|
1550
1717
|
} from "./types";
|
|
1551
|
-
export type {
|
|
1718
|
+
export type {
|
|
1719
|
+
SonicMediaRef,
|
|
1720
|
+
SonicFrameSource,
|
|
1721
|
+
} from "@supersoniks/concorde/core/utils/mediaRef";
|
|
1552
1722
|
export {
|
|
1553
1723
|
toMediaUrl,
|
|
1554
1724
|
cloneMediaRef,
|
|
1725
|
+
isFrameSource,
|
|
1726
|
+
mediaElementKey,
|
|
1555
1727
|
} from "@supersoniks/concorde/core/utils/mediaRef";
|
|
1556
1728
|
export {
|
|
1729
|
+
channelsUseSelf,
|
|
1557
1730
|
findPeaks,
|
|
1558
1731
|
meanRgba,
|
|
1732
|
+
parseBufferFormat,
|
|
1559
1733
|
parseExtractPass,
|
|
1560
1734
|
parseHoverParam,
|
|
1735
|
+
parseReleaseOffscreen,
|
|
1561
1736
|
roiToPixels,
|
|
1737
|
+
rgbaToUint8,
|
|
1738
|
+
shouldReleaseWhenOffscreen,
|
|
1562
1739
|
ShaderCompileError,
|
|
1563
1740
|
} from "./types";
|
|
1564
1741
|
|
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* ShaderToy-compatible GLSL ES 3.0 prelude (fragment body, sans `#version`).
|
|
3
|
+
* - `sonic-shader` préfixe `#version 300 es` via `buildFragmentSource`.
|
|
4
|
+
* - `sonic-3d` post passe le corps à Three `RawShaderMaterial` (GLSL3).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const GLSL_VERSION_300 = `#version 300 es
|
|
8
|
+
`;
|
|
9
|
+
|
|
10
|
+
/** Corps des uniforms / out (sans version). */
|
|
11
|
+
export const SHADERTOY_FRAGMENT_BODY = `precision highp float;
|
|
4
12
|
precision highp int;
|
|
5
13
|
precision mediump sampler2D;
|
|
6
14
|
|
|
@@ -22,11 +30,26 @@ uniform float uParam0;
|
|
|
22
30
|
uniform float uParam1;
|
|
23
31
|
uniform float uParam2;
|
|
24
32
|
uniform float uParam3;
|
|
33
|
+
/** Near / far caméra (0 dans sonic-shader standalone). */
|
|
34
|
+
uniform float uNear;
|
|
35
|
+
uniform float uFar;
|
|
25
36
|
|
|
26
37
|
out vec4 sonicFragColor;
|
|
27
38
|
|
|
39
|
+
/** Profondeur linéaire monde depuis une DepthTexture (0–1). */
|
|
40
|
+
float sonicLinearDepth(float d) {
|
|
41
|
+
float z = d * 2.0 - 1.0;
|
|
42
|
+
float n = max(uNear, 1e-4);
|
|
43
|
+
float f = max(uFar, n + 1e-4);
|
|
44
|
+
return (2.0 * n * f) / (f + n - z * (f - n));
|
|
45
|
+
}
|
|
46
|
+
|
|
28
47
|
`;
|
|
29
48
|
|
|
49
|
+
/** @deprecated Préférer SHADERTOY_FRAGMENT_BODY + buildFragmentSource. */
|
|
50
|
+
export const SHADERTOY_FRAGMENT_PRELUDE =
|
|
51
|
+
GLSL_VERSION_300 + SHADERTOY_FRAGMENT_BODY;
|
|
52
|
+
|
|
30
53
|
export const SHADERTOY_FRAGMENT_EPILOGUE = `
|
|
31
54
|
void main() {
|
|
32
55
|
mainImage(sonicFragColor, gl_FragCoord.xy);
|
|
@@ -41,12 +64,33 @@ void main() {
|
|
|
41
64
|
}
|
|
42
65
|
`;
|
|
43
66
|
|
|
44
|
-
|
|
67
|
+
/** Vertex Three RawShaderMaterial GLSL3 (fullscreen triangle via PlaneGeometry 2×2). */
|
|
68
|
+
export const THREE_FULLSCREEN_VERTEX = `precision highp float;
|
|
69
|
+
in vec3 position;
|
|
70
|
+
void main() {
|
|
71
|
+
gl_Position = vec4(position.xy, 0.0, 1.0);
|
|
72
|
+
}
|
|
73
|
+
`;
|
|
74
|
+
|
|
75
|
+
export function buildFragmentBody(common: string, userCode: string): string {
|
|
45
76
|
return (
|
|
46
|
-
|
|
77
|
+
SHADERTOY_FRAGMENT_BODY +
|
|
47
78
|
(common ? common + "\n" : "") +
|
|
48
79
|
userCode +
|
|
49
80
|
"\n" +
|
|
50
81
|
SHADERTOY_FRAGMENT_EPILOGUE
|
|
51
82
|
);
|
|
52
83
|
}
|
|
84
|
+
|
|
85
|
+
/** Source fragment WebGL2 native (`sonic-shader`). */
|
|
86
|
+
export function buildFragmentSource(common: string, userCode: string): string {
|
|
87
|
+
return GLSL_VERSION_300 + buildFragmentBody(common, userCode);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Source fragment pour Three RawShaderMaterial (GLSL3, sans #version). */
|
|
91
|
+
export function buildThreeFragmentSource(
|
|
92
|
+
common: string,
|
|
93
|
+
userCode: string,
|
|
94
|
+
): string {
|
|
95
|
+
return buildFragmentBody(common, userCode);
|
|
96
|
+
}
|