textmode.js 0.8.1 → 0.9.0-beta.2

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 (32) hide show
  1. package/dist/textmode.esm.js +2841 -2345
  2. package/dist/textmode.umd.js +18 -16
  3. package/dist/types/exports/conversion.d.ts +1 -0
  4. package/dist/types/exports/filters.d.ts +1 -0
  5. package/dist/types/exports/input.d.ts +1 -0
  6. package/dist/types/exports/layering.d.ts +1 -0
  7. package/dist/types/exports/loadables.d.ts +1 -0
  8. package/dist/types/exports/loading.d.ts +1 -0
  9. package/dist/types/exports/plugins.d.ts +1 -0
  10. package/dist/types/index.d.ts +35 -1
  11. package/dist/types/rendering/webgl/core/Framebuffer.d.ts +1 -1
  12. package/dist/types/rendering/webgl/core/Shader.d.ts +17 -3
  13. package/dist/types/rendering/webgl/core/interfaces/IFramebuffer.d.ts +1 -8
  14. package/dist/types/textmode/AnimationController.d.ts +29 -0
  15. package/dist/types/textmode/Grid.d.ts +2 -0
  16. package/dist/types/textmode/Textmodifier.d.ts +8 -15
  17. package/dist/types/textmode/interfaces/ITextmodifier.d.ts +3 -11
  18. package/dist/types/textmode/layers/Camera3D.d.ts +205 -0
  19. package/dist/types/textmode/layers/Layer3DCompositor.d.ts +152 -0
  20. package/dist/types/textmode/layers/LayerManager.d.ts +70 -25
  21. package/dist/types/textmode/layers/TextmodeLayer.d.ts +12 -52
  22. package/dist/types/textmode/layers/index.d.ts +4 -0
  23. package/dist/types/textmode/layers/interfaces/ILayerManager.d.ts +52 -0
  24. package/dist/types/textmode/layers/interfaces/ITextmodeLayer.d.ts +49 -2
  25. package/dist/types/textmode/managers/PluginManager.d.ts +155 -7
  26. package/dist/types/textmode/mixins/interfaces/IAnimationMixin.d.ts +133 -0
  27. package/dist/types/textmode/mixins/interfaces/IRenderingMixin.d.ts +80 -0
  28. package/dist/types/textmode/types.d.ts +4 -3
  29. package/dist/types/utils/TextmodeCollection.d.ts +262 -0
  30. package/dist/types/utils/mat3.d.ts +149 -0
  31. package/dist/types/utils/math.d.ts +26 -0
  32. package/package.json +36 -1
@@ -0,0 +1 @@
1
+ export * from '../textmode/conversion';
@@ -0,0 +1 @@
1
+ export * from '../textmode/filters';
@@ -0,0 +1 @@
1
+ export * from '../textmode/managers';
@@ -0,0 +1 @@
1
+ export * from '../textmode/layers';
@@ -0,0 +1 @@
1
+ export * from '../textmode/loadables';
@@ -0,0 +1 @@
1
+ export * from '../textmode/loading';
@@ -0,0 +1 @@
1
+ export type { TextmodePlugin, TextmodePluginAPI, TextmodePluginHook, LayerLifecycleHook, LayerRenderHook, SetupLifecycleHook, } from '../textmode/managers/PluginManager';
@@ -16,7 +16,40 @@ export type { TextmodeFramebufferOptions } from './rendering/webgl';
16
16
  * but custom strategies can be registered via {@link TextmodeConversionManager.register}.
17
17
  */
18
18
  export * as conversion from './textmode/conversion';
