@lightningjs/renderer 1.0.0-rc.0 → 1.0.0-rc.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 (54) hide show
  1. package/README.md +27 -48
  2. package/dist/exports/index.d.ts +6 -1
  3. package/dist/exports/index.js +5 -0
  4. package/dist/exports/index.js.map +1 -1
  5. package/dist/exports/utils.d.ts +1 -0
  6. package/dist/exports/utils.js +1 -0
  7. package/dist/exports/utils.js.map +1 -1
  8. package/dist/src/core/CoreNode.d.ts +3 -4
  9. package/dist/src/core/CoreNode.js +14 -16
  10. package/dist/src/core/CoreNode.js.map +1 -1
  11. package/dist/src/core/CoreShaderManager.d.ts +1 -1
  12. package/dist/src/core/Stage.js +1 -1
  13. package/dist/src/core/Stage.js.map +1 -1
  14. package/dist/src/core/animations/CoreAnimation.d.ts +1 -1
  15. package/dist/src/core/animations/CoreAnimation.js +28 -26
  16. package/dist/src/core/animations/CoreAnimation.js.map +1 -1
  17. package/dist/src/core/renderers/CoreRenderer.d.ts +5 -0
  18. package/dist/src/core/renderers/CoreRenderer.js.map +1 -1
  19. package/dist/src/core/renderers/canvas/CanvasCoreRenderer.d.ts +1 -0
  20. package/dist/src/core/renderers/canvas/CanvasCoreRenderer.js +3 -0
  21. package/dist/src/core/renderers/canvas/CanvasCoreRenderer.js.map +1 -1
  22. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.d.ts +3 -1
  23. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.js +11 -1
  24. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.js.map +1 -1
  25. package/dist/src/core/renderers/webgl/shaders/DynamicShader.d.ts +1 -58
  26. package/dist/src/core/renderers/webgl/shaders/DynamicShader.js.map +1 -1
  27. package/dist/src/core/renderers/webgl/shaders/RoundedRectangle.js +3 -1
  28. package/dist/src/core/renderers/webgl/shaders/RoundedRectangle.js.map +1 -1
  29. package/dist/src/core/renderers/webgl/shaders/effects/ShaderEffect.d.ts +58 -0
  30. package/dist/src/core/renderers/webgl/shaders/effects/ShaderEffect.js.map +1 -1
  31. package/dist/src/main-api/DynamicShaderController.d.ts +6 -5
  32. package/dist/src/main-api/DynamicShaderController.js +3 -0
  33. package/dist/src/main-api/DynamicShaderController.js.map +1 -1
  34. package/dist/src/main-api/INode.d.ts +1 -1
  35. package/dist/src/main-api/Renderer.d.ts +45 -4
  36. package/dist/src/main-api/Renderer.js +45 -2
  37. package/dist/src/main-api/Renderer.js.map +1 -1
  38. package/dist/tsconfig.dist.tsbuildinfo +1 -1
  39. package/exports/index.ts +10 -1
  40. package/exports/utils.ts +1 -0
  41. package/package.json +1 -1
  42. package/src/core/CoreNode.ts +18 -19
  43. package/src/core/CoreShaderManager.ts +2 -2
  44. package/src/core/Stage.ts +1 -1
  45. package/src/core/animations/CoreAnimation.ts +35 -33
  46. package/src/core/renderers/CoreRenderer.ts +6 -0
  47. package/src/core/renderers/canvas/CanvasCoreRenderer.ts +3 -0
  48. package/src/core/renderers/webgl/WebGlCoreRenderer.ts +13 -1
  49. package/src/core/renderers/webgl/shaders/DynamicShader.ts +2 -59
  50. package/src/core/renderers/webgl/shaders/RoundedRectangle.ts +4 -1
  51. package/src/core/renderers/webgl/shaders/effects/ShaderEffect.ts +60 -0
  52. package/src/main-api/DynamicShaderController.ts +12 -5
  53. package/src/main-api/INode.ts +3 -2
  54. package/src/main-api/Renderer.ts +52 -5
