@codexo/exojs 0.10.0 → 0.11.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 (90) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/dist/esm/core/dev.d.ts +21 -0
  3. package/dist/esm/core/dev.js +18 -0
  4. package/dist/esm/core/dev.js.map +1 -0
  5. package/dist/esm/particles/modules/AlphaFadeOverLifetime.d.ts +2 -2
  6. package/dist/esm/particles/modules/AlphaFadeOverLifetime.js +5 -1
  7. package/dist/esm/particles/modules/AlphaFadeOverLifetime.js.map +1 -1
  8. package/dist/esm/rendering/TransformBuffer.d.ts +44 -0
  9. package/dist/esm/rendering/TransformBuffer.js +64 -0
  10. package/dist/esm/rendering/TransformBuffer.js.map +1 -1
  11. package/dist/esm/rendering/gradient/Gradient.d.ts +35 -2
  12. package/dist/esm/rendering/gradient/Gradient.js +51 -5
  13. package/dist/esm/rendering/gradient/Gradient.js.map +1 -1
  14. package/dist/esm/rendering/gradient/LinearGradient.d.ts +11 -3
  15. package/dist/esm/rendering/gradient/LinearGradient.js +23 -0
  16. package/dist/esm/rendering/gradient/LinearGradient.js.map +1 -1
  17. package/dist/esm/rendering/gradient/RadialGradient.d.ts +11 -3
  18. package/dist/esm/rendering/gradient/RadialGradient.js +19 -0
  19. package/dist/esm/rendering/gradient/RadialGradient.js.map +1 -1
  20. package/dist/esm/rendering/index.d.ts +1 -1
  21. package/dist/esm/rendering/pass/RenderPassCoordinator.d.ts +2 -2
  22. package/dist/esm/rendering/pass/RenderPassDescriptor.d.ts +2 -2
  23. package/dist/esm/rendering/pass/RenderPassDescriptor.js +1 -1
  24. package/dist/esm/rendering/plan/RenderCommand.d.ts +21 -2
  25. package/dist/esm/rendering/plan/RenderCommand.js +34 -1
  26. package/dist/esm/rendering/plan/RenderCommand.js.map +1 -1
  27. package/dist/esm/rendering/plan/RenderInstruction.d.ts +51 -0
  28. package/dist/esm/rendering/plan/RenderInstruction.js +45 -0
  29. package/dist/esm/rendering/plan/RenderInstruction.js.map +1 -0
  30. package/dist/esm/rendering/plan/RenderPlanPlayer.d.ts +4 -0
  31. package/dist/esm/rendering/plan/RenderPlanPlayer.js +58 -7
  32. package/dist/esm/rendering/plan/RenderPlanPlayer.js.map +1 -1
  33. package/dist/esm/rendering/primitives/Graphics.d.ts +70 -5
  34. package/dist/esm/rendering/primitives/Graphics.js +172 -14
  35. package/dist/esm/rendering/primitives/Graphics.js.map +1 -1
  36. package/dist/esm/rendering/sprite/spriteMaterialSources.d.ts +13 -8
  37. package/dist/esm/rendering/sprite/spriteMaterialSources.js +35 -14
  38. package/dist/esm/rendering/sprite/spriteMaterialSources.js.map +1 -1
  39. package/dist/esm/rendering/text/BitmapText.d.ts +2 -0
  40. package/dist/esm/rendering/text/BitmapText.js +8 -1
  41. package/dist/esm/rendering/text/BitmapText.js.map +1 -1
  42. package/dist/esm/rendering/text/BmFont.js +3 -0
  43. package/dist/esm/rendering/text/BmFont.js.map +1 -1
  44. package/dist/esm/rendering/text/GlyphSdf.d.ts +14 -0
  45. package/dist/esm/rendering/text/GlyphSdf.js +41 -11
  46. package/dist/esm/rendering/text/GlyphSdf.js.map +1 -1
  47. package/dist/esm/rendering/text/TextStyle.d.ts +5 -0
  48. package/dist/esm/rendering/text/TextStyle.js +1 -1
  49. package/dist/esm/rendering/text/TextStyle.js.map +1 -1
  50. package/dist/esm/rendering/texture/RenderTexture.js.map +1 -1
  51. package/dist/esm/rendering/webgl2/WebGl2Backend.d.ts +23 -1
  52. package/dist/esm/rendering/webgl2/WebGl2Backend.js +50 -0
  53. package/dist/esm/rendering/webgl2/WebGl2Backend.js.map +1 -1
  54. package/dist/esm/rendering/webgl2/WebGl2MeshRenderer.js +3 -3
  55. package/dist/esm/rendering/webgl2/WebGl2MeshRenderer.js.map +1 -1
  56. package/dist/esm/rendering/webgl2/WebGl2ParticleRenderer.d.ts +8 -0
  57. package/dist/esm/rendering/webgl2/WebGl2ParticleRenderer.js +8 -0
  58. package/dist/esm/rendering/webgl2/WebGl2ParticleRenderer.js.map +1 -1
  59. package/dist/esm/rendering/webgl2/WebGl2SpriteRenderer.d.ts +2 -0
  60. package/dist/esm/rendering/webgl2/WebGl2SpriteRenderer.js +62 -39
  61. package/dist/esm/rendering/webgl2/WebGl2SpriteRenderer.js.map +1 -1
  62. package/dist/esm/rendering/webgl2/WebGl2TextRenderer.d.ts +7 -0
  63. package/dist/esm/rendering/webgl2/WebGl2TextRenderer.js +7 -0
  64. package/dist/esm/rendering/webgl2/WebGl2TextRenderer.js.map +1 -1
  65. package/dist/esm/rendering/webgl2/glsl/sprite.vert.js +1 -1
  66. package/dist/esm/rendering/webgl2/glsl/text-color.frag.js +1 -1
  67. package/dist/esm/rendering/webgpu/WebGpuBackend.d.ts +16 -3
  68. package/dist/esm/rendering/webgpu/WebGpuBackend.js +49 -4
  69. package/dist/esm/rendering/webgpu/WebGpuBackend.js.map +1 -1
  70. package/dist/esm/rendering/webgpu/WebGpuMeshRenderer.js +53 -41
  71. package/dist/esm/rendering/webgpu/WebGpuMeshRenderer.js.map +1 -1
  72. package/dist/esm/rendering/webgpu/WebGpuParticleRenderer.d.ts +7 -0
  73. package/dist/esm/rendering/webgpu/WebGpuParticleRenderer.js +17 -11
  74. package/dist/esm/rendering/webgpu/WebGpuParticleRenderer.js.map +1 -1
  75. package/dist/esm/rendering/webgpu/WebGpuPassCoordinator.d.ts +2 -2
  76. package/dist/esm/rendering/webgpu/WebGpuPassCoordinator.js +2 -2
  77. package/dist/esm/rendering/webgpu/WebGpuSpriteRenderer.d.ts +9 -1
  78. package/dist/esm/rendering/webgpu/WebGpuSpriteRenderer.js +122 -77
  79. package/dist/esm/rendering/webgpu/WebGpuSpriteRenderer.js.map +1 -1
  80. package/dist/esm/rendering/webgpu/WebGpuTextRenderer.d.ts +7 -0
  81. package/dist/esm/rendering/webgpu/WebGpuTextRenderer.js +22 -13
  82. package/dist/esm/rendering/webgpu/WebGpuTextRenderer.js.map +1 -1
  83. package/dist/esm/rendering/webgpu/WebGpuTransformStorage.d.ts +32 -0
  84. package/dist/esm/rendering/webgpu/WebGpuTransformStorage.js +58 -12
  85. package/dist/esm/rendering/webgpu/WebGpuTransformStorage.js.map +1 -1
  86. package/dist/esm/resources/Loader.js +1 -1
  87. package/dist/esm/resources/Loader.js.map +1 -1
  88. package/dist/exo.esm.js +1022 -265
  89. package/dist/exo.esm.js.map +1 -1
  90. package/package.json +9 -5