19
- export type { TextmodePlugin, TextmodePluginAPI } from './textmode/managers/PluginManager';
19
+ /**
20
+ * Plugin system types for extending textmode.js functionality.
21
+ *
22
+ * Plugins can:
23
+ * - Add methods to TextmodeLayer instances (e.g., `.synth()`)
24
+ * - Hook into the render lifecycle (pre/post draw, per-layer rendering)
25
+ * - React to layer creation and disposal events
26
+ * - Access the WebGL renderer, framebuffers, and other internals
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * import type { TextmodePlugin, TextmodePluginAPI } from 'textmode.js/plugins';
31
+ *
32
+ * const MyPlugin: TextmodePlugin = {
33
+ * name: 'my-plugin',
34
+ * version: '1.0.0',
35
+ * install(textmodifier, api) {
36
+ * // Extend layers with a new method
37
+ * api.extendLayer('myMethod', function(value) {
38
+ * this.setPluginState('my-plugin', { value });
39
+ * });
40
+ *
41
+ * // Hook into layer rendering
42
+ * api.registerLayerPreRenderHook((layer, ctx) => {
43
+ * const state = layer.getPluginState('my-plugin');
44
+ * if (state) {
45
+ * // Render plugin content to layer.drawFramebuffer
46
+ * }
47
+ * });
48
+ * }
49
+ * };
50
+ * ```
51
+ */
52
+ export * as plugins from './textmode/managers/PluginManager';
20
53
  /**
21
54
  * All filter related modules and types.
22
55
  *
@@ -28,6 +61,7 @@ export type { TextmodePlugin, TextmodePluginAPI } from './textmode/managers/Plug
28
61
  */
29
62
  export * as filters from './textmode/filters';
30
63
  export { TextmodeErrorLevel } from './errors/ErrorHandler';
64
+ export { GLShader as TextmodeShader } from './rendering/webgl/core/Shader';
31
65
  export { Textmode as textmode } from './Textmode';
32
66
  /** All loading screen related modules and types. */
33
67
  export * as loading from './textmode/loading';