@@ -45,7 +45,7 @@ export class CoreAnimation extends EventEmitter {
45
45
  private timingFunction: (t: number) => number | undefined;
46
46
 
47
47
  propValuesMap: PropValuesMap = {};
48
- dynPropValuesMap: PropValuesMap = {};
48
+ dynPropValuesMap: PropValuesMap | undefined = undefined;
49
49
 
50
50
  constructor(
51
51
  private node: CoreNode,
@@ -76,16 +76,15 @@ export class CoreAnimation extends EventEmitter {
76
76
  } else {
77
77
  const shaderPropKeys = Object.keys(props.shaderProps!);
78
78
  const spLength = shaderPropKeys.length;
79
- let j = 0;
80
- for (; j < spLength; j++) {
79
+ this.dynPropValuesMap = {};
80
+ for (let j = 0; j < spLength; j++) {
81
81
  const effectName = shaderPropKeys[j]!;
82
82
  const effect = props.shaderProps![effectName]!;
83
83
  this.dynPropValuesMap[effectName] = {};
84
84
  const effectProps = Object.entries(effect);
85
85
  const eLength = effectProps.length;
86
86
 
87
- let k = 0;
88
- for (; k < eLength; k++) {
87
+ for (let k = 0; k < eLength; k++) {
89
88
  const [key, value] = effectProps[k]!;
90
89
  this.dynPropValuesMap[effectName]![key] = {
91
90
  start: node.shader.props[effectName][key],
@@ -145,16 +144,17 @@ export class CoreAnimation extends EventEmitter {
145
144
  );
146
145
  }
147
146
 
148
- const dynEntries = Object.keys(this.dynPropValuesMap);
149
- const dynEntriesL = dynEntries.length;
150
- if (dynEntriesL > 0) {
151
- let i = 0;
152
- for (; i < dynEntriesL; i++) {
153
- const key = dynEntries[i]!;
154
- this.restoreValues(
155
- this.node.shader.props[key],
156
- this.dynPropValuesMap[key]!,
157
- );
147
+ if (this.dynPropValuesMap !== undefined) {
148
+ const dynEntries = Object.keys(this.dynPropValuesMap);
149
+ const dynEntriesL = dynEntries.length;
150
+ if (dynEntriesL > 0) {
151
+ for (let i = 0; i < dynEntriesL; i++) {
152
+ const key = dynEntries[i]!;
153
+ this.restoreValues(
154
+ this.node.shader.props[key],
155
+ this.dynPropValuesMap[key]!,
156
+ );
157
+ }
158
158
  }
159
159
  }
160
160
  }
@@ -182,13 +182,14 @@ export class CoreAnimation extends EventEmitter {
182
182
  this.reverseValues(this.propValuesMap['shaderProps']);
183
183
  }
184
184
 
185
- const dynEntries = Object.keys(this.dynPropValuesMap);
186
- const dynEntriesL = dynEntries.length;
187
- if (dynEntriesL > 0) {
188
- let i = 0;
189
- for (; i < dynEntriesL; i++) {
190
- const key = dynEntries[i]!;
191
- this.reverseValues(this.dynPropValuesMap[key]!);
185
+ if (this.dynPropValuesMap !== undefined) {
186
+ const dynEntries = Object.keys(this.dynPropValuesMap);
187
+ const dynEntriesL = dynEntries.length;
188
+ if (dynEntriesL > 0) {
189
+ for (let i = 0; i < dynEntriesL; i++) {
190
+ const key = dynEntries[i]!;
191
+ this.reverseValues(this.dynPropValuesMap[key]!);
192
+ }
192
193
  }
193
194
  }
194
195
 
@@ -309,17 +310,18 @@ export class CoreAnimation extends EventEmitter {
309
310
  );
310
311
  }
311
312
 
312
- const dynEntries = Object.keys(this.dynPropValuesMap);
313
- const dynEntriesL = dynEntries.length;
314
- if (dynEntriesL > 0) {
315
- let i = 0;
316
- for (; i < dynEntriesL; i++) {
317
- const key = dynEntries[i]!;
318
- this.updateValues(
319
- this.node.shader.props[key],
320
- this.dynPropValuesMap[key]!,
321
- easing,
322
- );
313
+ if (this.dynPropValuesMap !== undefined) {
314
+ const dynEntries = Object.keys(this.dynPropValuesMap);
315
+ const dynEntriesL = dynEntries.length;
316
+ if (dynEntriesL > 0) {
317
+ for (let i = 0; i < dynEntriesL; i++) {
318
+ const key = dynEntries[i]!;
319
+ this.updateValues(
320
+ this.node.shader.props[key],
321
+ this.dynPropValuesMap[key]!,
322
+ easing,
323
+ );
324
+ }
323
325
  }
324
326
  }
325
327
 
@@ -72,6 +72,11 @@ export interface CoreRendererOptions {
72
72
  contextSpy: ContextSpy | null;
73
73
  }
74
74
 
75
+ export interface BufferInfo {
76
+ totalUsed: number;
77
+ totalAvailable: number;
78
+ }
79
+
75
80
  export abstract class CoreRenderer {
76
81
  public options: CoreRendererOptions;
77
82
  public mode: 'webgl' | 'canvas' | undefined;
@@ -102,5 +107,6 @@ export abstract class CoreRenderer {
102
107
  abstract renderRTTNodes(): void;
103
108
  abstract removeRTTNode(node: CoreNode): void;
104
109
  abstract renderToTexture(node: CoreNode): void;
110
+ abstract getBufferInfo(): BufferInfo | null;
105
111
  abstract getDefShaderCtr(): BaseShaderController;
106
112
  }
@@ -239,4 +239,7 @@ export class CanvasCoreRenderer extends CoreRenderer {
239
239
  renderToTexture(node: CoreNode): void {
240
240
  // noop
241
241
  }
242
+ getBufferInfo(): null {
243
+ return null;
244
+ }
242
245
  }
@@ -20,6 +20,7 @@
20
20
  import { assertTruthy, createWebGLContext, hasOwn } from '../../../utils.js';
21
21
  import {
22
22
  CoreRenderer,
23
+ type BufferInfo,
23
24
  type CoreRendererOptions,
24
25
  type QuadOptions,
25
26
  } from '../CoreRenderer.js';
@@ -54,6 +55,7 @@ import type { BaseShaderController } from '../../../main-api/ShaderController.js
54
55
  import { ImageTexture } from '../../textures/ImageTexture.js';
55
56
 
56
57
  const WORDS_PER_QUAD = 24;
58
+ const QUAD_BUFFER_SIZE = 4 * 1024 * 1024;
57
59
  // const BYTES_PER_QUAD = WORDS_PER_QUAD * 4;
58
60
 
59
61
  export type WebGlCoreRendererOptions = CoreRendererOptions;
@@ -69,7 +71,7 @@ export class WebGlCoreRenderer extends CoreRenderer {
69
71
  system: CoreWebGlSystem;
70
72
 
71
73
  //// Persistent data
72
- quadBuffer: ArrayBuffer = new ArrayBuffer(1024 * 1024 * 4);
74
+ quadBuffer: ArrayBuffer = new ArrayBuffer(QUAD_BUFFER_SIZE);
73
75
  fQuadBuffer: Float32Array = new Float32Array(this.quadBuffer);
74
76
  uiQuadBuffer: Uint32Array = new Uint32Array(this.quadBuffer);
75
77
  renderOps: WebGlCoreRenderOp[] = [];
@@ -90,6 +92,7 @@ export class WebGlCoreRenderer extends CoreRenderer {
90
92
  */
91
93
  defaultTexture: Texture;
92
94
 
95
+ quadBufferUsage = 0;
93
96
  /**
94
97
  * Whether the renderer is currently rendering to a texture.
95
98
  */
@@ -613,6 +616,7 @@ export class WebGlCoreRenderer extends CoreRenderer {
613
616
  }
614
617
  renderOp.draw();
615
618
  });
619
+ this.quadBufferUsage = this.curBufferIdx * arr.BYTES_PER_ELEMENT;
616
620
  }
617
621
 
618
622
  renderToTexture(node: CoreNode) {
@@ -694,6 +698,14 @@ export class WebGlCoreRenderer extends CoreRenderer {
694
698
  this.rttNodes.splice(index, 1);
695
699
  }
696
700
 
701
+ getBufferInfo(): BufferInfo | null {
702
+ const bufferInfo: BufferInfo = {
703
+ totalAvailable: QUAD_BUFFER_SIZE,
704
+ totalUsed: this.quadBufferUsage,
705
+ };
706
+ return bufferInfo;
707
+ }
708
+
697
709
  override getDefShaderCtr(): BaseShaderController {
698
710
  return this.defShaderCtrl;
699
711
  }
@@ -16,7 +16,6 @@
16
16
  * See the License for the specific language governing permissions and
17
17
  * limitations under the License.
18
18
  */
19
- import type { ExtractProps } from '../../../CoreTextureManager.js';
20
19
  import type { WebGlCoreRenderer } from '../WebGlCoreRenderer.js';
21
20
  import {
22
21
  WebGlCoreShader,
@@ -27,70 +26,14 @@ import type { UniformInfo } from '../internal/ShaderUtils.js';
27
26
  import type { WebGlCoreCtxTexture } from '../WebGlCoreCtxTexture.js';
28
27
  import {
29
28
  ShaderEffect,
29
+ type EffectDescUnion,
30
30
  type ShaderEffectUniform,
31
31
  type ShaderEffectValueMap,
32
+ type BaseEffectDesc,
32
33
  } from './effects/ShaderEffect.js';
33
34
  import type { EffectMap } from '../../../CoreShaderManager.js';
34
35
  import { assertTruthy } from '../../../../utils.js';
35
36
 
36
- export interface BaseEffectDesc {
37
- name: string;
38
- type: keyof EffectMap;
39
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
40
- props: Record<string, any>;
41
- }
42
-
43
- export interface EffectDesc<
44
- T extends { name: string; type: keyof EffectMap } = {
45
- name: string;
46
- type: keyof EffectMap;
47
- },
48
- > extends BaseEffectDesc {
49
- name: T['name'];
50
- type: T['type'];
51
- props: ExtractProps<EffectMap[T['type']]>;
52
- }
53
-
54
- /**
55
- * Allows the `keyof EffectMap` to be mapped over and form an discriminated
56
- * union of all the EffectDescs structures individually.
57
- *
58
- * @remarks
59
- * When used like the following:
60
- * ```
61
- * MapEffectDescs<keyof EffectMap>[]
62
- * ```
63
- * The resultant type will be a discriminated union like so:
64
- * ```
65
- * (
66
- * {
67
- * name: 'effect1',
68
- * type: 'radius',
69
- * props?: {
70
- * radius?: number | number[];
71
- * }
72
- * } |
73
- * {
74
- * name: 'effect2',
75
- * type: 'border',
76
- * props?: {
77
- * width?: number;
78
- * color?: number;
79
- * }
80
- * } |
81
- * // ...
82
- * )[]
83
- * ```
84
- * Which means TypeScript will now base its type checking on the `type` field
85
- * and will know exactly what the `props` field should be based on the `type`
86
- * field.
87
- */
88
- type MapEffectDescs<T extends keyof EffectMap> = T extends keyof EffectMap
89
- ? EffectDesc<{ type: T; name: string }>
90
- : never;
91
-
92
- export type EffectDescUnion = MapEffectDescs<keyof EffectMap>;
93
-
94
37
  export interface DynamicShaderProps
95
38
  extends DimensionsShaderProp,
96
39
  AlphaShaderProp {
@@ -77,7 +77,10 @@ export class RoundedRectangle extends WebGlCoreShader {
77
77
  }
78
78
 
79
79
  protected override bindProps(props: Required<RoundedRectangleProps>): void {
80
- this.setUniform('u_radius', props.radius);
80
+ const radiusFactor =
81
+ Math.min(props.$dimensions.width, props.$dimensions.height) /
82
+ (2.0 * props.radius);
83
+ this.setUniform('u_radius', props.radius * Math.min(radiusFactor, 1));
81
84
  }
82
85
 
83
86
  override canBatchShaderProps(
@@ -1,3 +1,5 @@
1
+ import type { EffectMap } from '../../../../CoreShaderManager.js';
2
+ import type { ExtractProps } from '../../../../CoreTextureManager.js';
1
3
  import type {
2
4
  AlphaShaderProp,
3
5
  DimensionsShaderProp,
@@ -7,6 +9,64 @@ import type {
7
9
  UniformMethodMap,
8
10
  } from '../../internal/ShaderUtils.js';
9
11
 
12
+ export interface BaseEffectDesc {
13
+ name?: string;
14
+ type: keyof EffectMap;
15
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
16
+ props: Record<string, any>;
17
+ }
18
+
19
+ export interface EffectDesc<
20
+ T extends { name?: string; type: keyof EffectMap } = {
21
+ name?: string;
22
+ type: keyof EffectMap;
23
+ },
24
+ > extends BaseEffectDesc {
25
+ name?: T['name'];
26
+ type: T['type'];
27
+ props: ExtractProps<EffectMap[T['type']]>;
28
+ }
29
+
30
+ /**
31
+ * Allows the `keyof EffectMap` to be mapped over and form an discriminated
32
+ * union of all the EffectDescs structures individually.
33
+ *
34
+ * @remarks
35
+ * When used like the following:
36
+ * ```
37
+ * MapEffectDescs<keyof EffectMap>[]
38
+ * ```
39
+ * The resultant type will be a discriminated union like so:
40
+ * ```
41
+ * (
42
+ * {
43
+ * name: 'effect1',
44
+ * type: 'radius',
45
+ * props?: {
46
+ * radius?: number | number[];
47
+ * }
48
+ * } |
49
+ * {
50
+ * name: 'effect2',
51
+ * type: 'border',
52
+ * props?: {
53
+ * width?: number;
54
+ * color?: number;
55
+ * }
56
+ * } |
57
+ * // ...
58
+ * )[]
59
+ * ```
60
+ * Which means TypeScript will now base its type checking on the `type` field
61
+ * and will know exactly what the `props` field should be based on the `type`
62
+ * field.
63
+ */
64
+ type MapEffectDescs<T extends keyof EffectMap> = T extends keyof EffectMap
65
+ ? EffectDesc<{ type: T; name: string }>
66
+ : never;
67
+
68
+ export type EffectDescUnion = MapEffectDescs<keyof EffectMap>;
69
+
10
70
  export interface ShaderEffectUniform {
11
71
  value: number | number[] | boolean | string;
12
72
  type: string;
@@ -5,23 +5,27 @@ import type {
5
5
  ShaderMap,
6
6
  } from '../core/CoreShaderManager.js';
7
7
  import type { ExtractProps } from '../core/CoreTextureManager.js';
8
- import type { EffectDesc } from '../core/renderers/webgl/shaders/DynamicShader.js';
8
+ import type { EffectDesc } from '../core/renderers/webgl/shaders/effects/ShaderEffect.js';
9
9
  import type { BaseShaderController } from './ShaderController.js';
10
10
 
11
+ type OptionalName<T> = T extends string ? T : never;
12
+
11
13
  type MapEffectProps<
12
- Effects extends [...{ name: string; type: keyof EffectMap }[]],
14
+ Effects extends [...{ name?: string; type: keyof EffectMap }[]],
13
15
  > = {
14
- [K in Effects[number] as K['name']]: ExtractProps<EffectMap[K['type']]>;
16
+ [K in Effects[number] as OptionalName<K['name']>]: ExtractProps<
17
+ EffectMap[K['type']]
18
+ >;
15
19
  };
16
20
 
17
21
  export type DynamicEffects<
18
- T extends [...{ name: string; type: keyof EffectMap }[]],
22
+ T extends [...{ name?: string; type: keyof EffectMap }[]],
19
23
  > = {
20
24
  [K in keyof T]: EffectDesc<T[K]>;
21
25
  };
22
26
 
23
27
  export class DynamicShaderController<
24
- Effects extends [...{ name: string; type: keyof EffectMap }[]],
28
+ Effects extends [...{ name?: string; type: keyof EffectMap }[]],
25
29
  > implements BaseShaderController
26
30
  {
27
31
  private resolvedProps: ExtractProps<ShaderMap['DynamicShader']>;
@@ -47,6 +51,9 @@ export class DynamicShaderController<
47
51
  props: effectProps,
48
52
  type: effectType,
49
53
  } = effects[i]!;
54
+ if (effectName === undefined) {
55
+ continue;
56
+ }
50
57
  const definedEffectProps = {};
51
58
  const propEntries = Object.keys(effectProps);
52
59
  const propEntriesLength = propEntries.length;
@@ -57,8 +57,9 @@ export interface INode<SC extends BaseShaderController = BaseShaderController>
57
57
  /**
58
58
  * Properties used to animate() a Node
59
59
  */
60
- export interface INodeAnimateProps<SC extends BaseShaderController>
61
- extends Omit<CoreNodeAnimateProps, 'shaderProps'> {
60
+ export interface INodeAnimateProps<
61
+ SC extends BaseShaderController = BaseShaderController,
62
+ > extends Omit<CoreNodeAnimateProps, 'shaderProps'> {
62
63
  shaderProps: Partial<SC['props']>;
63
64
  }
64
65
 
@@ -29,7 +29,7 @@ import { Inspector } from './Inspector.js';
29
29
  import { assertTruthy, isProductionEnvironment } from '../utils.js';
30
30
  import { Stage } from '../core/Stage.js';
31
31
  import { CoreNode, type CoreNodeProps } from '../core/CoreNode.js';
32
- import { CoreTextNode, type CoreTextNodeProps } from '../core/CoreTextNode.js';
32
+ import { type CoreTextNodeProps } from '../core/CoreTextNode.js';
33
33
  import type {
34
34
  BaseShaderController,
35
35
  ShaderController,
@@ -42,7 +42,7 @@ import type {
42
42
  import type {
43
43
  EffectDesc,
44
44
  EffectDescUnion,
45
- } from '../core/renderers/webgl/shaders/DynamicShader.js';
45
+ } from '../core/renderers/webgl/shaders/effects/ShaderEffect.js';
46
46
  import type { TextureMemoryManagerSettings } from '../core/TextureMemoryManager.js';
47
47
 
48
48
  /**
@@ -470,18 +470,61 @@ export class RendererMain extends EventEmitter {
470
470
  return this.stage.shManager.loadShader(shaderType, props);
471
471
  }
472
472
 
473
+ /**
474
+ * Create a new Dynamic Shader controller
475
+ *
476
+ * @remarks
477
+ * A Dynamic Shader is a shader that can be composed of an array of mulitple
478
+ * effects. Each effect can be animated or changed after creation (provided
479
+ * the effect is given a name).
480
+ *
481
+ * Example:
482
+ * ```ts
483
+ * renderer.createNode({
484
+ * shader: renderer.createDynamicShader([
485
+ * renderer.createEffect('radius', {
486
+ * radius: 0
487
+ * }, 'effect1'),
488
+ * renderer.createEffect('border', {
489
+ * color: 0xff00ffff,
490
+ * width: 10,
491
+ * }, 'effect2'),
492
+ * ]),
493
+ * });
494
+ * ```
495
+ *
496
+ * @param effects
497
+ * @returns
498
+ */
473
499
  createDynamicShader<
474
- T extends DynamicEffects<[...{ name: string; type: keyof EffectMap }[]]>,
500
+ T extends DynamicEffects<[...{ name?: string; type: keyof EffectMap }[]]>,
475
501
  >(effects: [...T]): DynamicShaderController<T> {
476
502
  return this.stage.shManager.loadDynamicShader({
477
503
  effects: effects as EffectDescUnion[],
478
504
  });
479
505
  }
480
506
 
481
- createEffect<Name extends string, Type extends keyof EffectMap>(
482
- name: Name,
507
+ /**
508
+ * Create an effect to be used in a Dynamic Shader
509
+ *
510
+ * @remark
511
+ * The {name} parameter is optional but required if you want to animate the effect
512
+ * or change the effect's properties after creation.
513
+ *
514
+ * See {@link createDynamicShader} for an example.
515
+ *
516
+ * @param type
517
+ * @param props
518
+ * @param name
519
+ * @returns
520
+ */
521
+ createEffect<
522
+ Type extends keyof EffectMap,
523
+ Name extends string | undefined = undefined,
524
+ >(
483
525
  type: Type,
484
526
  props: EffectDesc<{ name: Name; type: Type }>['props'],
527
+ name?: Name,
485
528
  ): EffectDesc<{ name: Name; type: Type }> {
486
529
  return {
487
530
  name,
@@ -528,6 +571,10 @@ export class RendererMain extends EventEmitter {
528
571
  throw new Error('Not implemented');
529
572
  }
530
573
 
574
+ getBufferInfo() {
575
+ return this.stage.renderer.getBufferInfo();
576
+ }
577
+
531
578
  /**
532
579
  * Re-render the current frame without advancing any running animations.
533
580
  *