layershift 0.2.2 → 0.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 +14 -0
- package/dist/components/layershift.js +921 -647
- package/dist/npm/layershift.es.js +3354 -2266
- package/dist/types/components/layershift/global.d.ts +2 -2
- package/dist/types/components/layershift/index.d.ts +5 -1
- package/dist/types/components/layershift/index.d.ts.map +1 -1
- package/dist/types/components/layershift/layershift-element.d.ts +41 -10
- package/dist/types/components/layershift/layershift-element.d.ts.map +1 -1
- package/dist/types/components/layershift/lifecycle.d.ts +6 -0
- package/dist/types/components/layershift/lifecycle.d.ts.map +1 -1
- package/dist/types/components/layershift/portal-element.d.ts +13 -4
- package/dist/types/components/layershift/portal-element.d.ts.map +1 -1
- package/dist/types/components/layershift/types.d.ts +30 -9
- package/dist/types/components/layershift/types.d.ts.map +1 -1
- package/dist/types/depth-analysis.d.ts +10 -6
- package/dist/types/depth-analysis.d.ts.map +1 -1
- package/dist/types/depth-effect-renderer.d.ts +186 -0
- package/dist/types/depth-effect-renderer.d.ts.map +1 -0
- package/dist/types/depth-estimator.d.ts +96 -0
- package/dist/types/depth-estimator.d.ts.map +1 -0
- package/dist/types/input-handler.d.ts +8 -2
- package/dist/types/input-handler.d.ts.map +1 -1
- package/dist/types/jfa-distance-field.d.ts +78 -0
- package/dist/types/jfa-distance-field.d.ts.map +1 -0
- package/dist/types/media-source.d.ts +76 -0
- package/dist/types/media-source.d.ts.map +1 -0
- package/dist/types/portal-renderer.d.ts +65 -66
- package/dist/types/portal-renderer.d.ts.map +1 -1
- package/dist/types/precomputed-depth.d.ts +14 -51
- package/dist/types/precomputed-depth.d.ts.map +1 -1
- package/dist/types/quality.d.ts +95 -0
- package/dist/types/quality.d.ts.map +1 -0
- package/dist/types/render-pass.d.ts +171 -0
- package/dist/types/render-pass.d.ts.map +1 -0
- package/dist/types/renderer-base.d.ts +129 -0
- package/dist/types/renderer-base.d.ts.map +1 -0
- package/dist/types/shared/channel-to-renderer.d.ts +72 -0
- package/dist/types/shared/channel-to-renderer.d.ts.map +1 -0
- package/dist/types/shared/filter-config.d.ts +184 -0
- package/dist/types/shared/filter-config.d.ts.map +1 -0
- package/dist/types/video-source.d.ts +0 -1
- package/dist/types/video-source.d.ts.map +1 -1
- package/dist/types/webgl-utils.d.ts +29 -0
- package/dist/types/webgl-utils.d.ts.map +1 -0
- package/package.json +31 -5
- package/dist/types/parallax-renderer.d.ts +0 -175
- package/dist/types/parallax-renderer.d.ts.map +0 -1
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adaptive Quality Scaling — device capability probing and tier classification.
|
|
3
|
+
*
|
|
4
|
+
* Probes WebGL context + navigator APIs once at init time, classifies the
|
|
5
|
+
* device into a quality tier (high / medium / low), and resolves concrete
|
|
6
|
+
* parameters that both renderers and Web Components consume to adjust:
|
|
7
|
+
*
|
|
8
|
+
* - **Render resolution** — DPR cap (2.0 / 1.5 / 1.0)
|
|
9
|
+
* - **Depth resolution** — depth texture max dimension (512 / 512 / 256)
|
|
10
|
+
* - **Sample count** — POM steps (16 / 16 / 8), bilateral kernel (5×5 / 5×5 / 3×3)
|
|
11
|
+
* - **JFA resolution** — distance field divisor (2 / 2 / 4) for portal effect
|
|
12
|
+
*
|
|
13
|
+
* Override precedence (unchanged): explicit config > quality-derived > calibrated defaults.
|
|
14
|
+
*
|
|
15
|
+
* @see ADR-012 for the architectural decision and rationale.
|
|
16
|
+
*/
|
|
17
|
+
/** Device quality classification. */
|
|
18
|
+
export type QualityTier = 'high' | 'medium' | 'low';
|
|
19
|
+
/** Concrete rendering parameters resolved from a quality tier. */
|
|
20
|
+
export interface QualityParams {
|
|
21
|
+
readonly tier: QualityTier;
|
|
22
|
+
/** Maximum device pixel ratio (2.0 / 1.5 / 1.0). */
|
|
23
|
+
readonly dprCap: number;
|
|
24
|
+
/** Maximum depth texture dimension — depth maps larger than this are downscaled (512 / 512 / 256). */
|
|
25
|
+
readonly depthMaxDim: number;
|
|
26
|
+
/** POM ray-march step count (16 / 16 / 8). */
|
|
27
|
+
readonly pomSteps: number;
|
|
28
|
+
/** Bilateral filter kernel radius in texels — kernel is (2r+1)×(2r+1) (2 / 2 / 1). */
|
|
29
|
+
readonly bilateralRadius: number;
|
|
30
|
+
/** JFA distance field resolution divisor (2 = half-res, 4 = quarter-res). */
|
|
31
|
+
readonly jfaDivisor: number;
|
|
32
|
+
}
|
|
33
|
+
/** Raw device capability probe results. */
|
|
34
|
+
export interface DeviceCapabilities {
|
|
35
|
+
/** GPU renderer string from WEBGL_debug_renderer_info, or 'unknown'. */
|
|
36
|
+
readonly gpuRenderer: string;
|
|
37
|
+
/** GL_MAX_TEXTURE_SIZE. */
|
|
38
|
+
readonly maxTextureSize: number;
|
|
39
|
+
/** navigator.hardwareConcurrency (logical cores), or 0 if unavailable. */
|
|
40
|
+
readonly hardwareConcurrency: number;
|
|
41
|
+
/** navigator.deviceMemory in GB, or 0 if unavailable. */
|
|
42
|
+
readonly deviceMemory: number;
|
|
43
|
+
/** window.devicePixelRatio. */
|
|
44
|
+
readonly devicePixelRatio: number;
|
|
45
|
+
/** Total screen pixels (width × height). */
|
|
46
|
+
readonly screenPixels: number;
|
|
47
|
+
/** Whether the device appears to be mobile (touch + small screen). */
|
|
48
|
+
readonly isMobile: boolean;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Probe device capabilities from the WebGL context and navigator APIs.
|
|
52
|
+
*
|
|
53
|
+
* This is intentionally lightweight — it reads values that are already
|
|
54
|
+
* available (no async, no benchmarks). Called once at init time.
|
|
55
|
+
*/
|
|
56
|
+
export declare function probeCapabilities(gl: WebGL2RenderingContext): DeviceCapabilities;
|
|
57
|
+
/**
|
|
58
|
+
* Classify device capabilities into a quality tier using a score-based heuristic.
|
|
59
|
+
*
|
|
60
|
+
* Weighted signals are summed to produce a score:
|
|
61
|
+
* - Score >= 0 → high
|
|
62
|
+
* - Score -25 to -1 → medium
|
|
63
|
+
* - Score < -25 → low
|
|
64
|
+
*/
|
|
65
|
+
export declare function classifyDevice(caps: DeviceCapabilities): QualityTier;
|
|
66
|
+
/**
|
|
67
|
+
* Resolve quality parameters for a renderer.
|
|
68
|
+
*
|
|
69
|
+
* - If `quality` is a specific tier ('high' | 'medium' | 'low'), return
|
|
70
|
+
* that tier's parameters directly (no probing).
|
|
71
|
+
* - If `quality` is 'auto' or undefined, probe device capabilities and
|
|
72
|
+
* classify automatically.
|
|
73
|
+
*
|
|
74
|
+
* Called once per renderer at construction time. The returned params are
|
|
75
|
+
* stored as `private readonly qualityParams` and read during init and resize.
|
|
76
|
+
*
|
|
77
|
+
* @param gl - WebGL 2 rendering context (used for GPU probing).
|
|
78
|
+
* @param quality - Explicit tier, 'auto', or undefined (defaults to 'auto').
|
|
79
|
+
*/
|
|
80
|
+
export declare function resolveQuality(gl: WebGL2RenderingContext, quality?: 'auto' | QualityTier): QualityParams;
|
|
81
|
+
/**
|
|
82
|
+
* Probe device capabilities from a WebGPU adapter.
|
|
83
|
+
*
|
|
84
|
+
* Extracts the same `DeviceCapabilities` shape as the WebGL2 probe,
|
|
85
|
+
* allowing the shared `classifyDevice()` scoring logic to work for both backends.
|
|
86
|
+
*/
|
|
87
|
+
export declare function probeCapabilitiesWebGPU(adapterInfo: GPUAdapterInfo): DeviceCapabilities;
|
|
88
|
+
/**
|
|
89
|
+
* Resolve quality parameters for a WebGPU renderer.
|
|
90
|
+
*
|
|
91
|
+
* Same logic as `resolveQuality()` but accepts a `GPUAdapterInfo` instead
|
|
92
|
+
* of a WebGL context.
|
|
93
|
+
*/
|
|
94
|
+
export declare function resolveQualityWebGPU(adapterInfo: GPUAdapterInfo, quality?: 'auto' | QualityTier): QualityParams;
|
|
95
|
+
//# sourceMappingURL=quality.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quality.d.ts","sourceRoot":"","sources":["../../src/quality.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,qCAAqC;AACrC,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEpD,kEAAkE;AAClE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,oDAAoD;IACpD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,sGAAsG;IACtG,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,8CAA8C;IAC9C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,sFAAsF;IACtF,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,6EAA6E;IAC7E,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,2CAA2C;AAC3C,MAAM,WAAW,kBAAkB;IACjC,wEAAwE;IACxE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,2BAA2B;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,0EAA0E;IAC1E,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,yDAAyD;IACzD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,+BAA+B;IAC/B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,4CAA4C;IAC5C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAkCD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,sBAAsB,GAAG,kBAAkB,CA0ChF;AA2CD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,WAAW,CAmCpE;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAC5B,EAAE,EAAE,sBAAsB,EAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,WAAW,GAC7B,aAAa,CAMf;AAMD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,cAAc,GAAG,kBAAkB,CAkCvF;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,cAAc,EAC3B,OAAO,CAAC,EAAE,MAAM,GAAG,WAAW,GAC7B,aAAa,CAMf"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared render pass framework for compositing and effect stacking.
|
|
3
|
+
*
|
|
4
|
+
* Provides standardized interfaces (`RenderPass`, `FBOPass`) and a
|
|
5
|
+
* `TextureRegistry` for unit allocation. Both the parallax and portal
|
|
6
|
+
* renderers adopt this framework to structure their multi-pass GPU
|
|
7
|
+
* pipelines consistently.
|
|
8
|
+
*
|
|
9
|
+
* ## Design principles
|
|
10
|
+
*
|
|
11
|
+
* - **Geometry-agnostic** — passes may use fullscreen quads, indexed
|
|
12
|
+
* meshes, or any other geometry. The framework doesn't assume.
|
|
13
|
+
* - **No common execute()** — passes have wildly different execute
|
|
14
|
+
* signatures (bilateral needs raw depth data; JFA flood is iterative;
|
|
15
|
+
* parallax just draws). Each renderer calls passes type-safely.
|
|
16
|
+
* - **Zero per-frame overhead** — TextureRegistry allocates at init
|
|
17
|
+
* time. Hot-path code reads slot references directly.
|
|
18
|
+
* - **Pragmatic** — ~250 lines, not a game engine.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* A self-contained render pass: owns its shader program, uniform cache,
|
|
22
|
+
* and knows how to clean itself up.
|
|
23
|
+
*
|
|
24
|
+
* `program` and `uniforms` are exposed directly so the render loop can
|
|
25
|
+
* set per-frame uniforms (e.g., `uOffset`) without method-call overhead.
|
|
26
|
+
*/
|
|
27
|
+
export interface RenderPass {
|
|
28
|
+
/** Display name for debugging (e.g., "bilateral-filter", "jfa-flood"). */
|
|
29
|
+
readonly name: string;
|
|
30
|
+
/** The compiled + linked shader program. */
|
|
31
|
+
readonly program: WebGLProgram;
|
|
32
|
+
/** Cached uniform locations. */
|
|
33
|
+
readonly uniforms: Record<string, WebGLUniformLocation | null>;
|
|
34
|
+
/** Release GPU resources owned by this pass (program, FBOs). */
|
|
35
|
+
dispose(gl: WebGL2RenderingContext): void;
|
|
36
|
+
}
|
|
37
|
+
/** A single FBO color attachment descriptor. */
|
|
38
|
+
export interface FBOAttachment {
|
|
39
|
+
/** The texture backing this attachment. */
|
|
40
|
+
texture: WebGLTexture;
|
|
41
|
+
/** Assigned texture unit (e.g., `gl.TEXTURE2` maps to unit 2). */
|
|
42
|
+
unit: number;
|
|
43
|
+
/** GL color attachment point (e.g., `gl.COLOR_ATTACHMENT0`). */
|
|
44
|
+
attachment: number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* A render pass that writes to an FBO rather than the default framebuffer.
|
|
48
|
+
*
|
|
49
|
+
* Manages its own framebuffer and output texture(s). Supports both
|
|
50
|
+
* single-output passes (bilateral filter → R8) and MRT passes
|
|
51
|
+
* (portal interior → RGBA8 color + RGBA8 depth).
|
|
52
|
+
*/
|
|
53
|
+
export interface FBOPass extends RenderPass {
|
|
54
|
+
/** The framebuffer object. Null before first `resize()`. */
|
|
55
|
+
fbo: WebGLFramebuffer | null;
|
|
56
|
+
/** Output textures written by this pass. */
|
|
57
|
+
readonly outputs: readonly FBOAttachment[];
|
|
58
|
+
/** Width of the FBO in pixels. */
|
|
59
|
+
width: number;
|
|
60
|
+
/** Height of the FBO in pixels. */
|
|
61
|
+
height: number;
|
|
62
|
+
/**
|
|
63
|
+
* Resize or recreate the FBO and its attachment textures.
|
|
64
|
+
* Called on viewport resize, not per-frame.
|
|
65
|
+
*/
|
|
66
|
+
resize(gl: WebGL2RenderingContext, width: number, height: number): void;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Ordered list of render passes. Execute in array order.
|
|
70
|
+
*
|
|
71
|
+
* This is intentionally a thin type alias, not a class. The dual-loop
|
|
72
|
+
* architecture (RVFC + RAF) means passes are NOT all executed in one
|
|
73
|
+
* sequence, so orchestration stays in each renderer's render loop.
|
|
74
|
+
*/
|
|
75
|
+
export type RenderPipeline = readonly RenderPass[];
|
|
76
|
+
/** A named texture with its assigned unit. */
|
|
77
|
+
export interface TextureSlot {
|
|
78
|
+
/** Human-readable name (e.g., "video", "filteredDepth"). */
|
|
79
|
+
readonly name: string;
|
|
80
|
+
/** Assigned texture unit number (0, 1, 2, ...). */
|
|
81
|
+
readonly unit: number;
|
|
82
|
+
/** The WebGL texture handle. Null until allocated. */
|
|
83
|
+
texture: WebGLTexture | null;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Tracks texture unit assignments for a renderer.
|
|
87
|
+
*
|
|
88
|
+
* All allocation happens at init time via `register()`. The hot-path
|
|
89
|
+
* render loop accesses slots directly by cached reference — no map
|
|
90
|
+
* lookups per frame.
|
|
91
|
+
*
|
|
92
|
+
* Usage:
|
|
93
|
+
* ```ts
|
|
94
|
+
* const textures = new TextureRegistry();
|
|
95
|
+
* const videoSlot = textures.register('video'); // unit 0
|
|
96
|
+
* const depthSlot = textures.register('filteredDepth'); // unit 1
|
|
97
|
+
*
|
|
98
|
+
* // In render loop (hot path) — direct reference, zero lookup:
|
|
99
|
+
* gl.activeTexture(gl.TEXTURE0 + videoSlot.unit);
|
|
100
|
+
* gl.bindTexture(gl.TEXTURE_2D, videoSlot.texture);
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export declare class TextureRegistry {
|
|
104
|
+
private readonly slots;
|
|
105
|
+
private nextUnit;
|
|
106
|
+
/**
|
|
107
|
+
* Reserve a texture unit for a named texture.
|
|
108
|
+
*
|
|
109
|
+
* @returns The `TextureSlot` — hold a reference for hot-path access.
|
|
110
|
+
* @throws If the name is already registered.
|
|
111
|
+
*/
|
|
112
|
+
register(name: string): TextureSlot;
|
|
113
|
+
/**
|
|
114
|
+
* Get a previously registered slot by name.
|
|
115
|
+
*
|
|
116
|
+
* @throws If the name was not registered.
|
|
117
|
+
*/
|
|
118
|
+
get(name: string): TextureSlot;
|
|
119
|
+
/** Delete all textures and reset slots to null. */
|
|
120
|
+
disposeAll(gl: WebGL2RenderingContext): void;
|
|
121
|
+
/** Number of registered slots. */
|
|
122
|
+
get size(): number;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Create a `RenderPass` from vertex/fragment shader source.
|
|
126
|
+
*
|
|
127
|
+
* Compiles shaders, links program, caches uniform locations.
|
|
128
|
+
* The returned pass owns its program and cleans it up on `dispose()`.
|
|
129
|
+
*/
|
|
130
|
+
export declare function createPass(gl: WebGL2RenderingContext, name: string, vertexSource: string, fragmentSource: string, uniformNames: readonly string[]): RenderPass;
|
|
131
|
+
/** Options for creating a single-output FBO pass. */
|
|
132
|
+
export interface FBOPassOptions {
|
|
133
|
+
/** GL internal format (e.g., `gl.R8`, `gl.RGBA8`, `gl.RG16F`). */
|
|
134
|
+
internalFormat: number;
|
|
135
|
+
/** GL format for texImage2D (e.g., `gl.RED`, `gl.RGBA`, `gl.RG`). */
|
|
136
|
+
format: number;
|
|
137
|
+
/** GL type for texImage2D (e.g., `gl.UNSIGNED_BYTE`, `gl.FLOAT`). */
|
|
138
|
+
type: number;
|
|
139
|
+
/** Texture unit to assign to the output texture. */
|
|
140
|
+
textureUnit: number;
|
|
141
|
+
/** Initial FBO width. */
|
|
142
|
+
width: number;
|
|
143
|
+
/** Initial FBO height. */
|
|
144
|
+
height: number;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Create an `FBOPass` with a single color attachment.
|
|
148
|
+
*
|
|
149
|
+
* The FBO and its output texture are created immediately at the given
|
|
150
|
+
* dimensions. Call `resize()` to recreate at a different size.
|
|
151
|
+
*/
|
|
152
|
+
export declare function createFBOPass(gl: WebGL2RenderingContext, name: string, vertexSource: string, fragmentSource: string, uniformNames: readonly string[], options: FBOPassOptions): FBOPass;
|
|
153
|
+
/** Descriptor for one MRT color attachment. */
|
|
154
|
+
export interface MRTAttachment {
|
|
155
|
+
/** GL internal format (e.g., `gl.RGBA8`). */
|
|
156
|
+
internalFormat: number;
|
|
157
|
+
/** GL format (e.g., `gl.RGBA`). */
|
|
158
|
+
format: number;
|
|
159
|
+
/** GL type (e.g., `gl.UNSIGNED_BYTE`). */
|
|
160
|
+
type: number;
|
|
161
|
+
/** Texture unit to assign. */
|
|
162
|
+
textureUnit: number;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Create an `FBOPass` with multiple color attachments (MRT).
|
|
166
|
+
*
|
|
167
|
+
* Used by the portal interior pass which writes both color and depth
|
|
168
|
+
* to separate textures in a single draw call via `gl.drawBuffers()`.
|
|
169
|
+
*/
|
|
170
|
+
export declare function createMRTPass(gl: WebGL2RenderingContext, name: string, vertexSource: string, fragmentSource: string, uniformNames: readonly string[], attachments: readonly MRTAttachment[], width: number, height: number): FBOPass;
|
|
171
|
+
//# sourceMappingURL=render-pass.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-pass.d.ts","sourceRoot":"","sources":["../../src/render-pass.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abstract base class for Layershift renderers.
|
|
3
|
+
*
|
|
4
|
+
* Extracts shared non-GPU logic common to both the depth-effect and portal
|
|
5
|
+
* renderers (and their WebGPU counterparts):
|
|
6
|
+
*
|
|
7
|
+
* - Canvas creation + container attachment
|
|
8
|
+
* - Dual-loop animation management (RVFC + RAF)
|
|
9
|
+
* - Resize handling with debounce
|
|
10
|
+
* - Depth dimension clamping + CPU subsampling
|
|
11
|
+
* - Cover-fit UV computation
|
|
12
|
+
* - WebGL context loss handling
|
|
13
|
+
*
|
|
14
|
+
* Subclasses implement the GPU-specific abstract methods:
|
|
15
|
+
* `onRenderFrame()`, `onDepthUpdate()`, `recalculateViewportLayout()`,
|
|
16
|
+
* `disposeRenderer()`, and `onContextRestored()`.
|
|
17
|
+
*/
|
|
18
|
+
import type { MediaSource } from './media-source';
|
|
19
|
+
import type { EffectInput } from './input-handler';
|
|
20
|
+
import type { QualityParams } from './quality';
|
|
21
|
+
export declare abstract class RendererBase {
|
|
22
|
+
protected static readonly RESIZE_DEBOUNCE_MS = 100;
|
|
23
|
+
protected readonly canvas: HTMLCanvasElement;
|
|
24
|
+
protected readonly container: HTMLElement;
|
|
25
|
+
/** GPU texture dimensions (may be clamped by quality tier). */
|
|
26
|
+
protected depthWidth: number;
|
|
27
|
+
protected depthHeight: number;
|
|
28
|
+
/** Original source depth dimensions (from precomputed data). */
|
|
29
|
+
protected sourceDepthWidth: number;
|
|
30
|
+
protected sourceDepthHeight: number;
|
|
31
|
+
/** Reusable buffer for subsampling depth data when GPU dims < source dims. */
|
|
32
|
+
protected depthSubsampleBuffer: Uint8Array | null;
|
|
33
|
+
protected videoAspect: number;
|
|
34
|
+
/** When true, computeCoverFitUV mirrors the X-axis for selfie mode. */
|
|
35
|
+
protected isCameraSource: boolean;
|
|
36
|
+
protected uvOffset: number[];
|
|
37
|
+
protected uvScale: number[];
|
|
38
|
+
protected readDepth: ((timeSec: number) => Uint8Array) | null;
|
|
39
|
+
protected readInput: (() => EffectInput) | null;
|
|
40
|
+
protected mediaSource: MediaSource | null;
|
|
41
|
+
/**
|
|
42
|
+
* Optional callback invoked on each new video frame (from RVFC).
|
|
43
|
+
* The Web Component uses this to dispatch frame events.
|
|
44
|
+
*/
|
|
45
|
+
protected onVideoFrame: ((currentTime: number, frameNumber: number) => void) | null;
|
|
46
|
+
protected animationFrameHandle: number;
|
|
47
|
+
/** requestVideoFrameCallback handle (0 = inactive). */
|
|
48
|
+
protected rvfcHandle: number;
|
|
49
|
+
/** Whether RVFC is supported on the current video element. */
|
|
50
|
+
protected rvfcSupported: boolean;
|
|
51
|
+
protected resizeObserver: ResizeObserver | null;
|
|
52
|
+
protected resizeTimer: number | null;
|
|
53
|
+
/** Adaptive quality parameters. Set by subclass constructor after GL init. */
|
|
54
|
+
protected qualityParams: QualityParams;
|
|
55
|
+
constructor(parent: HTMLElement);
|
|
56
|
+
/** The underlying canvas element. */
|
|
57
|
+
get canvasElement(): HTMLCanvasElement;
|
|
58
|
+
/**
|
|
59
|
+
* Begin the render loop.
|
|
60
|
+
*
|
|
61
|
+
* For live sources (video/camera) with RVFC support, two loops run:
|
|
62
|
+
* 1. RVFC loop — fires once per new video frame, handles depth update.
|
|
63
|
+
* 2. RAF loop — fires at display refresh rate, handles input + render.
|
|
64
|
+
*
|
|
65
|
+
* For static sources (image) or when RVFC is unavailable, RAF-only.
|
|
66
|
+
*/
|
|
67
|
+
start(source: MediaSource, readDepth: (timeSec: number) => Uint8Array, readInput: () => EffectInput, onVideoFrame?: (currentTime: number, frameNumber: number) => void): void;
|
|
68
|
+
/** Stop both render loops and release callbacks. */
|
|
69
|
+
stop(): void;
|
|
70
|
+
/** Stop rendering and release all GPU resources. */
|
|
71
|
+
dispose(): void;
|
|
72
|
+
/** Check whether requestVideoFrameCallback is available. */
|
|
73
|
+
protected static isRVFCSupported(): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* RAF loop — fires at display refresh rate.
|
|
76
|
+
* Delegates to subclass `onRenderFrame()` for the actual render work.
|
|
77
|
+
*/
|
|
78
|
+
private readonly _rafLoop;
|
|
79
|
+
/**
|
|
80
|
+
* RVFC callback — fires only when the browser presents a new video frame.
|
|
81
|
+
* Delegates to subclass `onDepthUpdate()` for depth texture upload.
|
|
82
|
+
*/
|
|
83
|
+
private readonly _videoFrameLoop;
|
|
84
|
+
private readonly _handleContextLost;
|
|
85
|
+
private readonly _handleContextRestored;
|
|
86
|
+
/**
|
|
87
|
+
* Set up a ResizeObserver on the container element and a fallback
|
|
88
|
+
* window resize listener. Called by subclass after GPU init.
|
|
89
|
+
*/
|
|
90
|
+
protected setupResizeHandling(): void;
|
|
91
|
+
/** Debounce resize events to avoid expensive layout recalculations. */
|
|
92
|
+
protected readonly scheduleResizeRecalculate: () => void;
|
|
93
|
+
/** Read the container's pixel dimensions, with a minimum of 1x1. */
|
|
94
|
+
protected getViewportSize(): {
|
|
95
|
+
width: number;
|
|
96
|
+
height: number;
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Clamp depth dimensions to the quality tier's maximum and allocate
|
|
100
|
+
* the subsample buffer if needed. Called during `initialize()`.
|
|
101
|
+
*/
|
|
102
|
+
protected clampDepthDimensions(sourceWidth: number, sourceHeight: number, maxDim: number): void;
|
|
103
|
+
/**
|
|
104
|
+
* CPU nearest-neighbor depth subsampling.
|
|
105
|
+
*
|
|
106
|
+
* Returns the original data if no subsampling is needed, otherwise
|
|
107
|
+
* fills and returns the pre-allocated subsample buffer.
|
|
108
|
+
*/
|
|
109
|
+
protected subsampleDepth(depthData: Uint8Array): Uint8Array;
|
|
110
|
+
/**
|
|
111
|
+
* Compute cover-fit + overscan UV transform.
|
|
112
|
+
*
|
|
113
|
+
* The video fills the viewport (cover-fit), and overscan adds extra
|
|
114
|
+
* visible area so parallax displacement doesn't reveal edges.
|
|
115
|
+
* Updates `this.uvOffset` and `this.uvScale`.
|
|
116
|
+
*/
|
|
117
|
+
protected computeCoverFitUV(parallaxStrength: number, overscanPadding: number): void;
|
|
118
|
+
/** Main render frame logic (called from RAF loop at display refresh rate). */
|
|
119
|
+
protected abstract onRenderFrame(): void;
|
|
120
|
+
/** Depth texture upload + filter (called from RVFC loop at video frame rate). */
|
|
121
|
+
protected abstract onDepthUpdate(timeSec: number): void;
|
|
122
|
+
/** Recalculate canvas size, FBOs, UV transform on resize. */
|
|
123
|
+
protected abstract recalculateViewportLayout(): void;
|
|
124
|
+
/** Release all GPU resources (called from dispose()). */
|
|
125
|
+
protected abstract disposeRenderer(): void;
|
|
126
|
+
/** Rebuild GPU state after context restoration. */
|
|
127
|
+
protected abstract onContextRestored(): void;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=renderer-base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer-base.d.ts","sourceRoot":"","sources":["../../src/renderer-base.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter: converts ChannelLayer[] → renderer configs.
|
|
3
|
+
*
|
|
4
|
+
* Both DepthEffectRenderer (WebGL2) and DepthEffectRendererWebGPU consume
|
|
5
|
+
* scalar config values. This adapter derives those scalars from the
|
|
6
|
+
* channel/curve model, keeping both renderers untouched.
|
|
7
|
+
*
|
|
8
|
+
* Also exports evaluateCurve(), which the curve editor UI will need.
|
|
9
|
+
*/
|
|
10
|
+
import type { ChannelLayer, DepthCurve } from './filter-config';
|
|
11
|
+
/**
|
|
12
|
+
* Evaluate a DepthCurve at a given depth value (0-1).
|
|
13
|
+
*/
|
|
14
|
+
export declare function evaluateCurve(curve: DepthCurve, depth: number): number;
|
|
15
|
+
/**
|
|
16
|
+
* Bake a DepthCurve into a sampled LUT (for GPU upload).
|
|
17
|
+
*
|
|
18
|
+
* DEPTH CONVENTION (canonical — see DEPTH_CONVENTION.md):
|
|
19
|
+
* Depth Anything v2 outputs higher = closer.
|
|
20
|
+
* The depth texture stores 0.0 = far, 1.0 = near.
|
|
21
|
+
* The curve editor x-axis is 0 = far, 1 = near.
|
|
22
|
+
* These match, so the LUT is a direct mapping with NO inversion.
|
|
23
|
+
* The shader samples `texture(uCurve, vec2(depth, 0.5))`, and
|
|
24
|
+
* depth=0(far) → LUT index 0 → curve x=0(far). Correct.
|
|
25
|
+
*/
|
|
26
|
+
export declare function bakeCurveLUT(curve: DepthCurve, size?: number): Uint8Array;
|
|
27
|
+
export interface RendererConfigValues {
|
|
28
|
+
parallaxStrength: number;
|
|
29
|
+
pomEnabled: boolean;
|
|
30
|
+
pomSteps: number;
|
|
31
|
+
contrastLow: number;
|
|
32
|
+
contrastHigh: number;
|
|
33
|
+
verticalReduction: number;
|
|
34
|
+
dofStart: number;
|
|
35
|
+
dofStrength: number;
|
|
36
|
+
blurRadius: number;
|
|
37
|
+
glowColor: [number, number, number];
|
|
38
|
+
glowRadius: number;
|
|
39
|
+
glowSoftness: number;
|
|
40
|
+
tiltEnabled: boolean;
|
|
41
|
+
tiltHalfTanFov: number;
|
|
42
|
+
tiltTransitionWidth: number;
|
|
43
|
+
tiltPeakIntensity: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Derives DepthEffectRenderer config from the channel model.
|
|
47
|
+
*
|
|
48
|
+
* - Displacement channel params → strength, pomEnabled, pomSteps
|
|
49
|
+
* - Blur channel curve → dofStart, dofStrength
|
|
50
|
+
* - contrastLow/contrastHigh/verticalReduction have no channel equivalent
|
|
51
|
+
* yet, so they're passed through from fallback values.
|
|
52
|
+
*/
|
|
53
|
+
export declare function channelsToRendererConfig(channels: ChannelLayer[], fallback: {
|
|
54
|
+
contrastLow: number;
|
|
55
|
+
contrastHigh: number;
|
|
56
|
+
verticalReduction: number;
|
|
57
|
+
}): RendererConfigValues;
|
|
58
|
+
export interface CurveLUTs {
|
|
59
|
+
displacementLUT: Uint8Array | null;
|
|
60
|
+
blurLUT: Uint8Array | null;
|
|
61
|
+
glowLUT: Uint8Array | null;
|
|
62
|
+
colorShiftLUT: Uint8Array | null;
|
|
63
|
+
colorShiftParams: {
|
|
64
|
+
hueShift: number;
|
|
65
|
+
saturation: number;
|
|
66
|
+
brightness: number;
|
|
67
|
+
tintStrength: number;
|
|
68
|
+
tintColor: [number, number, number];
|
|
69
|
+
} | null;
|
|
70
|
+
}
|
|
71
|
+
export declare function bakeCurveLUTs(channels: ChannelLayer[]): CurveLUTs;
|
|
72
|
+
//# sourceMappingURL=channel-to-renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel-to-renderer.d.ts","sourceRoot":"","sources":["../../../src/shared/channel-to-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAe,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAM7E;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CA2BtE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,SAAM,GAAG,UAAU,CAOtE;AAcD,MAAM,WAAW,oBAAoB;IACnC,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,YAAY,EAAE,EACxB,QAAQ,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,GACjF,oBAAoB,CAyCtB;AAED,MAAM,WAAW,SAAS;IACxB,eAAe,EAAE,UAAU,GAAG,IAAI,CAAC;IACnC,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,UAAU,GAAG,IAAI,CAAC;IACjC,gBAAgB,EAAE;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;KACrC,GAAG,IAAI,CAAC;CACV;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,SAAS,CAsBjE"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filter config schema — defines the shape of an authored filter.
|
|
3
|
+
*
|
|
4
|
+
* This is the central data model shared between the editor, web component,
|
|
5
|
+
* and export pipeline. Every parameter the user configures is captured here,
|
|
6
|
+
* and the export pipeline serializes it to JSON.
|
|
7
|
+
*/
|
|
8
|
+
export type EffectType = 'parallax' | 'tilt-shift' | 'depth-glow' | 'rack-focus' | 'depth-color-grade' | 'fog-atmosphere' | 'pop-out' | 'freestyle';
|
|
9
|
+
export declare const EFFECT_LABELS: Record<EffectType, string>;
|
|
10
|
+
export declare const EFFECT_DESCRIPTIONS: Record<EffectType, string>;
|
|
11
|
+
export interface CurvePoint {
|
|
12
|
+
/** Depth position (0=far, 1=near). */
|
|
13
|
+
x: number;
|
|
14
|
+
/** Intensity at this depth (0-1). */
|
|
15
|
+
y: number;
|
|
16
|
+
/** Bezier handle for incoming tangent (relative to point). */
|
|
17
|
+
handleIn?: {
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
};
|
|
21
|
+
/** Bezier handle for outgoing tangent (relative to point). */
|
|
22
|
+
handleOut?: {
|
|
23
|
+
x: number;
|
|
24
|
+
y: number;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export type CurveInterpolation = 'linear' | 'smooth' | 'step';
|
|
28
|
+
export interface DepthCurve {
|
|
29
|
+
/** Control points defining the curve shape. Must be sorted by x ascending. */
|
|
30
|
+
points: CurvePoint[];
|
|
31
|
+
/** Interpolation mode between control points. */
|
|
32
|
+
interpolation: CurveInterpolation;
|
|
33
|
+
}
|
|
34
|
+
export type ChannelType = 'displacement' | 'blur' | 'glow' | 'color-shift';
|
|
35
|
+
export declare const CHANNEL_LABELS: Record<ChannelType, string>;
|
|
36
|
+
export interface DisplacementChannelParams {
|
|
37
|
+
/** Overall displacement strength multiplier. */
|
|
38
|
+
strength: number;
|
|
39
|
+
/** Enable parallax occlusion mapping. */
|
|
40
|
+
pomEnabled: boolean;
|
|
41
|
+
/** POM ray-march step count. */
|
|
42
|
+
pomSteps: number;
|
|
43
|
+
}
|
|
44
|
+
export interface BlurChannelParams {
|
|
45
|
+
/** Maximum blur radius (at curve intensity = 1). */
|
|
46
|
+
maxRadius: number;
|
|
47
|
+
/** Blur kernel sample count. */
|
|
48
|
+
samples: number;
|
|
49
|
+
/** Parametric: center of the sharp focus band in depth space (0-1). Used by tilt-shift. */
|
|
50
|
+
focalCenter?: number;
|
|
51
|
+
/** Parametric: width of the sharp focus band (0-1). Used by tilt-shift. */
|
|
52
|
+
focalWidth?: number;
|
|
53
|
+
/** Parametric: peak blur intensity at edges (0-1). */
|
|
54
|
+
peakIntensity?: number;
|
|
55
|
+
/** Parametric: transition softness from sharp to blurred (0-1). */
|
|
56
|
+
transitionSoftness?: number;
|
|
57
|
+
/** Enable tilted focal plane blur (Scheimpflug simulation). Used by tilt-shift. */
|
|
58
|
+
tiltEnabled?: boolean;
|
|
59
|
+
/** Virtual FOV in degrees for pseudo-world reconstruction (default 50). */
|
|
60
|
+
tiltFov?: number;
|
|
61
|
+
}
|
|
62
|
+
export interface GlowChannelParams {
|
|
63
|
+
/** Glow color [r, g, b] each 0-1. */
|
|
64
|
+
color: [number, number, number];
|
|
65
|
+
/** Glow spread radius. */
|
|
66
|
+
radius: number;
|
|
67
|
+
/** Edge softness of glow boundary. */
|
|
68
|
+
softness: number;
|
|
69
|
+
/** Parametric: depth threshold below which glow begins (0-1, 0=near). */
|
|
70
|
+
glowThreshold?: number;
|
|
71
|
+
/** Parametric: peak glow intensity (0-1). */
|
|
72
|
+
glowIntensity?: number;
|
|
73
|
+
}
|
|
74
|
+
export interface ColorShiftChannelParams {
|
|
75
|
+
/** Hue rotation in degrees (-180 to 180). */
|
|
76
|
+
hueShift: number;
|
|
77
|
+
/** Saturation multiplier (0 = grayscale, 1 = unchanged, >1 = boosted). */
|
|
78
|
+
saturation: number;
|
|
79
|
+
/** Brightness/value multiplier (0 = black, 1 = unchanged, >1 = brighter). */
|
|
80
|
+
brightness: number;
|
|
81
|
+
/** Blend factor toward tintColor (0 = no tint, 1 = fully tinted). */
|
|
82
|
+
tintStrength: number;
|
|
83
|
+
/** Target tint color [r, g, b] each 0-1. Used for fog/atmosphere effects. */
|
|
84
|
+
tintColor: [number, number, number];
|
|
85
|
+
/** Depth where the color-shift effect begins (0=far, 1=near). */
|
|
86
|
+
depthStart: number;
|
|
87
|
+
/** Depth where the color-shift effect reaches full intensity. */
|
|
88
|
+
depthEnd: number;
|
|
89
|
+
}
|
|
90
|
+
export type ChannelParams = {
|
|
91
|
+
'displacement': DisplacementChannelParams;
|
|
92
|
+
'blur': BlurChannelParams;
|
|
93
|
+
'glow': GlowChannelParams;
|
|
94
|
+
'color-shift': ColorShiftChannelParams;
|
|
95
|
+
};
|
|
96
|
+
export interface ChannelLayer<T extends ChannelType = ChannelType> {
|
|
97
|
+
/** Which channel this layer drives. */
|
|
98
|
+
channel: T;
|
|
99
|
+
/** Depth-to-intensity transfer function. */
|
|
100
|
+
curve: DepthCurve;
|
|
101
|
+
/** Channel-specific parameters (non-depth-dependent knobs). */
|
|
102
|
+
params: ChannelParams[T];
|
|
103
|
+
/** Display label in the layer panel. */
|
|
104
|
+
label: string;
|
|
105
|
+
/** Mute this channel without deleting it. */
|
|
106
|
+
enabled: boolean;
|
|
107
|
+
/**
|
|
108
|
+
* True if the user has manually edited the curve in the curve editor.
|
|
109
|
+
* When set, parametric sliders update params but do NOT regenerate the curve,
|
|
110
|
+
* preserving the user's manual edits. Reset when switching effect presets.
|
|
111
|
+
*/
|
|
112
|
+
curveManuallyEdited?: boolean;
|
|
113
|
+
}
|
|
114
|
+
export interface MotionConfig {
|
|
115
|
+
/** X-axis sensitivity multiplier. */
|
|
116
|
+
sensitivityX: number;
|
|
117
|
+
/** Y-axis sensitivity multiplier. */
|
|
118
|
+
sensitivityY: number;
|
|
119
|
+
/** Interpolation smoothing factor (0-1, lower = smoother). */
|
|
120
|
+
lerpFactor: number;
|
|
121
|
+
/** When true, XY input rotates a tilted focal plane in 3D space (Scheimpflug). */
|
|
122
|
+
tiltPlaneInput?: boolean;
|
|
123
|
+
/** Pitch sensitivity in radians per unit input Y (default 0.35). */
|
|
124
|
+
tiltPitchSensitivity?: number;
|
|
125
|
+
/** Yaw sensitivity in radians per unit input X (default 0.15). */
|
|
126
|
+
tiltYawSensitivity?: number;
|
|
127
|
+
}
|
|
128
|
+
export type EdgeStrategy = 'fade' | 'clamp' | 'mirror' | 'wrap';
|
|
129
|
+
export interface FilterConfig {
|
|
130
|
+
/** Filter name (kebab-case, used for tag name: <layershift-{name}>). */
|
|
131
|
+
name: string;
|
|
132
|
+
/** Display name. */
|
|
133
|
+
displayName: string;
|
|
134
|
+
/** Effect type. */
|
|
135
|
+
effectType: EffectType;
|
|
136
|
+
/** Video source reference. */
|
|
137
|
+
video: {
|
|
138
|
+
id: string;
|
|
139
|
+
src: string;
|
|
140
|
+
depthSrc: string;
|
|
141
|
+
depthMeta: string;
|
|
142
|
+
type: 'video' | 'image';
|
|
143
|
+
};
|
|
144
|
+
/** Channel layer stack — the curve-based effect model. */
|
|
145
|
+
channels: ChannelLayer[];
|
|
146
|
+
/** Motion/input configuration. */
|
|
147
|
+
motion: MotionConfig;
|
|
148
|
+
/** Edge handling strategy. */
|
|
149
|
+
edgeStrategy: EdgeStrategy;
|
|
150
|
+
/** Overscan padding (UV space). */
|
|
151
|
+
overscanPadding: number;
|
|
152
|
+
/** Adaptive quality preference. */
|
|
153
|
+
quality: 'auto' | 'high' | 'medium' | 'low';
|
|
154
|
+
}
|
|
155
|
+
export declare const DEFAULT_MOTION: MotionConfig;
|
|
156
|
+
export declare const DEFAULT_LINEAR_RISING: DepthCurve;
|
|
157
|
+
export declare const DEFAULT_FLAT_FULL: DepthCurve;
|
|
158
|
+
export declare const DEFAULT_VALLEY: DepthCurve;
|
|
159
|
+
export declare const DEFAULT_CHANNEL_PARAMS: {
|
|
160
|
+
[K in ChannelType]: ChannelParams[K];
|
|
161
|
+
};
|
|
162
|
+
/** A single axis target. 'input' routes to renderer per-frame offset. */
|
|
163
|
+
export interface InputAxisTarget {
|
|
164
|
+
/** 'input' for renderer offset, or a ChannelType for channel param. */
|
|
165
|
+
target: 'input' | ChannelType;
|
|
166
|
+
/** Param name within the target. */
|
|
167
|
+
param: string;
|
|
168
|
+
/** Display label for this axis. */
|
|
169
|
+
label: string;
|
|
170
|
+
}
|
|
171
|
+
export interface InputMapping {
|
|
172
|
+
x: InputAxisTarget;
|
|
173
|
+
y: InputAxisTarget;
|
|
174
|
+
}
|
|
175
|
+
/** Valid ranges for channel params controllable via the ball. */
|
|
176
|
+
export declare const PARAM_RANGES: Record<string, {
|
|
177
|
+
min: number;
|
|
178
|
+
max: number;
|
|
179
|
+
default: number;
|
|
180
|
+
}>;
|
|
181
|
+
/** Default input mappings per effect type. */
|
|
182
|
+
export declare const DEFAULT_INPUT_MAPPINGS: Record<EffectType, InputMapping>;
|
|
183
|
+
export declare const DEFAULT_CHANNELS: ChannelLayer[];
|
|
184
|
+
//# sourceMappingURL=filter-config.d.ts.map
|