@triforge/compositor-core 0.1.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.
Files changed (97) hide show
  1. package/dist/core/BasePass.d.ts +49 -0
  2. package/dist/core/BasePass.d.ts.map +1 -0
  3. package/dist/core/BasePass.js +36 -0
  4. package/dist/core/CompositorBackend.d.ts +12 -0
  5. package/dist/core/CompositorBackend.d.ts.map +1 -0
  6. package/dist/core/CompositorBackend.js +1 -0
  7. package/dist/core/CompositorOutput.d.ts +73 -0
  8. package/dist/core/CompositorOutput.d.ts.map +1 -0
  9. package/dist/core/CompositorOutput.js +201 -0
  10. package/dist/index.d.ts +62 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +32 -0
  13. package/dist/passes/AlphaOver.d.ts +32 -0
  14. package/dist/passes/AlphaOver.d.ts.map +1 -0
  15. package/dist/passes/AlphaOver.js +59 -0
  16. package/dist/passes/Bloom.d.ts +25 -0
  17. package/dist/passes/Bloom.d.ts.map +1 -0
  18. package/dist/passes/Bloom.js +32 -0
  19. package/dist/passes/Blur.d.ts +23 -0
  20. package/dist/passes/Blur.d.ts.map +1 -0
  21. package/dist/passes/Blur.js +54 -0
  22. package/dist/passes/BrightnessContrast.d.ts +20 -0
  23. package/dist/passes/BrightnessContrast.d.ts.map +1 -0
  24. package/dist/passes/BrightnessContrast.js +42 -0
  25. package/dist/passes/ChromaticAberration.d.ts +22 -0
  26. package/dist/passes/ChromaticAberration.d.ts.map +1 -0
  27. package/dist/passes/ChromaticAberration.js +53 -0
  28. package/dist/passes/ColorBalance.d.ts +38 -0
  29. package/dist/passes/ColorBalance.d.ts.map +1 -0
  30. package/dist/passes/ColorBalance.js +50 -0
  31. package/dist/passes/CombineRGBA.d.ts +35 -0
  32. package/dist/passes/CombineRGBA.d.ts.map +1 -0
  33. package/dist/passes/CombineRGBA.js +49 -0
  34. package/dist/passes/DepthOfField.d.ts +27 -0
  35. package/dist/passes/DepthOfField.d.ts.map +1 -0
  36. package/dist/passes/DepthOfField.js +47 -0
  37. package/dist/passes/EdgeDetect.d.ts +31 -0
  38. package/dist/passes/EdgeDetect.d.ts.map +1 -0
  39. package/dist/passes/EdgeDetect.js +69 -0
  40. package/dist/passes/Exposure.d.ts +19 -0
  41. package/dist/passes/Exposure.d.ts.map +1 -0
  42. package/dist/passes/Exposure.js +42 -0
  43. package/dist/passes/FilmGrain.d.ts +26 -0
  44. package/dist/passes/FilmGrain.d.ts.map +1 -0
  45. package/dist/passes/FilmGrain.js +31 -0
  46. package/dist/passes/Gamma.d.ts +17 -0
  47. package/dist/passes/Gamma.d.ts.map +1 -0
  48. package/dist/passes/Gamma.js +36 -0
  49. package/dist/passes/GaussianBlur.d.ts +26 -0
  50. package/dist/passes/GaussianBlur.d.ts.map +1 -0
  51. package/dist/passes/GaussianBlur.js +81 -0
  52. package/dist/passes/GlareStreaks.d.ts +38 -0
  53. package/dist/passes/GlareStreaks.d.ts.map +1 -0
  54. package/dist/passes/GlareStreaks.js +82 -0
  55. package/dist/passes/HueSaturation.d.ts +26 -0
  56. package/dist/passes/HueSaturation.d.ts.map +1 -0
  57. package/dist/passes/HueSaturation.js +65 -0
  58. package/dist/passes/LUT.d.ts +64 -0
  59. package/dist/passes/LUT.d.ts.map +1 -0
  60. package/dist/passes/LUT.js +140 -0
  61. package/dist/passes/LensFlare.d.ts +34 -0
  62. package/dist/passes/LensFlare.d.ts.map +1 -0
  63. package/dist/passes/LensFlare.js +92 -0
  64. package/dist/passes/Mix.d.ts +23 -0
  65. package/dist/passes/Mix.d.ts.map +1 -0
  66. package/dist/passes/Mix.js +41 -0
  67. package/dist/passes/MotionBlur.d.ts +37 -0
  68. package/dist/passes/MotionBlur.d.ts.map +1 -0
  69. package/dist/passes/MotionBlur.js +65 -0
  70. package/dist/passes/Pixelate.d.ts +19 -0
  71. package/dist/passes/Pixelate.d.ts.map +1 -0
  72. package/dist/passes/Pixelate.js +45 -0
  73. package/dist/passes/RenderLayers.d.ts +31 -0
  74. package/dist/passes/RenderLayers.d.ts.map +1 -0
  75. package/dist/passes/RenderLayers.js +45 -0
  76. package/dist/passes/SSAO.d.ts +34 -0
  77. package/dist/passes/SSAO.d.ts.map +1 -0
  78. package/dist/passes/SSAO.js +42 -0
  79. package/dist/passes/SSR.d.ts +32 -0
  80. package/dist/passes/SSR.d.ts.map +1 -0
  81. package/dist/passes/SSR.js +44 -0
  82. package/dist/passes/SeparateRGBA.d.ts +29 -0
  83. package/dist/passes/SeparateRGBA.d.ts.map +1 -0
  84. package/dist/passes/SeparateRGBA.js +45 -0
  85. package/dist/passes/SetAlpha.d.ts +21 -0
  86. package/dist/passes/SetAlpha.d.ts.map +1 -0
  87. package/dist/passes/SetAlpha.js +36 -0
  88. package/dist/passes/Sharpen.d.ts +17 -0
  89. package/dist/passes/Sharpen.d.ts.map +1 -0
  90. package/dist/passes/Sharpen.js +42 -0
  91. package/dist/passes/Vignette.d.ts +22 -0
  92. package/dist/passes/Vignette.d.ts.map +1 -0
  93. package/dist/passes/Vignette.js +49 -0
  94. package/dist/passes/ZCombine.d.ts +34 -0
  95. package/dist/passes/ZCombine.d.ts.map +1 -0
  96. package/dist/passes/ZCombine.js +50 -0
  97. package/package.json +48 -0
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Registry resolved by CompositorOutput at compile time.
3
+ * Contains three/addons or pmndrs constructors keyed by class name,
4
+ * plus injected scene/camera under '_scene' and '_camera'.
5
+ */
6
+ export type PassRegistry = Record<string, unknown>;
7
+ /**
8
+ * Base class for all compositor pass nodes.
9
+ *
10
+ * Each subclass represents one Blender compositor node equivalent.
11
+ * Subclasses implement _buildThree() and optionally _buildPmndrs().
12
+ *
13
+ * All scalar inputs live in the public `parameters` object so they are
14
+ * reachable by GSAP / st-keyframe.
15
+ */
16
+ export declare abstract class BasePass {
17
+ abstract readonly passType: string;
18
+ /** All scalar inputs — GSAP-animatable. */
19
+ abstract parameters: Record<string, number>;
20
+ /** Whether this pass is active. Inactive passes are skipped during compile. */
21
+ enabled: boolean;
22
+ /**
23
+ * Build a Three.js pass object.
24
+ * Called by CompositorOutput with the resolved three/addons constructors.
25
+ * @param width Render target width
26
+ * @param height Render target height
27
+ * @param reg Resolved three/addons constructors (e.g. { UnrealBloomPass, ... })
28
+ */
29
+ abstract _buildThree(width: number, height: number, reg: PassRegistry): unknown;
30
+ /**
31
+ * Build a pmndrs/postprocessing Effect or Pass.
32
+ * Override in subclasses that support the pmndrs backend.
33
+ * Default throws a clear error.
34
+ * @param reg Resolved postprocessing constructors
35
+ */
36
+ _buildPmndrs(_reg: PassRegistry): unknown;
37
+ /**
38
+ * True when _buildPmndrs() returns a pmndrs Effect (merged into EffectPass).
39
+ * False when it returns a standalone Pass added directly to the composer.
40
+ */
41
+ get _isPmndrsEffect(): boolean;
42
+ /**
43
+ * Names of three/addons postprocessing module files this pass needs loaded.
44
+ * e.g. ['UnrealBloomPass', 'ShaderPass']
45
+ * CompositorOutput reads this to pre-load the registry before calling _buildThree().
46
+ */
47
+ _threePassDeps(): string[];
48
+ }
49
+ //# sourceMappingURL=BasePass.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BasePass.d.ts","sourceRoot":"","sources":["../../src/core/BasePass.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAElD;;;;;;;;GAQG;AACH,8BAAsB,QAAQ;IAC5B,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IAElC,2CAA2C;IAC3C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAE3C,+EAA+E;IAC/E,OAAO,UAAO;IAEd;;;;;;OAMG;IACH,QAAQ,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,GAAG,OAAO;IAE/E;;;;;OAKG;IACH,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO;IAOzC;;;OAGG;IACH,IAAI,eAAe,IAAI,OAAO,CAAiB;IAE/C;;;;OAIG;IACH,cAAc,IAAI,MAAM,EAAE;CAC3B"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Base class for all compositor pass nodes.
3
+ *
4
+ * Each subclass represents one Blender compositor node equivalent.
5
+ * Subclasses implement _buildThree() and optionally _buildPmndrs().
6
+ *
7
+ * All scalar inputs live in the public `parameters` object so they are
8
+ * reachable by GSAP / st-keyframe.
9
+ */
10
+ export class BasePass {
11
+ constructor() {
12
+ /** Whether this pass is active. Inactive passes are skipped during compile. */
13
+ this.enabled = true;
14
+ }
15
+ /**
16
+ * Build a pmndrs/postprocessing Effect or Pass.
17
+ * Override in subclasses that support the pmndrs backend.
18
+ * Default throws a clear error.
19
+ * @param reg Resolved postprocessing constructors
20
+ */
21
+ _buildPmndrs(_reg) {
22
+ throw new Error(`${this.passType}: pmndrs backend is not supported for this pass. ` +
23
+ `Use backend: 'three' or choose a pass that supports pmndrs.`);
24
+ }
25
+ /**
26
+ * True when _buildPmndrs() returns a pmndrs Effect (merged into EffectPass).
27
+ * False when it returns a standalone Pass added directly to the composer.
28
+ */
29
+ get _isPmndrsEffect() { return false; }
30
+ /**
31
+ * Names of three/addons postprocessing module files this pass needs loaded.
32
+ * e.g. ['UnrealBloomPass', 'ShaderPass']
33
+ * CompositorOutput reads this to pre-load the registry before calling _buildThree().
34
+ */
35
+ _threePassDeps() { return []; }
36
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Backend selector — controls which post-processing library is used.
3
+ *
4
+ * 'three' (default) — Three.js built-in EffectComposer from three/addons/.
5
+ * No extra install required. One render pass per effect.
6
+ *
7
+ * 'pmndrs' — pmndrs/postprocessing library.
8
+ * Install: npm install postprocessing
9
+ * Single-pass architecture, better performance and quality.
10
+ */
11
+ export type CompositorBackend = 'three' | 'pmndrs';
12
+ //# sourceMappingURL=CompositorBackend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CompositorBackend.d.ts","sourceRoot":"","sources":["../../src/core/CompositorBackend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,QAAQ,CAAA"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,73 @@
1
+ import { WebGLRenderer, Scene, Camera } from 'three';
2
+ import type { BasePass } from './BasePass.js';
3
+ import type { CompositorBackend } from './CompositorBackend.js';
4
+ export interface CompositorOutputOptions {
5
+ /**
6
+ * Post-processing backend.
7
+ * 'three' (default) — three/addons EffectComposer, no extra install needed.
8
+ * 'pmndrs' — pmndrs/postprocessing. Run: npm install postprocessing
9
+ */
10
+ backend?: CompositorBackend;
11
+ renderer: WebGLRenderer;
12
+ scene: Scene;
13
+ camera: Camera;
14
+ }
15
+ /**
16
+ * CompositorOutput — terminal node of the compositor graph.
17
+ *
18
+ * Equivalent to Blender's Compositor → Composite node.
19
+ * Collects all passes, compiles them into an EffectComposer,
20
+ * and exposes render() which replaces renderer.render() in the loop.
21
+ *
22
+ * Backend is 'three' by default. To use pmndrs/postprocessing:
23
+ * const comp = new CompositorOutput({ backend: 'pmndrs', renderer, scene, camera })
24
+ * // requires: npm install postprocessing
25
+ *
26
+ * Usage:
27
+ * const comp = new CompositorOutput({ renderer, scene, camera })
28
+ * comp.add(new Bloom({ strength: 1.2 }))
29
+ * .add(new ChromaticAberration({ offset: 0.002 }))
30
+ * await comp.compile()
31
+ *
32
+ * // In animation loop — replaces renderer.render(scene, camera)
33
+ * comp.render()
34
+ *
35
+ * // On resize
36
+ * comp.setSize(innerWidth, innerHeight)
37
+ */
38
+ export declare class CompositorOutput {
39
+ readonly backend: CompositorBackend;
40
+ private _renderer;
41
+ private _scene;
42
+ private _camera;
43
+ private _passes;
44
+ private _composer;
45
+ private _compiled;
46
+ constructor(opts: CompositorOutputOptions);
47
+ /** Add a pass node. Chainable. Resets compiled state. */
48
+ add(pass: BasePass): this;
49
+ /** Remove a pass node. Chainable. Resets compiled state. */
50
+ remove(pass: BasePass): this;
51
+ /** All currently registered passes (read-only view). */
52
+ get passes(): readonly BasePass[];
53
+ /** Whether compile() has been called successfully. */
54
+ get isCompiled(): boolean;
55
+ /**
56
+ * Compile the pass chain into an EffectComposer.
57
+ * Must be called once before render(). Re-call after adding/removing passes.
58
+ */
59
+ compile(): Promise<void>;
60
+ /**
61
+ * Render one frame through the compositor chain.
62
+ * Replaces renderer.render(scene, camera) in the animation loop.
63
+ * Falls back to plain render if compile() has not been called.
64
+ */
65
+ render(): void;
66
+ /** Call on window resize to keep the render target in sync. */
67
+ setSize(width: number, height: number): void;
68
+ dispose(): void;
69
+ private _compileThree;
70
+ private _loadThreePassModules;
71
+ private _compilePmndrs;
72
+ }
73
+ //# sourceMappingURL=CompositorOutput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CompositorOutput.d.ts","sourceRoot":"","sources":["../../src/core/CompositorOutput.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAAE,KAAK,EAAE,MAAM,EAE7B,MAAM,OAAO,CAAA;AACd,OAAO,KAAK,EAAE,QAAQ,EAAgB,MAAM,eAAe,CAAA;AAC3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAW,wBAAwB,CAAA;AAEpE,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,OAAO,CAAC,EAAG,iBAAiB,CAAA;IAC5B,QAAQ,EAAG,aAAa,CAAA;IACxB,KAAK,EAAM,KAAK,CAAA;IAChB,MAAM,EAAK,MAAM,CAAA;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,gBAAgB;IAC3B,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAA;IAEnC,OAAO,CAAC,SAAS,CAAe;IAChC,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,SAAS,CAAS;gBAEd,IAAI,EAAE,uBAAuB;IAOzC,yDAAyD;IACzD,GAAG,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI;IAMzB,4DAA4D;IAC5D,MAAM,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI;IAM5B,wDAAwD;IACxD,IAAI,MAAM,IAAI,SAAS,QAAQ,EAAE,CAAwB;IAEzD,sDAAsD;IACtD,IAAI,UAAU,IAAI,OAAO,CAA0B;IAEnD;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAc9B;;;;OAIG;IACH,MAAM,IAAI,IAAI;IAQd,+DAA+D;IAC/D,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAK5C,OAAO,IAAI,IAAI;YAQD,aAAa;YAgEb,qBAAqB;YA4BrB,cAAc;CAgD7B"}
@@ -0,0 +1,201 @@
1
+ import { Vector2, WebGLRenderTarget, LinearFilter, RGBAFormat, HalfFloatType, } from 'three';
2
+ /**
3
+ * CompositorOutput — terminal node of the compositor graph.
4
+ *
5
+ * Equivalent to Blender's Compositor → Composite node.
6
+ * Collects all passes, compiles them into an EffectComposer,
7
+ * and exposes render() which replaces renderer.render() in the loop.
8
+ *
9
+ * Backend is 'three' by default. To use pmndrs/postprocessing:
10
+ * const comp = new CompositorOutput({ backend: 'pmndrs', renderer, scene, camera })
11
+ * // requires: npm install postprocessing
12
+ *
13
+ * Usage:
14
+ * const comp = new CompositorOutput({ renderer, scene, camera })
15
+ * comp.add(new Bloom({ strength: 1.2 }))
16
+ * .add(new ChromaticAberration({ offset: 0.002 }))
17
+ * await comp.compile()
18
+ *
19
+ * // In animation loop — replaces renderer.render(scene, camera)
20
+ * comp.render()
21
+ *
22
+ * // On resize
23
+ * comp.setSize(innerWidth, innerHeight)
24
+ */
25
+ export class CompositorOutput {
26
+ constructor(opts) {
27
+ this._passes = [];
28
+ this._composer = null;
29
+ this._compiled = false;
30
+ this.backend = opts.backend ?? 'three';
31
+ this._renderer = opts.renderer;
32
+ this._scene = opts.scene;
33
+ this._camera = opts.camera;
34
+ }
35
+ /** Add a pass node. Chainable. Resets compiled state. */
36
+ add(pass) {
37
+ this._passes.push(pass);
38
+ this._compiled = false;
39
+ return this;
40
+ }
41
+ /** Remove a pass node. Chainable. Resets compiled state. */
42
+ remove(pass) {
43
+ this._passes = this._passes.filter(p => p !== pass);
44
+ this._compiled = false;
45
+ return this;
46
+ }
47
+ /** All currently registered passes (read-only view). */
48
+ get passes() { return this._passes; }
49
+ /** Whether compile() has been called successfully. */
50
+ get isCompiled() { return this._compiled; }
51
+ /**
52
+ * Compile the pass chain into an EffectComposer.
53
+ * Must be called once before render(). Re-call after adding/removing passes.
54
+ */
55
+ async compile() {
56
+ this._composer?.dispose();
57
+ this._composer = null;
58
+ this._compiled = false;
59
+ if (this.backend === 'pmndrs') {
60
+ this._composer = await this._compilePmndrs();
61
+ }
62
+ else {
63
+ this._composer = await this._compileThree();
64
+ }
65
+ this._compiled = true;
66
+ }
67
+ /**
68
+ * Render one frame through the compositor chain.
69
+ * Replaces renderer.render(scene, camera) in the animation loop.
70
+ * Falls back to plain render if compile() has not been called.
71
+ */
72
+ render() {
73
+ if (this._compiled && this._composer) {
74
+ this._composer.render();
75
+ }
76
+ else {
77
+ this._renderer.render(this._scene, this._camera);
78
+ }
79
+ }
80
+ /** Call on window resize to keep the render target in sync. */
81
+ setSize(width, height) {
82
+ this._renderer.setSize(width, height);
83
+ this._composer?.setSize(width, height);
84
+ }
85
+ dispose() {
86
+ this._composer?.dispose();
87
+ this._composer = null;
88
+ this._compiled = false;
89
+ }
90
+ // ── Three.js backend ──────────────────────────────────────────────────────
91
+ async _compileThree() {
92
+ // Dynamically import three/addons so this package has no hard dependency
93
+ // on a specific addons path — works with CDN importmap and npm alike.
94
+ let EC;
95
+ let RenderPass;
96
+ let OutputPass;
97
+ try {
98
+ const [ecMod, rpMod, opMod] = await Promise.all([
99
+ import('three/addons/postprocessing/EffectComposer.js'),
100
+ import('three/addons/postprocessing/RenderPass.js'),
101
+ import('three/addons/postprocessing/OutputPass.js'),
102
+ ]);
103
+ EC = ecMod['EffectComposer'];
104
+ RenderPass = rpMod['RenderPass'];
105
+ OutputPass = opMod['OutputPass'];
106
+ }
107
+ catch {
108
+ throw new Error('@st-compositor-core: Could not load three/addons postprocessing modules.\n' +
109
+ 'Make sure "three/addons/" is in your importmap or install three with examples/jsm.\n' +
110
+ 'Example importmap entry:\n' +
111
+ ' "three/addons/": "https://unpkg.com/three@0.165.0/examples/jsm/"');
112
+ }
113
+ const activePasses = this._passes.filter(p => p.enabled);
114
+ // Load all required per-pass three/addons modules into one registry object
115
+ const registry = await this._loadThreePassModules(activePasses);
116
+ const size = new Vector2();
117
+ this._renderer.getSize(size);
118
+ const target = new WebGLRenderTarget(size.x, size.y, {
119
+ minFilter: LinearFilter,
120
+ magFilter: LinearFilter,
121
+ format: RGBAFormat,
122
+ type: HalfFloatType,
123
+ });
124
+ const composer = new EC(this._renderer, target);
125
+ const addPass = (p) => composer.addPass(p);
126
+ // RenderPass first — renders the scene into the first buffer
127
+ addPass(new RenderPass(this._scene, this._camera));
128
+ registry['_renderer'] = this._renderer;
129
+ registry['_scene'] = this._scene;
130
+ registry['_camera'] = this._camera;
131
+ // User passes
132
+ for (const pass of activePasses) {
133
+ const built = pass._buildThree(size.x, size.y, registry);
134
+ if (built !== null)
135
+ addPass(built);
136
+ }
137
+ // OutputPass last — required since Three.js r152 to write to screen correctly
138
+ addPass(new OutputPass());
139
+ return composer;
140
+ }
141
+ async _loadThreePassModules(passes) {
142
+ const registry = {};
143
+ const needed = new Set();
144
+ for (const pass of passes) {
145
+ for (const dep of pass._threePassDeps()) {
146
+ needed.add(dep);
147
+ }
148
+ }
149
+ await Promise.all([...needed].map(async (dep) => {
150
+ try {
151
+ const mod = await import(`three/addons/postprocessing/${dep}.js`);
152
+ Object.assign(registry, mod);
153
+ }
154
+ catch {
155
+ // Pass will throw its own clear error in _buildThree() if dep is missing
156
+ }
157
+ }));
158
+ return registry;
159
+ }
160
+ // ── pmndrs backend ────────────────────────────────────────────────────────
161
+ async _compilePmndrs() {
162
+ let pkg;
163
+ try {
164
+ pkg = await import('postprocessing');
165
+ }
166
+ catch {
167
+ throw new Error('@st-compositor-core: backend "pmndrs" requires the "postprocessing" package.\n' +
168
+ 'Run: npm install postprocessing');
169
+ }
170
+ const EC = pkg['EffectComposer'];
171
+ const RenderPass = pkg['RenderPass'];
172
+ const EffectPass = pkg['EffectPass'];
173
+ const composer = new EC(this._renderer);
174
+ const addPass = (p) => composer.addPass(p);
175
+ addPass(new RenderPass(this._scene, this._camera));
176
+ const activePasses = this._passes.filter(p => p.enabled);
177
+ const effects = [];
178
+ const standalone = [];
179
+ for (const pass of activePasses) {
180
+ // Inject camera into registry so passes that need it (e.g. DepthOfField) can access it
181
+ const reg = {
182
+ ...pkg,
183
+ _camera: this._camera,
184
+ _scene: this._scene,
185
+ };
186
+ const built = pass._buildPmndrs(reg);
187
+ if (pass._isPmndrsEffect) {
188
+ effects.push(built);
189
+ }
190
+ else {
191
+ standalone.push(built);
192
+ }
193
+ }
194
+ if (effects.length > 0) {
195
+ addPass(new EffectPass(this._camera, ...effects));
196
+ }
197
+ for (const sp of standalone)
198
+ addPass(sp);
199
+ return composer;
200
+ }
201
+ }
@@ -0,0 +1,62 @@
1
+ export { BasePass } from './core/BasePass.js';
2
+ export { CompositorOutput } from './core/CompositorOutput.js';
3
+ export type { CompositorBackend } from './core/CompositorBackend.js';
4
+ export type { PassRegistry } from './core/BasePass.js';
5
+ export type { CompositorOutputOptions } from './core/CompositorOutput.js';
6
+ export { Bloom } from './passes/Bloom.js';
7
+ export { DepthOfField } from './passes/DepthOfField.js';
8
+ export { Blur } from './passes/Blur.js';
9
+ export { ChromaticAberration } from './passes/ChromaticAberration.js';
10
+ export { Vignette } from './passes/Vignette.js';
11
+ export { FilmGrain } from './passes/FilmGrain.js';
12
+ export { ColorBalance } from './passes/ColorBalance.js';
13
+ export { HueSaturation } from './passes/HueSaturation.js';
14
+ export { BrightnessContrast } from './passes/BrightnessContrast.js';
15
+ export { Gamma } from './passes/Gamma.js';
16
+ export { Exposure } from './passes/Exposure.js';
17
+ export { Mix } from './passes/Mix.js';
18
+ export { Pixelate } from './passes/Pixelate.js';
19
+ export { Sharpen } from './passes/Sharpen.js';
20
+ export { AlphaOver } from './passes/AlphaOver.js';
21
+ export { SetAlpha } from './passes/SetAlpha.js';
22
+ export { ZCombine } from './passes/ZCombine.js';
23
+ export { SeparateRGBA } from './passes/SeparateRGBA.js';
24
+ export { CombineRGBA } from './passes/CombineRGBA.js';
25
+ export { SSAO } from './passes/SSAO.js';
26
+ export { SSR } from './passes/SSR.js';
27
+ export type { BloomOptions } from './passes/Bloom.js';
28
+ export type { DepthOfFieldOptions } from './passes/DepthOfField.js';
29
+ export type { BlurOptions } from './passes/Blur.js';
30
+ export type { ChromaticAberrationOptions } from './passes/ChromaticAberration.js';
31
+ export type { VignetteOptions } from './passes/Vignette.js';
32
+ export type { FilmGrainOptions } from './passes/FilmGrain.js';
33
+ export type { ColorBalanceOptions } from './passes/ColorBalance.js';
34
+ export type { HueSaturationOptions } from './passes/HueSaturation.js';
35
+ export type { BrightnessContrastOptions } from './passes/BrightnessContrast.js';
36
+ export type { GammaOptions } from './passes/Gamma.js';
37
+ export type { ExposureOptions } from './passes/Exposure.js';
38
+ export type { MixOptions } from './passes/Mix.js';
39
+ export type { PixelateOptions } from './passes/Pixelate.js';
40
+ export type { SharpenOptions } from './passes/Sharpen.js';
41
+ export type { AlphaOverOptions } from './passes/AlphaOver.js';
42
+ export type { SetAlphaOptions } from './passes/SetAlpha.js';
43
+ export type { ZCombineOptions } from './passes/ZCombine.js';
44
+ export type { SeparateRGBAOptions, RGBAChannel } from './passes/SeparateRGBA.js';
45
+ export type { CombineRGBAOptions } from './passes/CombineRGBA.js';
46
+ export type { SSAOOptions } from './passes/SSAO.js';
47
+ export type { SSROptions } from './passes/SSR.js';
48
+ export { RenderLayers } from './passes/RenderLayers.js';
49
+ export { GaussianBlur } from './passes/GaussianBlur.js';
50
+ export { GlareStreaks } from './passes/GlareStreaks.js';
51
+ export { MotionBlur } from './passes/MotionBlur.js';
52
+ export type { RenderLayersOptions } from './passes/RenderLayers.js';
53
+ export type { GaussianBlurOptions } from './passes/GaussianBlur.js';
54
+ export type { GlareStreaksOptions } from './passes/GlareStreaks.js';
55
+ export type { MotionBlurOptions } from './passes/MotionBlur.js';
56
+ export { LensFlare } from './passes/LensFlare.js';
57
+ export { EdgeDetect } from './passes/EdgeDetect.js';
58
+ export type { LensFlareOptions } from './passes/LensFlare.js';
59
+ export type { EdgeDetectOptions } from './passes/EdgeDetect.js';
60
+ export { LUT } from './passes/LUT.js';
61
+ export type { LUTOptions } from './passes/LUT.js';
62
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,32 @@
1
+ // ── Core ──────────────────────────────────────────────────────────────────────
2
+ export { BasePass } from './core/BasePass.js';
3
+ export { CompositorOutput } from './core/CompositorOutput.js';
4
+ // ── Pass nodes ────────────────────────────────────────────────────────────────
5
+ export { Bloom } from './passes/Bloom.js';
6
+ export { DepthOfField } from './passes/DepthOfField.js';
7
+ export { Blur } from './passes/Blur.js';
8
+ export { ChromaticAberration } from './passes/ChromaticAberration.js';
9
+ export { Vignette } from './passes/Vignette.js';
10
+ export { FilmGrain } from './passes/FilmGrain.js';
11
+ export { ColorBalance } from './passes/ColorBalance.js';
12
+ export { HueSaturation } from './passes/HueSaturation.js';
13
+ export { BrightnessContrast } from './passes/BrightnessContrast.js';
14
+ export { Gamma } from './passes/Gamma.js';
15
+ export { Exposure } from './passes/Exposure.js';
16
+ export { Mix } from './passes/Mix.js';
17
+ export { Pixelate } from './passes/Pixelate.js';
18
+ export { Sharpen } from './passes/Sharpen.js';
19
+ export { AlphaOver } from './passes/AlphaOver.js';
20
+ export { SetAlpha } from './passes/SetAlpha.js';
21
+ export { ZCombine } from './passes/ZCombine.js';
22
+ export { SeparateRGBA } from './passes/SeparateRGBA.js';
23
+ export { CombineRGBA } from './passes/CombineRGBA.js';
24
+ export { SSAO } from './passes/SSAO.js';
25
+ export { SSR } from './passes/SSR.js';
26
+ export { RenderLayers } from './passes/RenderLayers.js';
27
+ export { GaussianBlur } from './passes/GaussianBlur.js';
28
+ export { GlareStreaks } from './passes/GlareStreaks.js';
29
+ export { MotionBlur } from './passes/MotionBlur.js';
30
+ export { LensFlare } from './passes/LensFlare.js';
31
+ export { EdgeDetect } from './passes/EdgeDetect.js';
32
+ export { LUT } from './passes/LUT.js';
@@ -0,0 +1,32 @@
1
+ import { BasePass } from '../core/BasePass.js';
2
+ import type { PassRegistry } from '../core/BasePass.js';
3
+ export interface AlphaOverOptions {
4
+ /** Background colour as hex string. Default '#000000'. Blender: Alpha Over → Background */
5
+ background?: string;
6
+ /** Blend premultiplied alpha. Default false. Blender: Alpha Over → Convert Premul */
7
+ premul?: boolean;
8
+ /** Overall mix factor [0–1]. Default 1.0. */
9
+ fac?: number;
10
+ }
11
+ /**
12
+ * AlphaOver — Blender Compositor: Alpha Over node.
13
+ *
14
+ * Composites the current render over a solid background colour using
15
+ * the render's alpha channel (standard over operation).
16
+ * A = current render (foreground), B = background colour.
17
+ * Result = A.rgb * A.a + B.rgb * (1 - A.a)
18
+ */
19
+ export declare class AlphaOver extends BasePass {
20
+ readonly passType = "AlphaOver";
21
+ parameters: {
22
+ fac: number;
23
+ bgR: number;
24
+ bgG: number;
25
+ bgB: number;
26
+ premul: number;
27
+ };
28
+ constructor(opts?: AlphaOverOptions);
29
+ _threePassDeps(): string[];
30
+ _buildThree(_w: number, _h: number, reg: PassRegistry): unknown;
31
+ }
32
+ //# sourceMappingURL=AlphaOver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AlphaOver.d.ts","sourceRoot":"","sources":["../../src/passes/AlphaOver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAEvD,MAAM,WAAW,gBAAgB;IAC/B,2FAA2F;IAC3F,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,qFAAqF;IACrF,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,6CAA6C;IAC7C,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAWD;;;;;;;GAOG;AACH,qBAAa,SAAU,SAAQ,QAAQ;IACrC,QAAQ,CAAC,QAAQ,eAAc;IAC/B,UAAU,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;gBAEtE,IAAI,GAAE,gBAAqB;IAUvC,cAAc;IAEd,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,GAAG,OAAO;CA4BhE"}
@@ -0,0 +1,59 @@
1
+ import { BasePass } from '../core/BasePass.js';
2
+ function hexToRgb(hex) {
3
+ const h = hex.replace('#', '');
4
+ return [
5
+ parseInt(h.substring(0, 2), 16) / 255,
6
+ parseInt(h.substring(2, 4), 16) / 255,
7
+ parseInt(h.substring(4, 6), 16) / 255,
8
+ ];
9
+ }
10
+ /**
11
+ * AlphaOver — Blender Compositor: Alpha Over node.
12
+ *
13
+ * Composites the current render over a solid background colour using
14
+ * the render's alpha channel (standard over operation).
15
+ * A = current render (foreground), B = background colour.
16
+ * Result = A.rgb * A.a + B.rgb * (1 - A.a)
17
+ */
18
+ export class AlphaOver extends BasePass {
19
+ constructor(opts = {}) {
20
+ super();
21
+ this.passType = 'AlphaOver';
22
+ const [bgR, bgG, bgB] = hexToRgb(opts.background ?? '#000000');
23
+ this.parameters = {
24
+ fac: opts.fac ?? 1.0,
25
+ bgR, bgG, bgB,
26
+ premul: opts.premul ? 1 : 0,
27
+ };
28
+ }
29
+ _threePassDeps() { return ['ShaderPass']; }
30
+ _buildThree(_w, _h, reg) {
31
+ const ShaderPass = reg['ShaderPass'];
32
+ if (!ShaderPass)
33
+ throw new Error('AlphaOver: ShaderPass not found.');
34
+ const { fac, bgR, bgG, bgB, premul } = this.parameters;
35
+ const shader = {
36
+ uniforms: {
37
+ tDiffuse: { value: null },
38
+ fac: { value: fac },
39
+ bgColor: { value: [bgR, bgG, bgB] },
40
+ premul: { value: premul },
41
+ },
42
+ vertexShader: `varying vec2 vUv; void main(){ vUv=uv; gl_Position=projectionMatrix*modelViewMatrix*vec4(position,1.0); }`,
43
+ fragmentShader: `
44
+ uniform sampler2D tDiffuse;
45
+ uniform float fac;
46
+ uniform vec3 bgColor;
47
+ uniform float premul;
48
+ varying vec2 vUv;
49
+ void main(){
50
+ vec4 fg = texture2D(tDiffuse, vUv);
51
+ vec3 fgRgb = premul > 0.5 ? fg.rgb : fg.rgb * fg.a;
52
+ vec3 result = mix(bgColor, fgRgb + bgColor*(1.0-fg.a), fac);
53
+ gl_FragColor = vec4(result, 1.0);
54
+ }
55
+ `,
56
+ };
57
+ return new ShaderPass(shader);
58
+ }
59
+ }
@@ -0,0 +1,25 @@
1
+ import { BasePass } from '../core/BasePass.js';
2
+ import type { PassRegistry } from '../core/BasePass.js';
3
+ export interface BloomOptions {
4
+ /** Luminance threshold — pixels below this are not bloomed. Default 0.8. Blender: Glare → Threshold */
5
+ threshold?: number;
6
+ /** Bloom intensity. Default 1.5. Blender: Glare → Strength */
7
+ strength?: number;
8
+ /** Bloom spread radius [0–1]. Default 0.4. Blender: Glare → Size */
9
+ radius?: number;
10
+ }
11
+ /** Bloom — Blender Compositor: Glare node (Bloom type) */
12
+ export declare class Bloom extends BasePass {
13
+ readonly passType = "Bloom";
14
+ parameters: {
15
+ threshold: number;
16
+ strength: number;
17
+ radius: number;
18
+ };
19
+ constructor(opts?: BloomOptions);
20
+ _threePassDeps(): string[];
21
+ _buildThree(width: number, height: number, reg: PassRegistry): unknown;
22
+ _buildPmndrs(reg: PassRegistry): unknown;
23
+ get _isPmndrsEffect(): boolean;
24
+ }
25
+ //# sourceMappingURL=Bloom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Bloom.d.ts","sourceRoot":"","sources":["../../src/passes/Bloom.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAEvD,MAAM,WAAW,YAAY;IAC3B,uGAAuG;IACvG,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,0DAA0D;AAC1D,qBAAa,KAAM,SAAQ,QAAQ;IACjC,QAAQ,CAAC,QAAQ,WAAU;IAC3B,UAAU,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;gBAEvD,IAAI,GAAE,YAAiB;IASnC,cAAc;IAEd,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,GAAG,OAAO;IAW7D,YAAY,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO;IAUjD,IAAa,eAAe,IAAI,OAAO,CAAgB;CACxD"}
@@ -0,0 +1,32 @@
1
+ import { Vector2 } from 'three';
2
+ import { BasePass } from '../core/BasePass.js';
3
+ /** Bloom — Blender Compositor: Glare node (Bloom type) */
4
+ export class Bloom extends BasePass {
5
+ constructor(opts = {}) {
6
+ super();
7
+ this.passType = 'Bloom';
8
+ this.parameters = {
9
+ threshold: opts.threshold ?? 0.8,
10
+ strength: opts.strength ?? 1.5,
11
+ radius: opts.radius ?? 0.4,
12
+ };
13
+ }
14
+ _threePassDeps() { return ['UnrealBloomPass']; }
15
+ _buildThree(width, height, reg) {
16
+ const Pass = reg['UnrealBloomPass'];
17
+ if (!Pass)
18
+ throw new Error('Bloom: UnrealBloomPass not found in three/addons.');
19
+ return new Pass(new Vector2(width, height), this.parameters.strength, this.parameters.radius, this.parameters.threshold);
20
+ }
21
+ _buildPmndrs(reg) {
22
+ const Effect = reg['BloomEffect'];
23
+ if (!Effect)
24
+ throw new Error('Bloom: BloomEffect not found in postprocessing.');
25
+ return new Effect({
26
+ intensity: this.parameters.strength,
27
+ luminanceThreshold: this.parameters.threshold,
28
+ radius: this.parameters.radius,
29
+ });
30
+ }
31
+ get _isPmndrsEffect() { return true; }
32
+ }