@@ -81,7 +81,7 @@ export declare class GLFramebuffer implements IFramebuffer {
81
81
  * @ignore
82
82
  */
83
83
  private _updateMaterial;
84
- $dispose(): void;
84
+ dispose(): void;
85
85
  /** Get the width of the framebuffer */
86
86
  get width(): number;
87
87
  /** Get the height of the framebuffer */
@@ -4,8 +4,13 @@ import { GLFramebuffer } from './Framebuffer';
4
4
  */
5
5
  export type UniformValue = number | boolean | number[] | number[][] | Float32Array | Int32Array | GLFramebuffer | WebGLTexture;
6
6
  /**
7
- * WebGL implementation of the shader abstraction.
8
- * Provides GPU shader program management with automatic uniform handling and minification support.
7
+ *
8
+ * Shader class for managing WebGL shader programs initialized via {@link Textmodifier.createFilterShader} or {@link Textmodifier.createShader}.
9
+ *
10
+ * Use shaders and set uniforms via {@link Textmodifier.shader}, {@link Textmodifier.setUniform}, and {@link Textmodifier.setUniforms}.
11
+ *
12
+ * With a shader active, the next {@link Textmodifier.rect} call will use the shader for rendering,
13
+ * and automatically unuse it afterwards.
9
14
  */
10
15
  export declare class GLShader {
11
16
  private _gl;
@@ -28,22 +33,31 @@ export declare class GLShader {
28
33
  private _createShader;
29
34
  /**
30
35
  * Use this shader program
36
+ * @ignore
31
37
  */
32
38
  $use(): void;
33
39
  /**
34
40
  * Reset texture unit counter and other state
35
41
  */
36
42
  private _resetState;
43
+ /**
44
+ * Set multiple uniform values at once.
45
+ * @param uniforms An object mapping uniform names to their values.
46
+ * @ignore
47
+ */
37
48
  $setUniforms(uniforms: Record<string, any>): void;
38
49
  /**
39
50
  * Set a single uniform value with automatic texture unit management and proper type detection
51
+ * @param name The name of the uniform variable in the shader
52
+ * @param value The value to set for the uniform
53
+ * @ignore
40
54
  */
41
55
  $setUniform(name: string, value: UniformValue): void;
42
56
  private _acquireTextureUnit;
43
57
  /**
44
58
  * Get the WebGL program
45
59
  */
46
- get $glProgram(): WebGLProgram;
60
+ get program(): WebGLProgram;
47
61
  /**
48
62
  * Dispose of WebGL resources used by this shader.
49
63
  */
@@ -89,15 +89,8 @@ export interface IFramebuffer {
89
89
  /**
90
90
  * Dispose of WebGL resources used by this framebuffer.
91
91
  *
92
- * This releases:
93
- * - The WebGL framebuffer object
94
- * - All associated texture objects
95
- * - Any cached pixel data
96
- *
97
92
  * This method is idempotent and safe to call multiple times.
98
93
  * After disposal, the framebuffer should not be used for rendering.
99
- *
100
- * @ignore
101
94
  */
102
- $dispose(): void;
95
+ dispose(): void;
103
96
  }
@@ -11,7 +11,9 @@ export declare class AnimationController {
11
11
  private _lastRenderTime;
12
12
  private _frameTimeHistory;
13
13
  private _frameTimeHistorySize;
14
+ private _deltaTime;
14
15
  private _frameCount;
16
+ private _millisStart;
15
17
  /**
16
18
  * Creates an AnimationController instance.
17
19
  * @param frameRateLimit Maximum frames per second. Defaults to 60.
@@ -68,4 +70,31 @@ export declare class AnimationController {
68
70
  * Should be called on each render to track total frames rendered.
69
71
  */
70
72
  $incrementFrame(): void;
73
+ /**
74
+ * Get the number of milliseconds since the animation started.
75
+ * Returns 0 if the animation has not started yet.
76
+ */
77
+ get $millis(): number;
78
+ /**
79
+ * Set the elapsed milliseconds by adjusting the start time.
80
+ * This allows seeking/scrubbing in animations.
81
+ * @param value The new elapsed time in milliseconds
82
+ */
83
+ set $millis(value: number);
84
+ /**
85
+ * Get the number of seconds since the animation started.
86
+ * Returns 0 if the animation has not started yet.
87
+ */
88
+ get $secs(): number;
89
+ /**
90
+ * Set the elapsed seconds by adjusting the start time.
91
+ * This allows seeking/scrubbing in animations.
92
+ * @param value The new elapsed time in seconds
93
+ */
94
+ set $secs(value: number);
95
+ /**
96
+ * Get the time in milliseconds between the current frame and the last frame.
97
+ * Useful for frame-rate-independent animations.
98
+ */
99
+ get $deltaTime(): number;
71
100
  }
@@ -80,6 +80,8 @@ export declare class TextmodeGrid {
80
80
  get offsetY(): number;
81
81
  /**
82
82
  * Restores responsive sizing so subsequent `t.resizeCanvas` calls recompute cols/rows.
83
+ *
84
+ * A grid becomes non-responsive when either `cols` or `rows` is manually set.
83
85
  */
84
86
  responsive(): void;
85
87
  /**
@@ -7,8 +7,8 @@ import { AnimationController } from './AnimationController';
7
7
  import { MouseManager } from './managers/MouseManager';
8
8
  import { KeyboardManager } from './managers/KeyboardManager';
9
9
  import { TouchManager } from './managers/TouchManager';
10
+ import { TextmodePluginManager } from './managers/PluginManager';
10
11
  import type { ITextmodifier } from './interfaces';
11
- import type { GLShader } from '../rendering';
12
12
  import type { TextmodeOptions } from './types';
13
13
  import type { IAnimationMixin } from './mixins/interfaces/IAnimationMixin';
14
14
  import type { IRenderingMixin } from './mixins/interfaces/IRenderingMixin';
@@ -17,8 +17,8 @@ import type { ITouchMixin } from './mixins/interfaces/ITouchMixin';
17
17
  import type { IMouseMixin } from './mixins/interfaces/IMouseMixin';
18
18
  import { LoadingScreenManager } from './loading/LoadingScreenManager';
19
19
  import { LayerManager } from './layers/LayerManager';
20
- import type { TextmodeLayerManager } from './layers';
21
- import { TextmodeFilterManager } from './filters';
20
+ import type { TextmodeLayer, TextmodeLayerManager } from './layers';
21
+ import type { TextmodeFilterManager } from './filters';
22
22
  import type { FilterName, BuiltInFilterName, BuiltInFilterParams } from './filters';
23
23
  import { TextmodeConversionManager } from './conversion';
24
24
  declare const Textmodifier_base: {
@@ -40,23 +40,16 @@ export declare class Textmodifier extends Textmodifier_base implements ITextmodi
40
40
  _touchManager: TouchManager;
41
41
  _keyboardManager: KeyboardManager;
42
42
  _loading: LoadingScreenManager;
43
- _textmodeConversionShader: GLShader;
44
- _presentShader: GLShader;
45
43
  _layerManager: TextmodeLayerManager;
46
- _activeFont?: TextmodeFont;
47
- _activeGrid?: TextmodeGrid;
48
- _filterManager: TextmodeFilterManager;
44
+ _activeLayer?: TextmodeLayer;
49
45
  _conversionManager: TextmodeConversionManager;
50
- private _globalFilterQueue;
51
- private _preFilterFramebuffer;
52
- private _postFilterFramebuffer;
53
- private _pluginManager;
46
+ /** @ignore */
47
+ _pluginManager: TextmodePluginManager;
54
48
  private _destroyRequested;
55
49
  private _isRenderingFrame;
56
50
  private _isDisposed;
57
51
  private _setupComplete;
58
52
  private _setupCallback;
59
- private _drawCallback;
60
53
  private _resizedCallback;
61
54
  private _windowResizeListener;
62
55
  private _resizeObserver?;
@@ -81,17 +74,16 @@ export declare class Textmodifier extends Textmodifier_base implements ITextmodi
81
74
  private _performDestroy;
82
75
  filter<T extends BuiltInFilterName>(name: T, params?: BuiltInFilterParams[T]): void;
83
76
  filter(name: FilterName, params?: unknown): void;
77
+ draw(callback: () => void): void;
84
78
  loadFont(fontSource: string): Promise<TextmodeFont>;
85
79
  fontSize(size: number): void;
86
80
  inputGrid(target?: 'topmost' | TextmodeGrid): 'topmost' | TextmodeGrid | void;
87
81
  /**
88
82
  * Get the grid used for input coordinate mapping.
89
83
  * Returns the override grid/layer's grid if set, otherwise the topmost visible layer's grid.
90
- * @ignore
91
84
  */
92
85
  private _getInputGrid;
93
86
  setup(callback: () => void | Promise<void>): Promise<void>;
94
- draw(callback: () => void): void;
95
87
  windowResized(callback: () => void): void;
96
88
  get grid(): TextmodeGrid | undefined;
97
89
  get font(): TextmodeFont;
@@ -104,6 +96,7 @@ export declare class Textmodifier extends Textmodifier_base implements ITextmodi
104
96
  get layers(): LayerManager;
105
97
  get filters(): TextmodeFilterManager;
106
98
  get conversions(): TextmodeConversionManager;
99
+ get isRenderingFrame(): boolean;
107
100
  }
108
101
  export interface Textmodifier extends IRenderingMixin, IAnimationMixin, IMouseMixin, ITouchMixin, IKeyboardMixin {
109
102
  }
@@ -3,7 +3,6 @@ import type { TextmodeFont } from '../loadables/font';
3
3
  import type { TextmodeImage } from '../loadables/TextmodeImage';
4
4
  import type { TextmodeCanvas } from '../Canvas';
5
5
  import type { AnimationController } from '../AnimationController';
6
- import type { GLShader } from '../../rendering';
7
6
  import type { GLRenderer } from '../../rendering/webgl/core/Renderer';
8
7
  import type { MouseManager } from '../managers/MouseManager';
9
8
  import type { KeyboardManager } from '../managers/KeyboardManager';
@@ -15,6 +14,7 @@ import type { IMouseMixin } from '../mixins/interfaces/IMouseMixin';
15
14
  import type { IAnimationMixin } from '../mixins/interfaces/IAnimationMixin';
16
15
  import type { LoadingScreenManager } from '../loading/LoadingScreenManager';
17
16
  import type { TextmodeLayerManager } from '../layers';
17
+ import type { TextmodeLayer } from '../layers/TextmodeLayer';
18
18
  import type { BuiltInFilterName, BuiltInFilterParams, TextmodeFilterManager, FilterName } from '../filters';
19
19
  import type { TextmodeConversionManager } from '../conversion';
20
20
  /**
@@ -38,22 +38,14 @@ export interface ITextmodifier extends IRenderingMixin, IAnimationMixin, IMouseM
38
38
  readonly _touchManager: TouchManager;
39
39
  /** Keyboard interaction manager @ignore */
40
40
  readonly _keyboardManager: KeyboardManager;
41
- /** Shader used for converting pixels to textmode grid format @ignore */
42
- readonly _textmodeConversionShader: GLShader;
43
- /** Shader used for final presentation to the screen @ignore */
44
- readonly _presentShader: GLShader;
45
41
  /** Loading screen manager for boot-time UX @ignore */
46
42
  readonly _loading: LoadingScreenManager;
47
43
  /** Conversion manager for image-to-ASCII conversion @ignore */
48
44
  readonly _conversionManager: TextmodeConversionManager;
49
- /** Filter manager for applying post-processing effects @ignore */
50
- readonly _filterManager: TextmodeFilterManager;
51
45
  /** Layer manager for handling multiple layers @ignore */
52
46
  readonly _layerManager: TextmodeLayerManager;
53
- /** Active font based on layer, or loading screen font override @ignore */
54
- _activeFont?: TextmodeFont;
55
- /** Active grid based on layer currently being rendered @ignore */
56
- _activeGrid?: TextmodeGrid;
47
+ /** Active layer currently being rendered @ignore */
48
+ _activeLayer?: TextmodeLayer;
57
49
  /** Main render method @ignore */
58
50
  $render(): void;
59
51
  /**
@@ -0,0 +1,205 @@
1
+ /**
2
+ * A 3D camera/transform controller for the voxel raymarching system.
3
+ *
4
+ * This class encapsulates the 3D transformation state (rotation, translation, zoom)
5
+ * used when rendering layers in 3D mode. It provides a clean separation between
6
+ * camera/viewport concerns and layer management.
7
+ *
8
+ * The camera operates in a right-handed coordinate system where:
9
+ * - X axis points right
10
+ * - Y axis points up
11
+ * - Z axis points toward the viewer (out of the screen)
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const camera = new Camera3D();
16
+ *
17
+ * // Set rotation (degrees)
18
+ * camera.rotation(45, 30, 0);
19
+ *
20
+ * // Get current rotation
21
+ * const [rx, ry, rz] = camera.rotation();
22
+ *
23
+ * // Animate
24
+ * camera.rotateY(camera.rotation()[1] + 1);
25
+ *
26
+ * // Reset to defaults
27
+ * camera.reset();
28
+ * ```
29
+ */
30
+ export declare class Camera3D {
31
+ private _rotation;
32
+ private _translation;
33
+ private _zoom;
34
+ private _rotationMatrixCache;
35
+ /**
36
+ * Create a new Camera3D with default values.
37
+ *
38
+ * @param options Initial camera configuration
39
+ */
40
+ constructor(options?: Camera3DOptions);
41
+ /**
42
+ * Set or get the rotation angles in degrees.
43
+ *
44
+ * When called with arguments, sets the rotation and returns void.
45
+ * When called without arguments, returns the current rotation.
46
+ *
47
+ * @param x Rotation around X axis in degrees
48
+ * @param y Rotation around Y axis in degrees (defaults to 0 if x provided)
49
+ * @param z Rotation around Z axis in degrees (defaults to 0 if x provided)
50
+ * @returns Current rotation as [x, y, z] tuple if no arguments provided
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * camera.rotation(45, 30, 0); // Set rotation
55
+ * const rot = camera.rotation(); // Get [45, 30, 0]
56
+ * ```
57
+ */
58
+ rotation(x?: number, y?: number, z?: number): [number, number, number] | void;
59
+ /**
60
+ * Set or get rotation around the X axis only.
61
+ *
62
+ * @param degrees Rotation in degrees, or undefined to get current value
63
+ * @returns Current X rotation if no argument provided
64
+ */
65
+ rotateX(degrees?: number): number | void;
66
+ /**
67
+ * Set or get rotation around the Y axis only.
68
+ *
69
+ * @param degrees Rotation in degrees, or undefined to get current value
70
+ * @returns Current Y rotation if no argument provided
71
+ */
72
+ rotateY(degrees?: number): number | void;
73
+ /**
74
+ * Set or get rotation around the Z axis only.
75
+ *
76
+ * @param degrees Rotation in degrees, or undefined to get current value
77
+ * @returns Current Z rotation if no argument provided
78
+ */
79
+ rotateZ(degrees?: number): number | void;
80
+ /**
81
+ * Set or get the translation offset in world units.
82
+ *
83
+ * @param x Translation along X axis
84
+ * @param y Translation along Y axis (defaults to 0 if x provided)
85
+ * @param z Translation along Z axis (defaults to 0 if x provided)
86
+ * @returns Current translation as [x, y, z] tuple if no arguments provided
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * camera.translation(10, 5, 0); // Set translation
91
+ * const pos = camera.translation(); // Get [10, 5, 0]
92
+ * ```
93
+ */
94
+ translation(x?: number, y?: number, z?: number): [number, number, number] | void;
95
+ /**
96
+ * Set or get translation along the X axis only.
97
+ *
98
+ * @param units Translation amount, or undefined to get current value
99
+ * @returns Current X translation if no argument provided
100
+ */
101
+ translateX(units?: number): number | void;
102
+ /**
103
+ * Set or get translation along the Y axis only.
104
+ *
105
+ * @param units Translation amount, or undefined to get current value
106
+ * @returns Current Y translation if no argument provided
107
+ */
108
+ translateY(units?: number): number | void;
109
+ /**
110
+ * Set or get translation along the Z axis only.
111
+ *
112
+ * @param units Translation amount, or undefined to get current value
113
+ * @returns Current Z translation if no argument provided
114
+ */
115
+ translateZ(units?: number): number | void;
116
+ /**
117
+ * Set or get the zoom level.
118
+ *
119
+ * Values greater than 1 zoom in, values less than 1 zoom out.
120
+ * The minimum zoom level is 0.001 to prevent division by zero.
121
+ *
122
+ * @param factor Zoom factor (1 = no zoom)
123
+ * @returns Current zoom if no argument provided
124
+ *
125
+ * @example
126
+ * ```ts
127
+ * camera.zoom(2); // Zoom in 2x
128
+ * const z = camera.zoom(); // Get 2
129
+ * camera.zoom(0.5); // Zoom out 50%
130
+ * ```
131
+ */
132
+ zoom(factor?: number): number | void;
133
+ /**
134
+ * Reset the camera to default values.
135
+ *
136
+ * - Rotation: [0, 0, 0]
137
+ * - Translation: [0, 0, 0]
138
+ * - Zoom: 1
139
+ */
140
+ reset(): void;
141
+ /**
142
+ * Copy values from another Camera3D instance.
143
+ *
144
+ * @param other The camera to copy from
145
+ */
146
+ copyFrom(other: Camera3D): void;
147
+ /**
148
+ * Create a clone of this camera.
149
+ *
150
+ * @returns A new Camera3D instance with the same values
151
+ */
152
+ clone(): Camera3D;
153
+ /**
154
+ * Get the rotation matrix as a Float32Array for GPU upload.
155
+ *
156
+ * The matrix is computed from the current Euler angles and transposed
157
+ * (inverted) for use in the shader. The result is cached and only
158
+ * recomputed when rotation values change.
159
+ *
160
+ * @returns Transposed 3x3 rotation matrix as Float32Array
161
+ */
162
+ getRotationMatrix(): Float32Array;
163
+ /**
164
+ * Get all transform parameters in a format ready for shader uniforms.
165
+ *
166
+ * @returns Object containing all transform data for GPU upload
167
+ */
168
+ getShaderUniforms(): Camera3DShaderUniforms;
169
+ /**
170
+ * Invalidate the cached rotation matrix.
171
+ * Called whenever rotation values change.
172
+ */
173
+ private _invalidateRotationCache;
174
+ }
175
+ /**
176
+ * Options for creating a new Camera3D instance.
177
+ */
178
+ export interface Camera3DOptions {
179
+ /**
180
+ * Initial rotation in degrees around X, Y, Z axes.
181
+ * @default [0, 0, 0]
182
+ */
183
+ rotation?: [number, number, number];
184
+ /**
185
+ * Initial translation offset in world units.
186
+ * @default [0, 0, 0]
187
+ */
188
+ translation?: [number, number, number];
189
+ /**
190
+ * Initial zoom factor. Values > 1 zoom in, < 1 zoom out.
191
+ * @default 1
192
+ */
193
+ zoom?: number;
194
+ }
195
+ /**
196
+ * Shader uniforms generated by Camera3D for GPU upload.
197
+ */
198
+ export interface Camera3DShaderUniforms {
199
+ /** Transposed 3x3 rotation matrix */
200
+ rotation: Float32Array;
201
+ /** Translation offset [x, y, z] */
202
+ translation: [number, number, number];
203
+ /** Zoom factor */
204
+ zoom: number;
205
+ }
@@ -0,0 +1,152 @@
1
+ import type { GLRenderer, GLFramebuffer } from '../../rendering';
2
+ import type { TextmodeLayer } from './TextmodeLayer';
3
+ import type { TextmodeFont } from '../loadables/font';
4
+ import type { TextmodeGrid } from '../Grid';
5
+ import type { Camera3D } from './Camera3D';
6
+ /**
7
+ * 3D rendering options for the voxel raymarching system.
8
+ */
9
+ export interface Layer3DOptions {
10
+ /**
11
+ * Camera containing rotation, translation, and zoom.
12
+ * If provided, rotation/translation/zoom properties below are ignored.
13
+ */
14
+ camera?: Camera3D;
15
+ /**
16
+ * Index of a specific layer to render in isolation.
17
+ * Set to -1 to render all layers.
18
+ * @default -1
19
+ */
20
+ isolatedLayer?: number;
21
+ /**
22
+ * Custom normal vectors for each voxel face (for lighting effects).
23
+ */
24
+ normals?: {
25
+ right?: [number, number, number];
26
+ left?: [number, number, number];
27
+ top?: [number, number, number];
28
+ bottom?: [number, number, number];
29
+ front?: [number, number, number];
30
+ back?: [number, number, number];
31
+ };
32
+ }
33
+ /**
34
+ * Parameters for the 3D composite operation.
35
+ */
36
+ export interface Composite3DParams {
37
+ /** The base layer's draw framebuffer. */
38
+ baseDrawFramebuffer: GLFramebuffer;
39
+ /** The target framebuffer to render the final result into. */
40
+ targetFramebuffer: GLFramebuffer;
41
+ /** The background color as RGBA values (0-1 range). */
42
+ backgroundColor: [number, number, number, number];
43
+ /** The base layer configuration. */
44
+ baseLayer: TextmodeLayer;
45
+ /** The array of user layers to stack. */
46
+ layers: readonly TextmodeLayer[];
47
+ /** The font used for character texture lookup (from base layer). */
48
+ font: TextmodeFont;
49
+ /** The grid with the largest dimensions (cols × rows) to use as reference. */
50
+ grid: TextmodeGrid;
51
+ /** Canvas width in pixels. */
52
+ canvasWidth: number;
53
+ /** Canvas height in pixels. */
54
+ canvasHeight: number;
55
+ /** 3D rendering options. */
56
+ options3D?: Layer3DOptions;
57
+ }
58
+ /**
59
+ * Handles the compositing of multiple layers using 3D voxel raymarching.
60
+ *
61
+ * This class is responsible for:
62
+ * - Combining all layer draw framebuffers into a single stacked atlas texture
63
+ * - Rendering the stacked layers as a 3D voxel grid using raymarching
64
+ * - Supporting rotation, zoom, and other 3D transformations
65
+ *
66
+ * @internal
67
+ *
68
+ * @remarks
69
+ * The compositor creates a stacked texture atlas where each layer's draw data
70
+ * is placed vertically in the texture. The 3D shader interprets this as a
71
+ * voxel grid with depth equal to the number of layers.
72
+ *
73
+ * Atlas layout:
74
+ * - Width: grid.cols
75
+ * - Height: grid.rows * (1 + numUserLayers)
76
+ * - Layer 0 (z=0, front): base layer at top
77
+ * - Layer N (z=N): user layers stacked below
78
+ */
79
+ export declare class Layer3DCompositor {
80
+ private readonly _renderer;
81
+ private readonly _shaderGBuffer;
82
+ private readonly _shaderShade;
83
+ private _stackedAsciiBuffer;
84
+ private _stackedPrimaryBuffer;
85
+ private _stackedSecondaryBuffer;
86
+ private _gBuffer;
87
+ private _currentLayerCount;
88
+ private _canvasWidth;
89
+ private _canvasHeight;
90
+ private _maxCols;
91
+ private _maxRows;
92
+ /**
93
+ * Create a new Layer3DCompositor.
94
+ * @param renderer The WebGL renderer instance.
95
+ */
96
+ constructor(renderer: GLRenderer);
97
+ /**
98
+ * Initialize the compositor's framebuffers.
99
+ * @param maxCols Maximum columns across all layers.
100
+ * @param maxRows Maximum rows across all layers.
101
+ * @param totalLayers Total number of layers (1 base + N user layers).
102
+ * @ignore
103
+ */
104
+ $initialize(maxCols: number, maxRows: number, totalLayers?: number): void;
105
+ /**
106
+ * Resize the stacked atlas buffers to accommodate new dimensions.
107
+ * @param maxCols Maximum columns across all layers.
108
+ * @param maxRows Maximum rows across all layers.
109
+ * @param totalLayers Total number of layers.
110
+ * @ignore
111
+ */
112
+ $resize(maxCols: number, maxRows: number, totalLayers?: number): void;
113
+ /**
114
+ * Composite all layers into a 3D voxel render.
115
+ * @param params The composite parameters.
116
+ */
117
+ $composite(params: Composite3DParams): void;
118
+ /**
119
+ * Build the stacked atlas by copying each layer's draw data.
120
+ * Each layer is centered within the max dimensions.
121
+ */
122
+ private _buildStackedAtlas;
123
+ /**
124
+ * Copy a source texture into a region of the target atlas framebuffer.
125
+ * Uses blitFramebuffer for efficient GPU-side copies.
126
+ */
127
+ private _copyTextureToAtlas;
128
+ /**
129
+ * Render the 3D voxel scene using two-pass deferred rendering.
130
+ * Pass 1: G-Buffer generation (raymarching, outputs voxel coords + surface data)
131
+ * Pass 2: Shading (reads G-buffer, samples textures, applies character rendering)
132
+ */
133
+ private _render3D;
134
+ /**
135
+ * Ensure the G-buffer exists and is correctly sized.
136
+ * Uses RGBA8 textures with normalized encoding for maximum compatibility.
137
+ */
138
+ private _ensureGBuffer;
139
+ /**
140
+ * Dispose of all compositor resources.
141
+ * @ignore
142
+ */
143
+ $dispose(): void;
144
+ /**
145
+ * Get the current maximum columns in the stacked atlas.
146
+ */
147
+ get $maxCols(): number;
148
+ /**
149
+ * Get the current maximum rows per layer in the stacked atlas.
150
+ */
151
+ get $maxRows(): number;
152
+ }