@supersoniks/concorde 4.9.98-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 +14687 -13905
- 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 +2773 -2547
- package/concorde-webgpu.bundle.js +43 -32
- package/concorde-webgpu.es.js +1819 -1553
- package/dist/concorde-3d.bundle.js +201 -152
- package/dist/concorde-3d.es.js +14687 -13905
- 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 +2773 -2547
- package/dist/concorde-webgpu.bundle.js +43 -32
- package/dist/concorde-webgpu.es.js +1819 -1553
- package/dist/js/core/components/functional/3d/3d.js +90 -2
- package/dist/js/core/components/functional/3d/3d.js.map +1 -1
- package/dist/js/core/components/functional/3d/constants.js +1 -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/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 +2 -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 +128 -14
- package/dist/js/core/components/functional/shader/gl-runtime.js.map +1 -1
- package/dist/js/core/components/functional/shader/shader.js +154 -57
- 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 +34 -1
- package/dist/js/core/components/functional/webgpu/webgpu.js.map +1 -1
- package/dist/js/core/utils/mediaRef.js +37 -0
- package/dist/js/core/utils/mediaRef.js.map +1 -1
- package/dist/types/core/components/functional/3d/3d.d.ts +26 -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/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.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 +9 -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 +33 -1
- package/dist/types/core/components/functional/shader/gl-runtime.d.ts.map +1 -1
- package/dist/types/core/components/functional/shader/shader.d.ts +28 -7
- 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 +29 -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 +7 -1
- package/dist/types/core/components/functional/webgpu/webgpu.d.ts.map +1 -1
- package/dist/types/core/utils/mediaRef.d.ts +15 -0
- package/dist/types/core/utils/mediaRef.d.ts.map +1 -1
- package/package.json +37 -1
- package/src/core/components/functional/3d/3d.md +34 -1
- package/src/core/components/functional/3d/3d.spec.ts +42 -0
- package/src/core/components/functional/3d/3d.ts +101 -3
- package/src/core/components/functional/3d/constants.ts +1 -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/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 +2 -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 +9 -0
- package/src/core/components/functional/3d/updated.ts +17 -1
- package/src/core/components/functional/shader/gl-runtime.ts +169 -12
- package/src/core/components/functional/shader/shader.md +27 -4
- package/src/core/components/functional/shader/shader.spec.ts +267 -0
- package/src/core/components/functional/shader/shader.ts +177 -55
- package/src/core/components/functional/shader/shadertoy-prelude.ts +49 -5
- package/src/core/components/functional/shader/types.ts +89 -12
- 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 +39 -1
- package/src/core/utils/mediaRef.spec.ts +25 -0
- package/src/core/utils/mediaRef.ts +45 -0
- package/src/docs/_misc/visual-stack.md +19 -1
- package/src/docs/components/docs-demo-sources.ts +28 -0
- package/src/docs/docs.ts +2 -0
- package/src/docs/example/docs-3d-post-depth-demo.ts +68 -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 +252 -2
- package/src/tsconfig.json +27 -0
- package/src/tsconfig.tsbuildinfo +1 -1
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
import { css, html, LitElement } from "lit";
|
|
4
4
|
import { customElement, property, state } from "lit/decorators.js";
|
|
5
5
|
import { PublisherManager } from "@supersoniks/concorde/utils";
|
|
6
|
+
import {
|
|
7
|
+
lookupLiveElement,
|
|
8
|
+
FrameConsumerRegistry,
|
|
9
|
+
} from "@supersoniks/concorde/core/utils/mediaRef";
|
|
6
10
|
import { Canvas2dFallbackRuntime } from "./canvas2d-fallback";
|
|
7
11
|
import { formBind } from "./form-bind";
|
|
8
12
|
import { WebGl2FallbackRuntime } from "./gl-fallback";
|
|
@@ -150,6 +154,7 @@ export class SonicWebGpu extends LitElement {
|
|
|
150
154
|
private resizeObserver: ResizeObserver | null = null;
|
|
151
155
|
private intersectionObserver: IntersectionObserver | null = null;
|
|
152
156
|
private rebuildToken = 0;
|
|
157
|
+
private frameConsumers = new FrameConsumerRegistry();
|
|
153
158
|
ready = false;
|
|
154
159
|
/** Évite deux boots concurrents (IO + rAF) qui disposent le fallback. */
|
|
155
160
|
private boot: Promise<void> | null = null;
|
|
@@ -204,6 +209,7 @@ export class SonicWebGpu extends LitElement {
|
|
|
204
209
|
this.removeEventListener("pointerenter", this.onPointerEnter);
|
|
205
210
|
this.unbindFormProvider();
|
|
206
211
|
this.revokeFrameUrl();
|
|
212
|
+
this.frameConsumers.clear();
|
|
207
213
|
this.frameOutSeq++;
|
|
208
214
|
this.frameOutBusy = false;
|
|
209
215
|
this.resizeObserver?.disconnect();
|
|
@@ -404,6 +410,10 @@ export class SonicWebGpu extends LitElement {
|
|
|
404
410
|
}
|
|
405
411
|
|
|
406
412
|
this.runtime = runtime;
|
|
413
|
+
const maybeGl2 = this.runtime as unknown as {
|
|
414
|
+
setElementResolver?: (fn: (key: string) => Element | null) => void;
|
|
415
|
+
};
|
|
416
|
+
maybeGl2.setElementResolver?.((key) => this.lookupElement(key));
|
|
407
417
|
const backend = runtime.backend as SonicWebGpuBackend;
|
|
408
418
|
this.activeBackend = backend;
|
|
409
419
|
let notice = "";
|
|
@@ -475,6 +485,21 @@ export class SonicWebGpu extends LitElement {
|
|
|
475
485
|
return canvas;
|
|
476
486
|
}
|
|
477
487
|
|
|
488
|
+
/** Résout `#id` dans getRootNode() puis document ; clés live `__sonic_frame_`. */
|
|
489
|
+
private lookupElement(key: string): Element | null {
|
|
490
|
+
if (!key.startsWith("#")) return null;
|
|
491
|
+
const live = lookupLiveElement(key);
|
|
492
|
+
if (live) return live;
|
|
493
|
+
const id = key.slice(1);
|
|
494
|
+
if (!id || id.startsWith("__sonic_frame_")) return null;
|
|
495
|
+
const root = this.getRootNode();
|
|
496
|
+
if (root instanceof Document || root instanceof ShadowRoot) {
|
|
497
|
+
const el = root.getElementById(id);
|
|
498
|
+
if (el) return el;
|
|
499
|
+
}
|
|
500
|
+
return typeof document !== "undefined" ? document.getElementById(id) : null;
|
|
501
|
+
}
|
|
502
|
+
|
|
478
503
|
private releaseRuntime() {
|
|
479
504
|
this.stopLoop();
|
|
480
505
|
this.ready = false;
|
|
@@ -486,6 +511,14 @@ export class SonicWebGpu extends LitElement {
|
|
|
486
511
|
this.canvasEl = null;
|
|
487
512
|
}
|
|
488
513
|
|
|
514
|
+
/** Enregistre les producteurs live pour play-offscreen auto. */
|
|
515
|
+
private syncFrameConsumers() {
|
|
516
|
+
const keys = [this.channel0, this.channel1, this.channel2, this.channel3];
|
|
517
|
+
this.frameConsumers.sync(
|
|
518
|
+
keys.filter((k) => k.startsWith("#")).map((k) => this.lookupElement(k)),
|
|
519
|
+
);
|
|
520
|
+
}
|
|
521
|
+
|
|
489
522
|
private async rebuild() {
|
|
490
523
|
if (!this.runtime) return;
|
|
491
524
|
const token = ++this.rebuildToken;
|
|
@@ -509,6 +542,7 @@ export class SonicWebGpu extends LitElement {
|
|
|
509
542
|
]);
|
|
510
543
|
}
|
|
511
544
|
if (token !== this.rebuildToken) return;
|
|
545
|
+
this.syncFrameConsumers();
|
|
512
546
|
this.errorMessage = "";
|
|
513
547
|
this.ready = true;
|
|
514
548
|
this.syncSize();
|
|
@@ -589,6 +623,9 @@ export class SonicWebGpu extends LitElement {
|
|
|
589
623
|
if (!this.startTime) this.startTime = now;
|
|
590
624
|
const time = (now - this.startTime) / 1000;
|
|
591
625
|
this.applyRemoteMouse();
|
|
626
|
+
if (this.runtime instanceof WebGpuRuntime) {
|
|
627
|
+
this.runtime.updateLiveChannels((key) => this.lookupElement(key));
|
|
628
|
+
}
|
|
592
629
|
this.runtime.draw({
|
|
593
630
|
width: w,
|
|
594
631
|
height: h,
|
|
@@ -662,7 +699,8 @@ export type {
|
|
|
662
699
|
} from "./types";
|
|
663
700
|
export { parseBackendPrefer, parseKernel, WebGpuCompileError } from "./types";
|
|
664
701
|
export { buildWgslSource, DEFAULT_MAIN_IMAGE } from "./wgsl-prelude";
|
|
665
|
-
export { WebGpuRuntime } from "./gpu-runtime";
|
|
702
|
+
export { WebGpuRuntime, channelTextureNeedsRecreate } from "./gpu-runtime";
|
|
666
703
|
export { WebGl2FallbackRuntime } from "./gl-fallback";
|
|
667
704
|
export { Canvas2dFallbackRuntime } from "./canvas2d-fallback";
|
|
668
705
|
export { ParticlesRuntime } from "./particles-runtime";
|
|
706
|
+
export { channelFormValue } from "./helpers";
|
|
@@ -36,6 +36,31 @@ describe("isFrameSource / mediaElementKey", () => {
|
|
|
36
36
|
expect(isFrameSource(null)).toBe(false);
|
|
37
37
|
});
|
|
38
38
|
|
|
39
|
+
it("FrameConsumerRegistry register / unregister", async () => {
|
|
40
|
+
const { FrameConsumerRegistry, isFrameConsumerHost } = await import(
|
|
41
|
+
"./mediaRef"
|
|
42
|
+
);
|
|
43
|
+
const tokens: object[] = [];
|
|
44
|
+
const host = {
|
|
45
|
+
registerFrameConsumer(t: object = {}) {
|
|
46
|
+
tokens.push(t);
|
|
47
|
+
},
|
|
48
|
+
unregisterFrameConsumer(t: object = {}) {
|
|
49
|
+
const i = tokens.indexOf(t);
|
|
50
|
+
if (i >= 0) tokens.splice(i, 1);
|
|
51
|
+
},
|
|
52
|
+
getFrameCanvas: () => null,
|
|
53
|
+
frameSeq: 0,
|
|
54
|
+
};
|
|
55
|
+
expect(isFrameConsumerHost(host)).toBe(true);
|
|
56
|
+
const reg = new FrameConsumerRegistry();
|
|
57
|
+
// FrameConsumerRegistry expects Element — cast for unit test
|
|
58
|
+
reg.sync([host as unknown as Element]);
|
|
59
|
+
expect(tokens.length).toBe(1);
|
|
60
|
+
reg.clear();
|
|
61
|
+
expect(tokens.length).toBe(0);
|
|
62
|
+
});
|
|
63
|
+
|
|
39
64
|
it("normalise element string / Element avec id", () => {
|
|
40
65
|
expect(mediaElementKey("#plateau")).toBe("#plateau");
|
|
41
66
|
expect(mediaElementKey("plateau")).toBe("#plateau");
|
|
@@ -29,6 +29,15 @@ export type SonicFrameSource = {
|
|
|
29
29
|
readonly frameSeq: number;
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Producteur de frames live qui peut rester actif hors viewport
|
|
34
|
+
* tant qu’un consommateur est enregistré (`sonic-3d` Lot 9).
|
|
35
|
+
*/
|
|
36
|
+
export type SonicFrameConsumerHost = {
|
|
37
|
+
registerFrameConsumer(token?: object): void;
|
|
38
|
+
unregisterFrameConsumer(token?: object): void;
|
|
39
|
+
};
|
|
40
|
+
|
|
32
41
|
export function isFrameSource(el: unknown): el is SonicFrameSource {
|
|
33
42
|
if (!el || typeof el !== "object") return false;
|
|
34
43
|
const o = el as SonicFrameSource;
|
|
@@ -37,6 +46,42 @@ export function isFrameSource(el: unknown): el is SonicFrameSource {
|
|
|
37
46
|
);
|
|
38
47
|
}
|
|
39
48
|
|
|
49
|
+
export function isFrameConsumerHost(el: unknown): el is SonicFrameConsumerHost {
|
|
50
|
+
if (!el || typeof el !== "object") return false;
|
|
51
|
+
const o = el as SonicFrameConsumerHost;
|
|
52
|
+
return (
|
|
53
|
+
typeof o.registerFrameConsumer === "function" &&
|
|
54
|
+
typeof o.unregisterFrameConsumer === "function"
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Suit les `#id` résolus → register/unregister auprès du producteur. */
|
|
59
|
+
export class FrameConsumerRegistry {
|
|
60
|
+
private tokens = new Map<Element, object>();
|
|
61
|
+
|
|
62
|
+
sync(elements: Iterable<Element | null | undefined>) {
|
|
63
|
+
const next = new Set<Element>();
|
|
64
|
+
for (const el of elements) {
|
|
65
|
+
if (el && isFrameConsumerHost(el)) next.add(el);
|
|
66
|
+
}
|
|
67
|
+
for (const [el, token] of [...this.tokens]) {
|
|
68
|
+
if (next.has(el)) continue;
|
|
69
|
+
if (isFrameConsumerHost(el)) el.unregisterFrameConsumer(token);
|
|
70
|
+
this.tokens.delete(el);
|
|
71
|
+
}
|
|
72
|
+
for (const el of next) {
|
|
73
|
+
if (this.tokens.has(el)) continue;
|
|
74
|
+
const token = {};
|
|
75
|
+
(el as unknown as SonicFrameConsumerHost).registerFrameConsumer(token);
|
|
76
|
+
this.tokens.set(el, token);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
clear() {
|
|
81
|
+
this.sync([]);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
40
85
|
/** Clés synthétiques pour Elements DP sans `id` (`#__sonic_frame_N`). */
|
|
41
86
|
const LIVE_PREFIX = "#__sonic_frame_";
|
|
42
87
|
let liveSeq = 0;
|
|
@@ -44,9 +44,27 @@ Also accepted: `<img>`, `<video>`, `<canvas>`, or another Concorde host that imp
|
|
|
44
44
|
|
|
45
45
|
<docs-lit-demo for="docs-3d-shader-live-demo"></docs-lit-demo>
|
|
46
46
|
|
|
47
|
+
## 3D → WebGPU live
|
|
48
|
+
|
|
49
|
+
Same `#id` bridge as the shader: `sonic-webgpu channel0="#plateau-gpu"` copies the 3D canvas each `frameSeq` via `copyExternalImageToTexture` (persistent texture — no recreate when size is stable).
|
|
50
|
+
|
|
51
|
+
<docs-lit-demo for="docs-3d-webgpu-live-demo"></docs-lit-demo>
|
|
52
|
+
|
|
53
|
+
## Post FX + depth (in sonic-3d)
|
|
54
|
+
|
|
55
|
+
Scene → offscreen color + depth → GLSL passes (`post-*`) in the same WebGL context. Use `post-image-ch1="depth"` for edge / DoF-style effects without a second component.
|
|
56
|
+
|
|
57
|
+
<docs-lit-demo for="docs-3d-post-depth-demo"></docs-lit-demo>
|
|
58
|
+
|
|
47
59
|
## Harris → patches → WebGPU
|
|
48
60
|
|
|
49
|
-
`sonic-shader` detects corners (Harris) and extracts patches → `channel0…3` on `sonic-webgpu` (`kernel="image"`): GPU mosaic.
|
|
61
|
+
`sonic-shader` detects corners (Harris, `buffer-format="rgba16f"` + NMS 5×5 / shape filter) and extracts patches → `channel0…3` on `sonic-webgpu` (`kernel="image"`): GPU mosaic.
|
|
62
|
+
|
|
63
|
+
Use `buffer-format="rgba16f"` so signed `IxIy` / non-clamped `Ix²` survive the buffer (RGBA8 zeros negatives and saturates). See [Shader — buffer precision](#core/components/functional/shader/shader.md/shader).
|
|
64
|
+
|
|
65
|
+
Channel rebinds and `release-offscreen="auto"` (keep FBO state when a pass uses `self`) : [Shader — état et visibilité](#core/components/functional/shader/shader.md/shader).
|
|
66
|
+
|
|
67
|
+
`sonic-3d` live sources keep playing off-screen when a `#id` consumer is registered (or `play-offscreen`) — see [3D — bridging](#core/components/functional/3d/3d.md/3d).
|
|
50
68
|
|
|
51
69
|
<docs-lit-demo for="docs-harris-webgpu-demo"></docs-lit-demo>
|
|
52
70
|
|
|
@@ -223,6 +223,22 @@ export const DOCS_LIT_DEMO_REGISTRY: Record<string, DocsLitDemoConfig> = {
|
|
|
223
223
|
},
|
|
224
224
|
],
|
|
225
225
|
},
|
|
226
|
+
"docs-3d-webgpu-live-demo": {
|
|
227
|
+
sources: [
|
|
228
|
+
{
|
|
229
|
+
path: "src/docs/example/docs-3d-webgpu-live-demo.ts",
|
|
230
|
+
label: "3D → webgpu live",
|
|
231
|
+
},
|
|
232
|
+
],
|
|
233
|
+
},
|
|
234
|
+
"docs-3d-post-depth-demo": {
|
|
235
|
+
sources: [
|
|
236
|
+
{
|
|
237
|
+
path: "src/docs/example/docs-3d-post-depth-demo.ts",
|
|
238
|
+
label: "3D post depth edges",
|
|
239
|
+
},
|
|
240
|
+
],
|
|
241
|
+
},
|
|
226
242
|
"docs-webgpu-demo": {
|
|
227
243
|
sources: [
|
|
228
244
|
{
|
|
@@ -506,6 +522,18 @@ export const DOCS_DEMO_SOURCE_REGISTRY: Record<string, DocsSource[]> = {
|
|
|
506
522
|
label: "3d → shader live",
|
|
507
523
|
},
|
|
508
524
|
],
|
|
525
|
+
"docs-3d-webgpu-live-demo": [
|
|
526
|
+
{
|
|
527
|
+
path: "src/docs/example/docs-3d-webgpu-live-demo.ts",
|
|
528
|
+
label: "3d → webgpu live",
|
|
529
|
+
},
|
|
530
|
+
],
|
|
531
|
+
"docs-3d-post-depth-demo": [
|
|
532
|
+
{
|
|
533
|
+
path: "src/docs/example/docs-3d-post-depth-demo.ts",
|
|
534
|
+
label: "3d post depth",
|
|
535
|
+
},
|
|
536
|
+
],
|
|
509
537
|
"docs-webgpu-demo": [
|
|
510
538
|
{ path: "src/docs/example/docs-webgpu-demo.ts", label: "webgpu demo" },
|
|
511
539
|
],
|
package/src/docs/docs.ts
CHANGED
|
@@ -22,6 +22,8 @@ import "./example/docs-shader-demos";
|
|
|
22
22
|
import "./example/docs-webgpu-demo";
|
|
23
23
|
import "./example/docs-visual-stack-demo";
|
|
24
24
|
import "./example/docs-3d-shader-live-demo";
|
|
25
|
+
import "./example/docs-3d-webgpu-live-demo";
|
|
26
|
+
import "./example/docs-3d-post-depth-demo";
|
|
25
27
|
import "./example/docs-harris-webgpu-demo";
|
|
26
28
|
import "./example/docs-router-demos";
|
|
27
29
|
import "./example/docs-submit-demos";
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Démo Lot 2 : post FX dans sonic-3d avec canal depth (contours).
|
|
3
|
+
*/
|
|
4
|
+
import { css, html, LitElement } from "lit";
|
|
5
|
+
import { customElement } from "lit/decorators.js";
|
|
6
|
+
import { tailwind } from "../tailwind";
|
|
7
|
+
import "../../core/components/functional/3d/3d";
|
|
8
|
+
import { DEMO_3D_STYLES, HELMET_GLB } from "./docs-3d-shared";
|
|
9
|
+
|
|
10
|
+
const DEPTH_EDGE = `
|
|
11
|
+
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
12
|
+
vec2 uv = fragCoord / iResolution.xy;
|
|
13
|
+
vec2 px = 1.0 / max(iResolution.xy, vec2(1.0));
|
|
14
|
+
vec3 col = texture(iChannel0, uv).rgb;
|
|
15
|
+
|
|
16
|
+
float dC = texture(iChannel1, uv).r;
|
|
17
|
+
float dL = texture(iChannel1, uv - px * vec2(1.0, 0.0)).r;
|
|
18
|
+
float dR = texture(iChannel1, uv + px * vec2(1.0, 0.0)).r;
|
|
19
|
+
float dU = texture(iChannel1, uv + px * vec2(0.0, 1.0)).r;
|
|
20
|
+
float dD = texture(iChannel1, uv - px * vec2(0.0, 1.0)).r;
|
|
21
|
+
float edge = length(vec2(dR - dL, dU - dD));
|
|
22
|
+
edge = smoothstep(0.002 + uParam0 * 0.02, 0.02 + uParam0 * 0.05, edge);
|
|
23
|
+
|
|
24
|
+
vec3 ink = vec3(0.05, 0.95, 1.0);
|
|
25
|
+
col = mix(col, ink, edge * 0.85);
|
|
26
|
+
col *= 0.92 + 0.08 * sin(iTime * 1.5);
|
|
27
|
+
fragColor = vec4(col, 1.0);
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
@customElement("docs-3d-post-depth-demo")
|
|
32
|
+
export class Docs3dPostDepthDemo extends LitElement {
|
|
33
|
+
static styles = [
|
|
34
|
+
tailwind,
|
|
35
|
+
DEMO_3D_STYLES,
|
|
36
|
+
css`
|
|
37
|
+
sonic-3d {
|
|
38
|
+
width: 100%;
|
|
39
|
+
}
|
|
40
|
+
`,
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
render() {
|
|
44
|
+
return html`
|
|
45
|
+
<div class="flex flex-col gap-2">
|
|
46
|
+
<sonic-3d
|
|
47
|
+
src=${HELMET_GLB}
|
|
48
|
+
camera="orbit"
|
|
49
|
+
auto-rotate
|
|
50
|
+
play
|
|
51
|
+
pick
|
|
52
|
+
min-distance="1"
|
|
53
|
+
max-distance="10"
|
|
54
|
+
aspect-ratio="16/10"
|
|
55
|
+
post-image=${DEPTH_EDGE}
|
|
56
|
+
post-image-ch0="scene"
|
|
57
|
+
post-image-ch1="depth"
|
|
58
|
+
param0="0.55"
|
|
59
|
+
></sonic-3d>
|
|
60
|
+
<p class="text-sm text-neutral-500">
|
|
61
|
+
Post FX interne (<code>post-image</code>) : couleur
|
|
62
|
+
<code>scene</code> + discontinuités sur <code>depth</code> — pas de
|
|
63
|
+
copie vers un second composant.
|
|
64
|
+
</p>
|
|
65
|
+
</div>
|
|
66
|
+
`;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Démo pont live : sonic-3d → sonic-webgpu via channel0="#plateau-gpu"
|
|
3
|
+
* (copyExternalImageToTexture chaque frameSeq, texture réutilisée).
|
|
4
|
+
*/
|
|
5
|
+
import { css, html, LitElement } from "lit";
|
|
6
|
+
import { customElement } from "lit/decorators.js";
|
|
7
|
+
import { tailwind } from "../tailwind";
|
|
8
|
+
import "../../core/components/functional/3d/3d";
|
|
9
|
+
import "../../core/components/functional/webgpu/webgpu";
|
|
10
|
+
import { DEMO_3D_STYLES, HELMET_GLB } from "./docs-3d-shared";
|
|
11
|
+
|
|
12
|
+
/** Tint + vignette — prouve le sampling live du canvas 3D. */
|
|
13
|
+
const LIVE_WGSL = `
|
|
14
|
+
fn mainImage(uv: vec2f, fragCoord: vec2f) -> vec4f {
|
|
15
|
+
_ = fragCoord;
|
|
16
|
+
let c = iChannel0(uv).rgb;
|
|
17
|
+
let mid = uv - vec2f(0.5);
|
|
18
|
+
let vig = smoothstep(1.1, 0.35, length(mid));
|
|
19
|
+
let pulse = 0.92 + 0.08 * sin(u.time * 2.0);
|
|
20
|
+
let tint = vec3f(0.15, 0.85, 1.0);
|
|
21
|
+
let edge = length(c - iChannel0(uv + mid * 0.012).rgb);
|
|
22
|
+
var col = mix(c, c * tint * 1.15, clamp(edge * 4.0, 0.0, 0.55));
|
|
23
|
+
col *= vig * pulse;
|
|
24
|
+
return vec4f(col, 1.0);
|
|
25
|
+
}
|
|
26
|
+
`;
|
|
27
|
+
|
|
28
|
+
@customElement("docs-3d-webgpu-live-demo")
|
|
29
|
+
export class Docs3dWebgpuLiveDemo extends LitElement {
|
|
30
|
+
static styles = [
|
|
31
|
+
tailwind,
|
|
32
|
+
DEMO_3D_STYLES,
|
|
33
|
+
css`
|
|
34
|
+
.grid {
|
|
35
|
+
display: grid;
|
|
36
|
+
gap: 0.75rem;
|
|
37
|
+
grid-template-columns: 1fr;
|
|
38
|
+
}
|
|
39
|
+
@media (min-width: 720px) {
|
|
40
|
+
.grid {
|
|
41
|
+
grid-template-columns: 1fr 1fr;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
sonic-3d,
|
|
45
|
+
sonic-webgpu {
|
|
46
|
+
width: 100%;
|
|
47
|
+
border-radius: 0.5rem;
|
|
48
|
+
overflow: hidden;
|
|
49
|
+
}
|
|
50
|
+
`,
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
render() {
|
|
54
|
+
return html`
|
|
55
|
+
<div class="flex flex-col gap-2">
|
|
56
|
+
<div class="grid">
|
|
57
|
+
<sonic-3d
|
|
58
|
+
id="plateau-gpu"
|
|
59
|
+
src=${HELMET_GLB}
|
|
60
|
+
camera="orbit"
|
|
61
|
+
auto-rotate
|
|
62
|
+
play
|
|
63
|
+
min-distance="1"
|
|
64
|
+
max-distance="10"
|
|
65
|
+
aspect-ratio="16/10"
|
|
66
|
+
></sonic-3d>
|
|
67
|
+
<sonic-webgpu
|
|
68
|
+
play
|
|
69
|
+
kernel="image"
|
|
70
|
+
channel0="#plateau-gpu"
|
|
71
|
+
.shader=${LIVE_WGSL}
|
|
72
|
+
aspect-ratio="16/10"
|
|
73
|
+
></sonic-webgpu>
|
|
74
|
+
</div>
|
|
75
|
+
<p class="text-sm text-neutral-500">
|
|
76
|
+
Live bridge: <code>channel0="#plateau-gpu"</code> →
|
|
77
|
+
<code>copyExternalImageToTexture</code> (texture persistante, pas de
|
|
78
|
+
JPEG). Gauche = <code>sonic-3d</code>, droite = tint / edge WebGPU.
|
|
79
|
+
</p>
|
|
80
|
+
</div>
|
|
81
|
+
`;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -17,6 +17,7 @@ const sample = (file: string) =>
|
|
|
17
17
|
new URL(`/docs/shader-samples/${file}`, location.origin).href;
|
|
18
18
|
|
|
19
19
|
const HARRIS_BUFFER_A = `
|
|
20
|
+
// Tenseur structure (Ix², Iy², IxIy) — nécessite buffer-format=rgba16f (IxIy signé).
|
|
20
21
|
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
21
22
|
vec2 uv = fragCoord / iResolution.xy;
|
|
22
23
|
vec2 px = 1.0 / iResolution.xy;
|
|
@@ -30,11 +31,12 @@ void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
|
30
31
|
float br = dot(texture(iChannel0, uv + px * vec2( 1.0, -1.0)).rgb, vec3(0.299, 0.587, 0.114));
|
|
31
32
|
float Ix = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
|
|
32
33
|
float Iy = (tl + 2.0 * t + tr) - (bl + 2.0 * b + br);
|
|
33
|
-
fragColor = vec4(Ix * Ix, Iy * Iy, Ix * Iy, 1.0)
|
|
34
|
+
fragColor = vec4(Ix * Ix, Iy * Iy, Ix * Iy, 1.0);
|
|
34
35
|
}
|
|
35
36
|
`;
|
|
36
37
|
|
|
37
38
|
const HARRIS_BUFFER_B = `
|
|
39
|
+
// Lissage gaussien 5×5 du tenseur (σ ≈ 1.26).
|
|
38
40
|
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
39
41
|
vec2 uv = fragCoord / iResolution.xy;
|
|
40
42
|
vec2 px = 1.0 / iResolution.xy;
|
|
@@ -51,58 +53,50 @@ void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
|
51
53
|
}
|
|
52
54
|
`;
|
|
53
55
|
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
+
const HARRIS_EXTRACT_MASK = `
|
|
57
|
+
// Réponse Harris + filtre de forme + max local STRICT 5×5 (départage par position).
|
|
58
|
+
float harrisAt(vec2 uv) {
|
|
56
59
|
vec3 t = texture(iChannel0, uv).rgb;
|
|
57
60
|
float k = max(uParam1, 0.001);
|
|
58
61
|
float det = t.x * t.y - t.z * t.z;
|
|
59
62
|
float trace = t.x + t.y;
|
|
60
|
-
|
|
63
|
+
float R = det - k * trace * trace;
|
|
64
|
+
// Forme ≈ 4 det / trace² ∈ [0,1] : ~1 coin isotropique, ~0 bord.
|
|
65
|
+
float shape = (trace > 1e-5) ? clamp(4.0 * det / (trace * trace), 0.0, 1.0) : 0.0;
|
|
66
|
+
if (R < max(uParam0, 1e-6) || shape < 0.45) return 0.0;
|
|
67
|
+
return R;
|
|
61
68
|
}
|
|
62
69
|
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
63
70
|
vec2 uv = fragCoord / iResolution.xy;
|
|
64
71
|
vec2 px = 1.0 / iResolution.xy;
|
|
65
|
-
|
|
66
|
-
float
|
|
67
|
-
float
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
float R = harrisAt(uv);
|
|
73
|
+
float thr = max(uParam0, 1e-6);
|
|
74
|
+
float isMax = step(thr, R);
|
|
75
|
+
for (int j = -2; j <= 2; j++) {
|
|
76
|
+
for (int i = -2; i <= 2; i++) {
|
|
77
|
+
if (i == 0 && j == 0) continue;
|
|
78
|
+
float n = harrisAt(uv + px * vec2(float(i), float(j)));
|
|
79
|
+
bool before = j < 0 || (j == 0 && i < 0);
|
|
80
|
+
if (n > R || (before && abs(n - R) < 1e-8)) isMax = 0.0;
|
|
73
81
|
}
|
|
74
82
|
}
|
|
75
|
-
float
|
|
76
|
-
float
|
|
77
|
-
|
|
78
|
-
col = mix(col, vec3(0.15, 1.0, 0.45), isCorner * overlay);
|
|
79
|
-
fragColor = vec4(col, 1.0);
|
|
83
|
+
float Rp = max(R, 0.0);
|
|
84
|
+
float score = isMax * (Rp / (Rp + thr * 4.0));
|
|
85
|
+
fragColor = vec4(vec3(score), 1.0);
|
|
80
86
|
}
|
|
81
87
|
`;
|
|
82
88
|
|
|
83
|
-
const
|
|
84
|
-
float harrisR(vec2 uv) {
|
|
85
|
-
vec3 t = texture(iChannel0, uv).rgb;
|
|
86
|
-
float k = max(uParam1, 0.001);
|
|
87
|
-
float det = t.x * t.y - t.z * t.z;
|
|
88
|
-
float trace = t.x + t.y;
|
|
89
|
-
return det - k * trace * trace;
|
|
90
|
-
}
|
|
89
|
+
const HARRIS_IMAGE = `
|
|
91
90
|
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
92
91
|
vec2 uv = fragCoord / iResolution.xy;
|
|
93
|
-
|
|
94
|
-
float
|
|
95
|
-
float
|
|
96
|
-
float
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
float isCorner = step(thr, R) * step(Rmax - 1e-6, R);
|
|
103
|
-
float Rp = max(R, 0.0);
|
|
104
|
-
float score = isCorner * (Rp / (Rp + thr * 3.0));
|
|
105
|
-
fragColor = vec4(vec3(score), 1.0);
|
|
92
|
+
vec3 video = texture(iChannel1, uv).rgb;
|
|
93
|
+
float score = texture(iChannel0, uv).r;
|
|
94
|
+
float overlay = clamp(uParam2, 0.0, 1.0);
|
|
95
|
+
float heat = smoothstep(0.05, 0.55, score);
|
|
96
|
+
vec3 col = mix(video, video * vec3(1.12, 0.4, 1.05) + vec3(0.28, 0.04, 0.35) * heat, heat * overlay * 0.55);
|
|
97
|
+
// Points isolés (pas de traînées de bords).
|
|
98
|
+
col = mix(col, vec3(0.12, 1.0, 0.42), step(0.08, score) * overlay);
|
|
99
|
+
fragColor = vec4(col, 1.0);
|
|
106
100
|
}
|
|
107
101
|
`;
|
|
108
102
|
|
|
@@ -285,9 +279,9 @@ export class DocsHarrisWebgpuDemo extends LitElement {
|
|
|
285
279
|
if (this.active) return;
|
|
286
280
|
this.active = true;
|
|
287
281
|
set(shaderKey, {
|
|
288
|
-
param0: 0.
|
|
289
|
-
param1: 0.
|
|
290
|
-
param2: 0.
|
|
282
|
+
param0: 0.015,
|
|
283
|
+
param1: 0.05,
|
|
284
|
+
param2: 0.9,
|
|
291
285
|
extractCount: 0,
|
|
292
286
|
extractSeq: 0,
|
|
293
287
|
extracts: [],
|
|
@@ -299,7 +293,7 @@ export class DocsHarrisWebgpuDemo extends LitElement {
|
|
|
299
293
|
.map((it) => it.blobUrl || it.url)
|
|
300
294
|
.filter((u): u is string => typeof u === "string" && u.length > 0)
|
|
301
295
|
.slice(0, 4);
|
|
302
|
-
this.patches = items.slice(0,
|
|
296
|
+
this.patches = items.slice(0, 8);
|
|
303
297
|
set(gpuKey, {
|
|
304
298
|
param0: 0.55,
|
|
305
299
|
param1: Math.max(1, urls.length),
|
|
@@ -331,7 +325,7 @@ export class DocsHarrisWebgpuDemo extends LitElement {
|
|
|
331
325
|
.map((it) => it.blobUrl || it.url)
|
|
332
326
|
.filter((u): u is string => typeof u === "string" && u.length > 0)
|
|
333
327
|
.slice(0, 4);
|
|
334
|
-
this.patches = items.slice(0,
|
|
328
|
+
this.patches = items.slice(0, 8);
|
|
335
329
|
set(gpuKey, {
|
|
336
330
|
param0: 0.55,
|
|
337
331
|
param1: Math.max(1, urls.length),
|
|
@@ -355,8 +349,8 @@ export class DocsHarrisWebgpuDemo extends LitElement {
|
|
|
355
349
|
<span class="text-neutral-400">(mosaïque)</span>
|
|
356
350
|
</div>
|
|
357
351
|
<p class="m-0 text-sm text-neutral-600">
|
|
358
|
-
Vidéo →
|
|
359
|
-
|
|
352
|
+
Vidéo → Harris (<code>rgba16f</code>, NMS 5×5 + filtre forme) →
|
|
353
|
+
crops → collage GPU. Coins isolés, pas de traînées sur les bords.
|
|
360
354
|
</p>
|
|
361
355
|
<sonic-button type="primary" size="sm" @click=${this.start}
|
|
362
356
|
>Try</sonic-button
|
|
@@ -388,8 +382,8 @@ export class DocsHarrisWebgpuDemo extends LitElement {
|
|
|
388
382
|
type="range"
|
|
389
383
|
name="param0"
|
|
390
384
|
min="0.002"
|
|
391
|
-
max="0.
|
|
392
|
-
step="0.
|
|
385
|
+
max="0.06"
|
|
386
|
+
step="0.001"
|
|
393
387
|
class="flex-1"
|
|
394
388
|
></sonic-input>
|
|
395
389
|
</div>
|
|
@@ -399,7 +393,7 @@ export class DocsHarrisWebgpuDemo extends LitElement {
|
|
|
399
393
|
type="range"
|
|
400
394
|
name="param1"
|
|
401
395
|
min="0.02"
|
|
402
|
-
max="0.
|
|
396
|
+
max="0.12"
|
|
403
397
|
step="0.005"
|
|
404
398
|
class="flex-1"
|
|
405
399
|
></sonic-input>
|
|
@@ -409,19 +403,21 @@ export class DocsHarrisWebgpuDemo extends LitElement {
|
|
|
409
403
|
<div class="stack">
|
|
410
404
|
<div class="label-bar">
|
|
411
405
|
<span
|
|
412
|
-
><code>sonic-shader</code> Harris
|
|
406
|
+
><code>sonic-shader</code> Harris
|
|
407
|
+
<code>rgba16f</code> + extract</span
|
|
413
408
|
>
|
|
414
|
-
<span class="text-neutral-400">coins → peaks</span>
|
|
409
|
+
<span class="text-neutral-400">coins isolés → peaks</span>
|
|
415
410
|
</div>
|
|
416
411
|
<sonic-shader
|
|
417
412
|
play
|
|
413
|
+
buffer-format="rgba16f"
|
|
418
414
|
.mouse=${false}
|
|
419
415
|
extract
|
|
420
416
|
extract-bitmaps
|
|
421
417
|
extract-mask="buffer-c"
|
|
422
418
|
extract-source="image"
|
|
423
|
-
extract-threshold="0.
|
|
424
|
-
extract-max="
|
|
419
|
+
extract-threshold="0.08"
|
|
420
|
+
extract-max="8"
|
|
425
421
|
extract-patch="56"
|
|
426
422
|
extract-interval="400"
|
|
427
423
|
extract-data-provider=${shaderKey.path}
|
|
@@ -430,7 +426,7 @@ export class DocsHarrisWebgpuDemo extends LitElement {
|
|
|
430
426
|
buffer-a-ch0=${video}
|
|
431
427
|
buffer-b-ch0="buffer-a"
|
|
432
428
|
buffer-c-ch0="buffer-b"
|
|
433
|
-
image-ch0="buffer-
|
|
429
|
+
image-ch0="buffer-c"
|
|
434
430
|
image-ch1=${video}
|
|
435
431
|
.bufferA=${HARRIS_BUFFER_A}
|
|
436
432
|
.bufferB=${HARRIS_BUFFER_B}
|
|
@@ -473,8 +469,10 @@ export class DocsHarrisWebgpuDemo extends LitElement {
|
|
|
473
469
|
</div>
|
|
474
470
|
|
|
475
471
|
<p class="m-0 text-xs text-neutral-500">
|
|
476
|
-
|
|
477
|
-
|
|
472
|
+
<code>buffer-format="rgba16f"</code> conserve
|
|
473
|
+
<code>IxIy</code> signé ; NMS 5×5 + forme
|
|
474
|
+
<code>4·det/trace²</code> → points isolés. Extract → DP →
|
|
475
|
+
<code>channel0…3</code>.
|
|
478
476
|
</p>
|
|
479
477
|
</div>
|
|
480
478
|
`;
|