@@ -4,6 +4,7 @@ import { Gradient } from './Gradient.js';
4
4
  * Radial gradient in UV space around `center` with normalized radius.
5
5
  */
6
6
  class RadialGradient extends Gradient {
7
+ type = 'radial';
7
8
  _center;
8
9
  _radius;
9
10
  constructor(stops, center = [0.5, 0.5], radius = 0.5) {
@@ -11,6 +12,17 @@ class RadialGradient extends Gradient {
11
12
  this._center = [center[0], center[1]];
12
13
  this._radius = Math.max(0, radius);
13
14
  }
15
+ /** Gradient center in UV space. */
16
+ get center() {
17
+ return [this._center[0], this._center[1]];
18
+ }
19
+ /** Normalized radius (UV units, clamped to be non-negative). */
20
+ get radius() {
21
+ return this._radius;
22
+ }
23
+ clone() {
24
+ return new RadialGradient(this.stops, this._center, this._radius);
25
+ }
14
26
  resolveT(u, v) {
15
27
  if (this._radius <= 0.000001) {
16
28
  return 1;
@@ -19,6 +31,13 @@ class RadialGradient extends Gradient {
19
31
  const dy = v - this._center[1];
20
32
  return Math.sqrt(dx * dx + dy * dy) / this._radius;
21
33
  }
34
+ _copyGeometry(source) {
35
+ this._center = [source._center[0], source._center[1]];
36
+ this._radius = source._radius;
37
+ }
38
+ _geometryEquals(other) {
39
+ return other instanceof RadialGradient && this._center[0] === other._center[0] && this._center[1] === other._center[1] && this._radius === other._radius;
40
+ }
22
41
  }
23
42
 
24
43
  export { RadialGradient };
@@ -1 +1 @@
1
- {"version":3,"file":"RadialGradient.js","sources":["../../../../../src/rendering/gradient/RadialGradient.ts"],"sourcesContent":[null],"names":[],"mappings":";;AAEA;;AAEG;AACG,MAAO,cAAe,SAAQ,QAAQ,CAAA;AACzB,IAAA,OAAO;AACP,IAAA,OAAO;IAExB,WAAA,CAAmB,KAA8B,EAAE,MAAA,GAAoC,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,EAAA;QAC7G,KAAK,CAAC,KAAK,CAAC;AAEZ,QAAA,IAAI,CAAC,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QACrC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC;IACpC;IAEmB,QAAQ,CAAC,CAAS,EAAE,CAAS,EAAA;AAC9C,QAAA,IAAI,IAAI,CAAC,OAAO,IAAI,QAAQ,EAAE;AAC5B,YAAA,OAAO,CAAC;QACV;QAEA,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QAC9B,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;AAE9B,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO;IACpD;AACD;;;;"}
1
+ {"version":3,"file":"RadialGradient.js","sources":["../../../../../src/rendering/gradient/RadialGradient.ts"],"sourcesContent":[null],"names":[],"mappings":";;AAEA;;AAEG;AACG,MAAO,cAAe,SAAQ,QAAQ,CAAA;IAC1B,IAAI,GAAiB,QAAQ;AAErC,IAAA,OAAO;AACP,IAAA,OAAO;IAEf,WAAA,CAAmB,KAA8B,EAAE,MAAA,GAAoC,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,EAAA;QAC7G,KAAK,CAAC,KAAK,CAAC;AAEZ,QAAA,IAAI,CAAC,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QACrC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC;IACpC;;AAGA,IAAA,IAAW,MAAM,GAAA;AACf,QAAA,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3C;;AAGA,IAAA,IAAW,MAAM,GAAA;QACf,OAAO,IAAI,CAAC,OAAO;IACrB;IAEO,KAAK,GAAA;AACV,QAAA,OAAO,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAS;IAC3E;IAEmB,QAAQ,CAAC,CAAS,EAAE,CAAS,EAAA;AAC9C,QAAA,IAAI,IAAI,CAAC,OAAO,IAAI,QAAQ,EAAE;AAC5B,YAAA,OAAO,CAAC;QACV;QAEA,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QAC9B,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;AAE9B,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO;IACpD;AAEmB,IAAA,aAAa,CAAC,MAAsB,EAAA;AACrD,QAAA,IAAI,CAAC,OAAO,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACrD,QAAA,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO;IAC/B;AAEmB,IAAA,eAAe,CAAC,KAAe,EAAA;AAChD,QAAA,OAAO,KAAK,YAAY,cAAc,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO;IAC1J;AACD;;;;"}
@@ -15,7 +15,7 @@ export type { WebGpuShaderFilterOptions } from './filters/WebGpuShaderFilter';
15
15
  export { WebGpuShaderFilter } from './filters/WebGpuShaderFilter';
16
16
  export { Geometry } from './geometry/Geometry';
17
17
  export type { AttributeType, GeometryAttribute, GeometryOptions, GeometryUsage, Topology } from './geometry/GeometryAttribute';
18
- export type { GradientStop, GradientToTextureOptions } from './gradient/Gradient';
18
+ export type { GradientStop, GradientToTextureOptions, GradientType } from './gradient/Gradient';
19
19
  export { Gradient } from './gradient/Gradient';
20
20
  export { LinearGradient } from './gradient/LinearGradient';
21
21
  export { RadialGradient } from './gradient/RadialGradient';
@@ -6,8 +6,8 @@ import type { View } from '../View';
6
6
  import type { RenderPassDescriptor, RenderPassLoad } from './RenderPassDescriptor';
7
7
  /**
8
8
  * Internal, backend-owned owner of render-pass lifecycle: target / view / clear
9
- * orchestration, the scissor and stencil-clip stacks, and — on WebGPU, from
10
- * phase 12D — the active `GPURenderPassEncoder`.
9
+ * orchestration, the scissor and stencil-clip stacks, and — on WebGPU — the
10
+ * active `GPURenderPassEncoder`.
11
11
  *
12
12
  * There is no public RenderPass API. This abstraction exists so the WebGL2 and
13
13
  * WebGPU backends can share the orchestration shape that geometric stencil
@@ -5,7 +5,7 @@ import type { View } from '../View';
5
5
  * Whether a render pass carries a stencil attachment.
6
6
  *
7
7
  * WebGL2 stencil is ambient per-target GL state, so this flag is largely
8
- * informational there; the WebGPU backend (from phase 12D onwards) uses it to
8
+ * informational there; the WebGPU backend uses it to
9
9
  * decide whether a pass descriptor needs a `depthStencilAttachment`.
10
10
  * @internal
11
11
  */
@@ -21,7 +21,7 @@ export type RenderPassLoad = 'clear' | 'load';
21
21
  * it carries a stencil attachment.
22
22
  *
23
23
  * WebGL2 maps this onto ambient framebuffer / viewport / scissor / stencil
24
- * state; WebGPU (phase 12D onwards) maps it onto a `GPURenderPassEncoder`.
24
+ * state; WebGPU maps it onto a `GPURenderPassEncoder`.
25
25
  * @internal
26
26
  */
27
27
  export interface RenderPassDescriptor {
@@ -2,7 +2,7 @@
2
2
  * Whether a render pass carries a stencil attachment.
3
3
  *
4
4
  * WebGL2 stencil is ambient per-target GL state, so this flag is largely
5
- * informational there; the WebGPU backend (from phase 12D onwards) uses it to
5
+ * informational there; the WebGPU backend uses it to
6
6
  * decide whether a pass descriptor needs a `depthStencilAttachment`.
7
7
  * @internal
8
8
  */
@@ -21,8 +21,8 @@ export declare const enum RenderEntryKind {
21
21
  * group / texture-slot state.
22
22
  *
23
23
  * When the drawable carries a {@link Material}, both keys are taken
24
- * directly from `material.pipelineKey` and `material.bindKey` (Phase 4+
25
- * Material system). When the drawable uses its default path (no material),
24
+ * directly from `material.pipelineKey` and `material.bindKey` (the Material
25
+ * system). When the drawable uses its default path (no material),
26
26
  * the keys are derived conservatively from renderer identity, blend mode,
27
27
  * and texture identity so grouping never accidentally merges draws with
28
28
  * incompatible state.
@@ -65,3 +65,22 @@ export interface DrawCommand {
65
65
  * @internal
66
66
  */
67
67
  export declare const makeMaterialKey: (drawable: Drawable, backend: RenderBackend | null) => MaterialKey;
68
+ /**
69
+ * Whether a draw command's renderer reads the shared {@link TransformBuffer} /
70
+ * transform storage. The render-group upload boundary packs each command's
71
+ * world transform (+ tint) keyed by its `nodeIndex`; only renderers that fetch
72
+ * those rows back from the buffer need a record written.
73
+ *
74
+ * Sprite and Mesh (and their subclasses — {@link AnimatedSprite}, Video,
75
+ * Graphics' meshes) fetch the transform via `nodeIndex` and therefore consume
76
+ * it. Text/BitmapText and particle renderers pack their own per-node data into
77
+ * a private data texture / uniforms and never touch the shared buffer, so they
78
+ * opt out via `_consumesSharedTransform === false` and their writes are skipped.
79
+ *
80
+ * Anything else — a custom renderer, or a drawable with no registered renderer
81
+ * (resolve throws) — defaults to writing, so behaviour is unchanged for any
82
+ * path that might still rely on the shared transform.
83
+ *
84
+ * @internal
85
+ */
86
+ export declare const drawCommandUsesSharedTransform: (command: DrawCommand, backend: RenderBackend) => boolean;
@@ -89,6 +89,39 @@ const makeMaterialKey = (drawable, backend) => {
89
89
  bindKey,
90
90
  };
91
91
  };
92
+ /**
93
+ * Whether a draw command's renderer reads the shared {@link TransformBuffer} /
94
+ * transform storage. The render-group upload boundary packs each command's
95
+ * world transform (+ tint) keyed by its `nodeIndex`; only renderers that fetch
96
+ * those rows back from the buffer need a record written.
97
+ *
98
+ * Sprite and Mesh (and their subclasses — {@link AnimatedSprite}, Video,
99
+ * Graphics' meshes) fetch the transform via `nodeIndex` and therefore consume
100
+ * it. Text/BitmapText and particle renderers pack their own per-node data into
101
+ * a private data texture / uniforms and never touch the shared buffer, so they
102
+ * opt out via `_consumesSharedTransform === false` and their writes are skipped.
103
+ *
104
+ * Anything else — a custom renderer, or a drawable with no registered renderer
105
+ * (resolve throws) — defaults to writing, so behaviour is unchanged for any
106
+ * path that might still rely on the shared transform.
107
+ *
108
+ * @internal
109
+ */
110
+ const drawCommandUsesSharedTransform = (command, backend) => {
111
+ const registry = backend.rendererRegistry;
112
+ if (!registry || typeof registry.resolve !== 'function') {
113
+ return true;
114
+ }
115
+ try {
116
+ const renderer = registry.resolve(command.drawable);
117
+ return renderer._consumesSharedTransform !== false;
118
+ }
119
+ catch {
120
+ // No renderer registered for a custom drawable: keep the conservative
121
+ // write so any consumer of the shared transform keeps working.
122
+ return true;
123
+ }
124
+ };
92
125
 
93
- export { RenderEntryKind, makeMaterialKey };
126
+ export { RenderEntryKind, drawCommandUsesSharedTransform, makeMaterialKey };
94
127
  //# sourceMappingURL=RenderCommand.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"RenderCommand.js","sources":["../../../../../src/rendering/plan/RenderCommand.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"RenderCommand.js","sources":["../../../../../src/rendering/plan/RenderCommand.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import { type DrawCommand, type MaterialKey } from './RenderCommand';
2
+ import type { GroupScope } from './RenderScope';
3
+ /**
4
+ * The canonical, reorderable unit of work in a render plan: a single draw
5
+ * that the plan player submits to the backend.
6
+ *
7
+ * Today a render instruction is exactly a {@link DrawCommand}; the alias
8
+ * names the concept the plan player consumes and that the batching layer
9
+ * reorders, independent of how the draw happens to be stored in the scope
10
+ * tree. Future {@link TransformBuffer} slotting keys on each instruction's
11
+ * stable {@link DrawCommand.nodeIndex} (within the `[0, plan.nodeCount)`
12
+ * slot space).
13
+ *
14
+ * @internal
15
+ */
16
+ export type RenderInstruction = DrawCommand;
17
+ /**
18
+ * A materialized batch unit: a maximal run of consecutive
19
+ * {@link RenderInstruction}s within a single {@link GroupScope} that share a
20
+ * GPU pipeline/bind state and may therefore be submitted together.
21
+ *
22
+ * The optimizer ({@link RenderPlanOptimizer}) already stamps this grouping
23
+ * implicitly onto each {@link DrawCommand.groupIndex}; a `RenderGroup` makes
24
+ * that batch unit explicit as a value without altering playback. The mesh
25
+ * renderers continue to detect batches by comparing adjacent `groupIndex`es,
26
+ * so this representation is purely additive.
27
+ *
28
+ * @internal
29
+ */
30
+ export interface RenderGroup {
31
+ /** Optimizer-assigned batch identity shared by every instruction in the run. */
32
+ readonly groupIndex: number;
33
+ /** Pipeline/bind state shared by the run; taken from its first instruction. */
34
+ readonly material: MaterialKey;
35
+ /** Draw instructions in submit order. */
36
+ readonly instructions: readonly RenderInstruction[];
37
+ }
38
+ /**
39
+ * Materialize the {@link RenderGroup} batch units contained directly in
40
+ * `scope`. Consecutive draw instructions that share a defined `groupIndex`
41
+ * coalesce into one group; any non-draw entry (a nested group or barrier)
42
+ * breaks the run, and a draw whose `groupIndex` is still `undefined` (i.e.
43
+ * the plan has not been optimized) forms its own singleton group — mirroring
44
+ * the adjacency semantics the mesh renderers already rely on.
45
+ *
46
+ * This is a read-only view over an (optimized) scope; it does not mutate the
47
+ * plan or affect playback order.
48
+ *
49
+ * @internal
50
+ */
51
+ export declare function collectRenderGroups(scope: GroupScope): RenderGroup[];
@@ -0,0 +1,45 @@
1
+ import { RenderEntryKind } from './RenderCommand.js';
2
+
3
+ /**
4
+ * Materialize the {@link RenderGroup} batch units contained directly in
5
+ * `scope`. Consecutive draw instructions that share a defined `groupIndex`
6
+ * coalesce into one group; any non-draw entry (a nested group or barrier)
7
+ * breaks the run, and a draw whose `groupIndex` is still `undefined` (i.e.
8
+ * the plan has not been optimized) forms its own singleton group — mirroring
9
+ * the adjacency semantics the mesh renderers already rely on.
10
+ *
11
+ * This is a read-only view over an (optimized) scope; it does not mutate the
12
+ * plan or affect playback order.
13
+ *
14
+ * @internal
15
+ */
16
+ function collectRenderGroups(scope) {
17
+ const groups = [];
18
+ let current = null;
19
+ for (const entry of scope.entries) {
20
+ if (entry.kind !== RenderEntryKind.Draw) {
21
+ current = null;
22
+ continue;
23
+ }
24
+ const command = entry.command;
25
+ const groupIndex = command.groupIndex;
26
+ if (current !== null && groupIndex !== undefined && groupIndex === current.groupIndex) {
27
+ current.instructions.push(command);
28
+ continue;
29
+ }
30
+ current = {
31
+ groupIndex: groupIndex ?? 0,
32
+ material: command.material,
33
+ instructions: [command],
34
+ };
35
+ groups.push(current);
36
+ if (groupIndex === undefined) {
37
+ // Unoptimized / non-batchable draw: never coalesce with the next one.
38
+ current = null;
39
+ }
40
+ }
41
+ return groups;
42
+ }
43
+
44
+ export { collectRenderGroups };
45
+ //# sourceMappingURL=RenderInstruction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RenderInstruction.js","sources":["../../../../../src/rendering/plan/RenderInstruction.ts"],"sourcesContent":[null],"names":[],"mappings":";;AA8CA;;;;;;;;;;;;AAYG;AACG,SAAU,mBAAmB,CAAC,KAAiB,EAAA;IACnD,MAAM,MAAM,GAAkB,EAAE;IAChC,IAAI,OAAO,GAA8B,IAAI;AAE7C,IAAA,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE;QACjC,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe,CAAC,IAAI,EAAE;YACvC,OAAO,GAAG,IAAI;YAEd;QACF;AAEA,QAAA,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO;AAC7B,QAAA,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU;AAErC,QAAA,IAAI,OAAO,KAAK,IAAI,IAAI,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,OAAO,CAAC,UAAU,EAAE;AACrF,YAAA,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC;YAElC;QACF;AAEA,QAAA,OAAO,GAAG;YACR,UAAU,EAAE,UAAU,IAAI,CAAC;YAC3B,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,YAAY,EAAE,CAAC,OAAO,CAAC;SACxB;AACD,QAAA,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;AAEpB,QAAA,IAAI,UAAU,KAAK,SAAS,EAAE;;YAE5B,OAAO,GAAG,IAAI;QAChB;IACF;AAEA,IAAA,OAAO,MAAM;AACf;;;;"}
@@ -5,5 +5,9 @@ import type { RenderScope } from './RenderScope';
5
5
  export declare class RenderPlanPlayer {
6
6
  static play(plan: RenderPlan, backend: RenderBackend): void;
7
7
  static playScope(scope: RenderScope, backend: RenderBackend): void;
8
+ private static _playScope;
8
9
  private static _playGroup;
10
+ private static _createPlaybackContext;
11
+ private static _createRenderGroupPlaybackContext;
12
+ private static _createRenderInstructionSlot;
9
13
  }
@@ -1,5 +1,6 @@
1
1
  import { RenderEntryKind } from './RenderCommand.js';
2
2
  import { RenderEffectExecutor } from './RenderEffectExecutor.js';
3
+ import { collectRenderGroups } from './RenderInstruction.js';
3
4
 
4
5
  /** @internal */
5
6
  class RenderPlanPlayer {
@@ -17,7 +18,7 @@ class RenderPlanPlayer {
17
18
  if (pass.clearColor !== null) {
18
19
  backend.clear(pass.clearColor);
19
20
  }
20
- this.playScope(pass.root, backend);
21
+ this._playScope(pass.root, backend, hooks, this._createPlaybackContext());
21
22
  }
22
23
  }
23
24
  finally {
@@ -25,31 +26,81 @@ class RenderPlanPlayer {
25
26
  }
26
27
  }
27
28
  static playScope(scope, backend) {
29
+ const hooks = backend;
30
+ this._playScope(scope, backend, hooks, this._createPlaybackContext());
31
+ }
32
+ static _playScope(scope, backend, hooks, context) {
28
33
  if (scope.kind === RenderEntryKind.Barrier) {
29
34
  RenderEffectExecutor.play(scope, backend, childScope => {
30
- this.playScope(childScope, backend);
35
+ this._playScope(childScope, backend, hooks, context);
31
36
  });
32
37
  return;
33
38
  }
34
- this._playGroup(scope, backend);
39
+ this._playGroup(scope, backend, hooks, context);
35
40
  }
36
- static _playGroup(scope, backend) {
37
- const hooks = backend;
41
+ static _playGroup(scope, backend, hooks, context) {
42
+ const groups = collectRenderGroups(scope);
43
+ let groupCursor = 0;
44
+ let currentGroup = null;
45
+ let currentInstructionIndex = 0;
38
46
  for (const entry of scope.entries) {
39
47
  if (entry.kind === RenderEntryKind.Draw) {
48
+ if (currentGroup === null) {
49
+ currentGroup = groups[groupCursor];
50
+ currentInstructionIndex = 0;
51
+ hooks._beginRenderGroup?.(currentGroup);
52
+ hooks._prepareRenderGroupUpload?.(currentGroup, this._createRenderGroupPlaybackContext(currentGroup.instructions.length, context.passInstructionIndex, context.passGroupIndex));
53
+ context.passGroupIndex++;
54
+ }
55
+ // Allocate the per-draw instruction slot only when a backend consumes
56
+ // it. No shipped backend implements `_prepareRenderInstructionSlot`, so
57
+ // skipping the `Object.freeze` slot allocation removes per-draw garbage
58
+ // from the playback hot path while preserving the extension point.
59
+ if (hooks._prepareRenderInstructionSlot !== undefined) {
60
+ const slot = this._createRenderInstructionSlot(currentInstructionIndex, context.passInstructionIndex);
61
+ hooks._prepareRenderInstructionSlot(entry.command, slot);
62
+ }
40
63
  hooks._prepareDrawCommand?.(entry.command);
41
64
  backend.draw(entry.command.drawable);
65
+ currentInstructionIndex++;
66
+ context.passInstructionIndex++;
67
+ if (currentGroup !== null && currentInstructionIndex === currentGroup.instructions.length) {
68
+ hooks._endRenderGroup?.(currentGroup);
69
+ currentGroup = null;
70
+ currentInstructionIndex = 0;
71
+ groupCursor++;
72
+ }
42
73
  }
43
74
  else if (entry.kind === RenderEntryKind.Group) {
44
- this._playGroup(entry.scope, backend);
75
+ this._playGroup(entry.scope, backend, hooks, context);
45
76
  }
46
77
  else {
47
78
  RenderEffectExecutor.play(entry.scope, backend, childScope => {
48
- this.playScope(childScope, backend);
79
+ this._playScope(childScope, backend, hooks, context);
49
80
  });
50
81
  }
51
82
  }
52
83
  }
84
+ static _createPlaybackContext() {
85
+ return {
86
+ passInstructionIndex: 0,
87
+ passGroupIndex: 0,
88
+ };
89
+ }
90
+ static _createRenderGroupPlaybackContext(groupInstructionCount, firstPassInstructionIndex, passGroupIndex) {
91
+ return Object.freeze({
92
+ groupInstructionCount,
93
+ firstPassInstructionIndex,
94
+ lastPassInstructionIndex: firstPassInstructionIndex + groupInstructionCount - 1,
95
+ passGroupIndex,
96
+ });
97
+ }
98
+ static _createRenderInstructionSlot(groupInstructionIndex, passInstructionIndex) {
99
+ return Object.freeze({
100
+ groupInstructionIndex,
101
+ passInstructionIndex,
102
+ });
103
+ }
53
104
  }
54
105
 
55
106
  export { RenderPlanPlayer };
@@ -1 +1 @@
1
- {"version":3,"file":"RenderPlanPlayer.js","sources":["../../../../../src/rendering/plan/RenderPlanPlayer.ts"],"sourcesContent":[null],"names":[],"mappings":";;;AAcA;MACa,gBAAgB,CAAA;AACpB,IAAA,OAAO,IAAI,CAAC,IAAgB,EAAE,OAAsB,EAAA;QACzD,MAAM,KAAK,GAAG,OAAkD;QAEhE,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC;AAEtC,QAAA,IAAI;AACF,YAAA,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE;AAC9B,gBAAA,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,IAAI,OAAO,CAAC,YAAY,KAAK,IAAI,CAAC,MAAM,EAAE;AAChE,oBAAA,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC;gBACtC;gBAEA,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE;AAC9B,oBAAA,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;gBAC5B;AAEA,gBAAA,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,EAAE;AAC5B,oBAAA,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC;gBAChC;gBAEA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC;YACpC;QACF;gBAAU;AACR,YAAA,KAAK,CAAC,YAAY,IAAI;QACxB;IACF;AAEO,IAAA,OAAO,SAAS,CAAC,KAAkB,EAAE,OAAsB,EAAA;QAChE,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe,CAAC,OAAO,EAAE;YAC1C,oBAAoB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,IAAG;AACrD,gBAAA,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC;AACrC,YAAA,CAAC,CAAC;YAEF;QACF;AAEA,QAAA,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC;IACjC;AAEQ,IAAA,OAAO,UAAU,CAAC,KAAiB,EAAE,OAAsB,EAAA;QACjE,MAAM,KAAK,GAAG,OAAkD;AAEhE,QAAA,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE;YACjC,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe,CAAC,IAAI,EAAE;gBACvC,KAAK,CAAC,mBAAmB,GAAG,KAAK,CAAC,OAAO,CAAC;gBAC1C,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;YACtC;iBAAO,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe,CAAC,KAAK,EAAE;gBAC/C,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC;YACvC;iBAAO;gBACL,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,IAAG;AAC3D,oBAAA,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC;AACrC,gBAAA,CAAC,CAAC;YACJ;QACF;IACF;AACD;;;;"}
1
+ {"version":3,"file":"RenderPlanPlayer.js","sources":["../../../../../src/rendering/plan/RenderPlanPlayer.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -1,32 +1,79 @@
1
1
  import { Color } from '@/core/Color';
2
2
  import { Vector } from '@/math/Vector';
3
3
  import { Container } from '@/rendering/Container';
4
+ import type { Gradient } from '@/rendering/gradient/Gradient';
4
5
  import { Mesh } from '@/rendering/mesh/Mesh';
5
6
  import type { RenderNode } from '@/rendering/RenderNode';
6
7
  /**
7
8
  * Immediate-mode 2D shape API backed by {@link Mesh} children.
8
9
  *
9
10
  * Each draw call (e.g. `drawCircle`, `drawRectangle`, `drawLine`) appends a
10
- * new {@link Mesh} child colored with the current `fillColor` or `lineColor`.
11
+ * new {@link Mesh} child painted with the active fill or stroke style. A style
12
+ * is either a solid {@link Color} or a {@link Gradient}, assigned through
13
+ * {@link fillStyle} / {@link strokeStyle}. The {@link fillColor} /
14
+ * {@link lineColor} accessors are color-only conveniences over those styles.
11
15
  * The active `lineWidth` controls stroke thickness for path and outline draws.
12
16
  * Path commands (`moveTo`, `lineTo`, `quadraticCurveTo`, etc.) track a cursor
13
17
  * point and flush a Mesh on each segment.
14
18
  *
19
+ * Gradient styles are rasterized once to a {@link DataTexture} via
20
+ * {@link Gradient.toTexture} and sampled across each shape's local bounding
21
+ * box, so {@link LinearGradient} and {@link RadialGradient} render through the
22
+ * same texture path as a textured Mesh. The textures are owned by the Graphics
23
+ * and released on {@link clear} / {@link destroy}.
24
+ *
15
25
  * Call {@link clear} to remove all child meshes and reset pen state. Because
16
26
  * each shape is a separate Mesh, `Graphics` inherits full filter, blend,
17
27
  * tint, and mask support from {@link Container}.
18
28
  */
19
29
  export declare class Graphics extends Container {
20
30
  private _lineWidth;
21
- private _lineColor;
22
- private _fillColor;
31
+ private readonly _fillColor;
32
+ private readonly _lineColor;
33
+ private _fillStyle;
34
+ private _strokeStyle;
35
+ private _fillStyleTexture;
36
+ private _strokeStyleTexture;
37
+ private readonly _ownedTextures;
23
38
  private _currentPoint;
24
39
  get lineWidth(): number;
25
40
  set lineWidth(lineWidth: number);
41
+ /** Solid stroke color slot: the last solid color assigned to the stroke. */
26
42
  get lineColor(): Color;
43
+ /**
44
+ * Convenience solid-color setter for the stroke. Copies `lineColor` into the
45
+ * color slot and makes it the active {@link strokeStyle}, replacing any
46
+ * gradient stroke style.
47
+ */
27
48
  set lineColor(lineColor: Color);
49
+ /** Solid fill color slot: the last solid color assigned to the fill. */
28
50
  get fillColor(): Color;
51
+ /**
52
+ * Convenience solid-color setter for the fill. Copies `fillColor` into the
53
+ * color slot and makes it the active {@link fillStyle}, replacing any
54
+ * gradient fill style.
55
+ */
29
56
  set fillColor(fillColor: Color);
57
+ /** Active fill style: a solid {@link Color} or a {@link Gradient}. */
58
+ get fillStyle(): Color | Gradient;
59
+ /**
60
+ * Set the fill style. Accepts a solid {@link Color}, a {@link Gradient}
61
+ * (cloned on assignment and rasterized lazily on first fill), or `null` to
62
+ * revert to the solid color held by {@link fillColor}. A {@link Color} value
63
+ * is copied into the {@link fillColor} slot; the most recently assigned style
64
+ * wins.
65
+ */
66
+ set fillStyle(style: Color | Gradient | null);
67
+ /** Active stroke style: a solid {@link Color} or a {@link Gradient}. */
68
+ get strokeStyle(): Color | Gradient;
69
+ /**
70
+ * Set the stroke style. Accepts a solid {@link Color}, a {@link Gradient}
71
+ * (cloned on assignment and rasterized lazily on first stroke), or `null` to
72
+ * revert to the solid color held by {@link lineColor}. A {@link Color} value
73
+ * is copied into the {@link lineColor} slot; the most recently assigned style
74
+ * wins.
75
+ */
76
+ set strokeStyle(style: Color | Gradient | null);
30
77
  get currentPoint(): Vector;
31
78
  getChildAt(index: number): Mesh;
32
79
  addChild(child: RenderNode): this;
@@ -64,8 +111,26 @@ export declare class Graphics extends Container {
64
111
  * `innerRadius` defaults to half of `radius`.
65
112
  */
66
113
  drawStar(centerX: number, centerY: number, points: number, radius: number, innerRadius?: number, rotation?: number): this;
67
- /** Remove all child meshes and reset pen state (position, colors, line width). */
114
+ /** Remove all child meshes and reset pen state (position, fill/stroke styles, line width). */
68
115
  clear(): this;
69
116
  destroy(): void;
70
- private _createMesh;
117
+ /**
118
+ * Resolve an assigned style into the stored paint. A {@link Color} is copied
119
+ * into the solid `colorSlot` (keeping the {@link fillColor} / {@link lineColor}
120
+ * convenience getters in sync) and that slot is returned; `null` reverts to
121
+ * the slot; a {@link Gradient} is cloned so later external mutation cannot
122
+ * change the stored paint.
123
+ */
124
+ private _resolveStyle;
125
+ private _createFillMesh;
126
+ private _createStrokeMesh;
127
+ private _createSolidMesh;
128
+ /**
129
+ * Build a textured mesh whose UVs span the shape's local bounding box, so the
130
+ * gradient texture samples across the filled/stroked geometry. The default
131
+ * white tint and vertex color leave the sampled gradient color unmodulated.
132
+ */
133
+ private _createGradientMesh;
134
+ private _rasterizeGradient;
135
+ private _destroyOwnedTextures;
71
136
  }