@lightningjs/renderer 3.0.0-beta20 → 3.0.0-beta21

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 (152) hide show
  1. package/dist/src/core/CoreNode.d.ts +53 -7
  2. package/dist/src/core/CoreNode.js +175 -65
  3. package/dist/src/core/CoreNode.js.map +1 -1
  4. package/dist/src/core/CoreTextNode.d.ts +1 -1
  5. package/dist/src/core/CoreTextNode.js +3 -5
  6. package/dist/src/core/CoreTextNode.js.map +1 -1
  7. package/dist/src/core/CoreTextureManager.js +1 -1
  8. package/dist/src/core/CoreTextureManager.js.map +1 -1
  9. package/dist/src/core/Stage.d.ts +2 -1
  10. package/dist/src/core/Stage.js +9 -7
  11. package/dist/src/core/Stage.js.map +1 -1
  12. package/dist/src/core/TextureMemoryManager.d.ts +1 -1
  13. package/dist/src/core/TextureMemoryManager.js +3 -3
  14. package/dist/src/core/TextureMemoryManager.js.map +1 -1
  15. package/dist/src/core/animations/Animation.d.ts +21 -0
  16. package/dist/src/core/animations/Animation.js +194 -0
  17. package/dist/src/core/animations/Animation.js.map +1 -0
  18. package/dist/src/core/animations/Playback.d.ts +64 -0
  19. package/dist/src/core/animations/Playback.js +169 -0
  20. package/dist/src/core/animations/Playback.js.map +1 -0
  21. package/dist/src/core/animations/Transition.d.ts +27 -0
  22. package/dist/src/core/animations/Transition.js +52 -0
  23. package/dist/src/core/animations/Transition.js.map +1 -0
  24. package/dist/src/core/animations/utils.d.ts +2 -0
  25. package/dist/src/core/animations/utils.js +136 -0
  26. package/dist/src/core/animations/utils.js.map +1 -0
  27. package/dist/src/core/lib/ImageWorker.d.ts +2 -2
  28. package/dist/src/core/lib/ImageWorker.js +30 -11
  29. package/dist/src/core/lib/ImageWorker.js.map +1 -1
  30. package/dist/src/core/lib/WebGlContextWrapper.js +1 -1
  31. package/dist/src/core/lib/WebGlContextWrapper.js.map +1 -1
  32. package/dist/src/core/lib/utils.d.ts +6 -2
  33. package/dist/src/core/lib/utils.js +21 -21
  34. package/dist/src/core/lib/utils.js.map +1 -1
  35. package/dist/src/core/renderers/CoreRenderer.d.ts +1 -31
  36. package/dist/src/core/renderers/CoreRenderer.js.map +1 -1
  37. package/dist/src/core/renderers/CoreShaderNode.d.ts +4 -0
  38. package/dist/src/core/renderers/CoreShaderNode.js +15 -0
  39. package/dist/src/core/renderers/CoreShaderNode.js.map +1 -1
  40. package/dist/src/core/renderers/canvas/CanvasRenderer.d.ts +3 -3
  41. package/dist/src/core/renderers/canvas/CanvasRenderer.js +38 -33
  42. package/dist/src/core/renderers/canvas/CanvasRenderer.js.map +1 -1
  43. package/dist/src/core/renderers/canvas/CanvasShaderNode.d.ts +1 -2
  44. package/dist/src/core/renderers/canvas/CanvasShaderNode.js.map +1 -1
  45. package/dist/src/core/renderers/webgl/SdfRenderOp.d.ts +33 -0
  46. package/dist/src/core/renderers/webgl/SdfRenderOp.js +97 -0
  47. package/dist/src/core/renderers/webgl/SdfRenderOp.js.map +1 -0
  48. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js +1 -1
  49. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js.map +1 -1
  50. package/dist/src/core/renderers/webgl/WebGlCtxTexture.js +12 -8
  51. package/dist/src/core/renderers/webgl/WebGlCtxTexture.js.map +1 -1
  52. package/dist/src/core/renderers/webgl/WebGlRenderOp.d.ts +2 -3
  53. package/dist/src/core/renderers/webgl/WebGlRenderOp.js +1 -3
  54. package/dist/src/core/renderers/webgl/WebGlRenderOp.js.map +1 -1
  55. package/dist/src/core/renderers/webgl/WebGlRenderer.d.ts +6 -18
  56. package/dist/src/core/renderers/webgl/WebGlRenderer.js +48 -61
  57. package/dist/src/core/renderers/webgl/WebGlRenderer.js.map +1 -1
  58. package/dist/src/core/renderers/webgl/WebGlShaderNode.d.ts +2 -4
  59. package/dist/src/core/renderers/webgl/WebGlShaderNode.js.map +1 -1
  60. package/dist/src/core/renderers/webgl/WebGlShaderProgram.d.ts +3 -4
  61. package/dist/src/core/renderers/webgl/WebGlShaderProgram.js +40 -29
  62. package/dist/src/core/renderers/webgl/WebGlShaderProgram.js.map +1 -1
  63. package/dist/src/core/shaders/canvas/Border.d.ts +8 -2
  64. package/dist/src/core/shaders/canvas/Border.js +62 -23
  65. package/dist/src/core/shaders/canvas/Border.js.map +1 -1
  66. package/dist/src/core/shaders/canvas/HolePunch.js +2 -1
  67. package/dist/src/core/shaders/canvas/HolePunch.js.map +1 -1
  68. package/dist/src/core/shaders/canvas/LinearGradient.js +5 -3
  69. package/dist/src/core/shaders/canvas/LinearGradient.js.map +1 -1
  70. package/dist/src/core/shaders/canvas/RadialGradient.js +7 -5
  71. package/dist/src/core/shaders/canvas/RadialGradient.js.map +1 -1
  72. package/dist/src/core/shaders/canvas/Rounded.js +2 -2
  73. package/dist/src/core/shaders/canvas/Rounded.js.map +1 -1
  74. package/dist/src/core/shaders/canvas/RoundedWithBorder.d.ts +6 -3
  75. package/dist/src/core/shaders/canvas/RoundedWithBorder.js +39 -9
  76. package/dist/src/core/shaders/canvas/RoundedWithBorder.js.map +1 -1
  77. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.d.ts +2 -3
  78. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js +44 -7
  79. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js.map +1 -1
  80. package/dist/src/core/shaders/canvas/RoundedWithShadow.js +5 -4
  81. package/dist/src/core/shaders/canvas/RoundedWithShadow.js.map +1 -1
  82. package/dist/src/core/shaders/canvas/Shadow.js +4 -2
  83. package/dist/src/core/shaders/canvas/Shadow.js.map +1 -1
  84. package/dist/src/core/shaders/canvas/utils/render.d.ts +1 -1
  85. package/dist/src/core/shaders/canvas/utils/render.js +31 -18
  86. package/dist/src/core/shaders/canvas/utils/render.js.map +1 -1
  87. package/dist/src/core/shaders/templates/BorderTemplate.d.ts +10 -0
  88. package/dist/src/core/shaders/templates/BorderTemplate.js +20 -0
  89. package/dist/src/core/shaders/templates/BorderTemplate.js.map +1 -1
  90. package/dist/src/core/shaders/webgl/Border.js +72 -14
  91. package/dist/src/core/shaders/webgl/Border.js.map +1 -1
  92. package/dist/src/core/shaders/webgl/RoundedWithBorder.js +101 -31
  93. package/dist/src/core/shaders/webgl/RoundedWithBorder.js.map +1 -1
  94. package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js +102 -38
  95. package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js.map +1 -1
  96. package/dist/src/core/shaders/webgl/RoundedWithShadow.js +5 -4
  97. package/dist/src/core/shaders/webgl/RoundedWithShadow.js.map +1 -1
  98. package/dist/src/core/shaders/webgl/SdfShadowShader.d.ts +9 -0
  99. package/dist/src/core/shaders/webgl/SdfShadowShader.js +100 -0
  100. package/dist/src/core/shaders/webgl/SdfShadowShader.js.map +1 -0
  101. package/dist/src/core/shaders/webgl/Shadow.js +12 -6
  102. package/dist/src/core/shaders/webgl/Shadow.js.map +1 -1
  103. package/dist/src/core/text-rendering/SdfTextRenderer.js +12 -20
  104. package/dist/src/core/text-rendering/SdfTextRenderer.js.map +1 -1
  105. package/dist/src/core/utils.d.ts +1 -1
  106. package/dist/src/main-api/Inspector.d.ts +1 -1
  107. package/dist/src/main-api/Inspector.js +4 -1
  108. package/dist/src/main-api/Inspector.js.map +1 -1
  109. package/dist/src/main-api/Renderer.d.ts +10 -0
  110. package/dist/src/main-api/Renderer.js +2 -0
  111. package/dist/src/main-api/Renderer.js.map +1 -1
  112. package/dist/tsconfig.dist.tsbuildinfo +1 -1
  113. package/package.json +1 -1
  114. package/src/core/Autosizer.ts +224 -0
  115. package/src/core/CoreNode.test.ts +116 -2
  116. package/src/core/CoreNode.ts +247 -78
  117. package/src/core/CoreTextNode.ts +3 -5
  118. package/src/core/CoreTextureManager.ts +1 -1
  119. package/src/core/Stage.ts +10 -7
  120. package/src/core/TextureMemoryManager.ts +3 -3
  121. package/src/core/lib/ImageWorker.ts +36 -11
  122. package/src/core/lib/WebGlContextWrapper.ts +1 -1
  123. package/src/core/lib/utils.ts +28 -25
  124. package/src/core/renderers/CoreRenderer.ts +1 -32
  125. package/src/core/renderers/CoreShaderNode.ts +20 -0
  126. package/src/core/renderers/canvas/CanvasRenderer.ts +43 -51
  127. package/src/core/renderers/canvas/CanvasShaderNode.ts +1 -2
  128. package/src/core/renderers/webgl/SdfRenderOp.ts +105 -0
  129. package/src/core/renderers/webgl/WebGlCtxTexture.ts +16 -9
  130. package/src/core/renderers/webgl/WebGlRenderer.ts +56 -78
  131. package/src/core/renderers/webgl/WebGlShaderNode.ts +2 -7
  132. package/src/core/renderers/webgl/WebGlShaderProgram.ts +48 -38
  133. package/src/core/shaders/canvas/Border.ts +86 -29
  134. package/src/core/shaders/canvas/HolePunch.ts +2 -1
  135. package/src/core/shaders/canvas/LinearGradient.ts +8 -6
  136. package/src/core/shaders/canvas/RadialGradient.ts +7 -10
  137. package/src/core/shaders/canvas/Rounded.ts +5 -5
  138. package/src/core/shaders/canvas/RoundedWithBorder.ts +68 -18
  139. package/src/core/shaders/canvas/RoundedWithBorderAndShadow.ts +71 -23
  140. package/src/core/shaders/canvas/RoundedWithShadow.ts +6 -5
  141. package/src/core/shaders/canvas/Shadow.ts +7 -5
  142. package/src/core/shaders/canvas/utils/render.ts +45 -36
  143. package/src/core/shaders/templates/BorderTemplate.ts +30 -0
  144. package/src/core/shaders/webgl/Border.ts +72 -15
  145. package/src/core/shaders/webgl/RoundedWithBorder.ts +101 -31
  146. package/src/core/shaders/webgl/RoundedWithBorderAndShadow.ts +102 -38
  147. package/src/core/shaders/webgl/RoundedWithShadow.ts +5 -4
  148. package/src/core/shaders/webgl/Shadow.ts +12 -6
  149. package/src/core/text-rendering/SdfTextRenderer.ts +18 -21
  150. package/src/main-api/Inspector.ts +6 -3
  151. package/src/main-api/Renderer.ts +13 -0
  152. package/src/core/renderers/webgl/WebGlRenderOp.ts +0 -170
@@ -22,9 +22,8 @@ import {
22
22
  CoreRenderer,
23
23
  type BufferInfo,
24
24
  type CoreRendererOptions,
25
- type QuadOptions,
26
25
  } from '../CoreRenderer.js';
27
- import { WebGlRenderOp } from './WebGlRenderOp.js';
26
+ import type { SdfRenderOp } from './SdfRenderOp.js';
28
27
  import type { CoreContextTexture } from '../CoreContextTexture.js';
29
28
  import {
30
29
  createIndexBuffer,
@@ -47,7 +46,7 @@ import { compareRect, getNormalizedRgbaComponents } from '../../lib/utils.js';
47
46
  import { WebGlShaderProgram } from './WebGlShaderProgram.js';
48
47
  import { WebGlContextWrapper } from '../../lib/WebGlContextWrapper.js';
49
48
  import { RenderTexture } from '../../textures/RenderTexture.js';
50
- import { CoreNodeRenderState, type CoreNode } from '../../CoreNode.js';
49
+ import { CoreNodeRenderState, CoreNode } from '../../CoreNode.js';
51
50
  import { WebGlCtxRenderTexture } from './WebGlCtxRenderTexture.js';
52
51
  import { Default } from '../../shaders/webgl/Default.js';
53
52
  import type { WebGlShaderType } from './WebGlShaderNode.js';
@@ -61,6 +60,8 @@ interface CoreWebGlSystem {
61
60
  extensions: CoreWebGlExtensions;
62
61
  }
63
62
 
63
+ export type WebGlRenderOp = CoreNode | SdfRenderOp;
64
+
64
65
  export class WebGlRenderer extends CoreRenderer {
65
66
  //// WebGL Native Context and Data
66
67
  glw: WebGlContextWrapper;
@@ -190,7 +191,9 @@ export class WebGlRenderer extends CoreRenderer {
190
191
  this.curRenderOp = null;
191
192
  this.renderOps.length = 0;
192
193
  glw.setScissorTest(false);
193
- glw.clear();
194
+ if (this.stage.options.enableClear !== false) {
195
+ glw.clear();
196
+ }
194
197
  }
195
198
 
196
199
  createShaderProgram(
@@ -253,30 +256,36 @@ export class WebGlRenderer extends CoreRenderer {
253
256
  * Finally, it calculates the vertices for the quad, taking into account any transformations, and adds them to the quad buffer.
254
257
  * The function updates the length and number of quads in the current render operation, and updates the current buffer index.
255
258
  */
256
- addQuad(params: QuadOptions) {
259
+ addQuad(node: CoreNode) {
257
260
  const f = this.fQuadBuffer;
258
261
  const u = this.uiQuadBuffer;
259
262
  let i = this.curBufferIdx;
260
263
 
261
- const reuse = this.reuseRenderOp(params);
264
+ const reuse = this.reuseRenderOp(node);
262
265
  if (reuse === false) {
263
- this.newRenderOp(params, i);
266
+ this.newRenderOp(node, i);
264
267
  }
265
268
 
266
- let tx = params.texture!;
269
+ let tx = (node.props.texture || this.stage.defaultTexture) as Texture;
267
270
  if (tx.type === TextureType.subTexture) {
268
271
  tx = (tx as SubTexture).parentTexture;
269
272
  }
270
273
 
271
- const tidx = this.addTexture(tx.ctxTexture as WebGlCtxTexture, i);
274
+ const texture = tx.ctxTexture as WebGlCtxTexture;
275
+ let tidx = this.curRenderOp!.addTexture(texture);
272
276
 
273
- const rc = params.renderCoords!;
274
- const tc = params.textureCoords!;
277
+ if (tidx === 0xffffffff) {
278
+ this.newRenderOp(node, i);
279
+ tidx = this.curRenderOp!.addTexture(texture);
280
+ }
275
281
 
276
- const cTl = params.colorTl;
277
- const cTr = params.colorTr;
278
- const cBl = params.colorBl;
279
- const cBr = params.colorBr;
282
+ const rc = node.renderCoords!;
283
+ const tc = node.textureCoords || this.defaultTextureCoords;
284
+
285
+ const cTl = node.premultipliedColorTl;
286
+ const cTr = node.premultipliedColorTr;
287
+ const cBl = node.premultipliedColorBl;
288
+ const cBr = node.premultipliedColorBr;
280
289
 
281
290
  // Upper-Left
282
291
  f[i] = rc.x1;
@@ -329,104 +338,73 @@ export class WebGlRenderer extends CoreRenderer {
329
338
  * @param shader
330
339
  * @param bufferIdx
331
340
  */
332
- private newRenderOp(quad: QuadOptions | WebGlRenderOp, bufferIdx: number) {
333
- const curRenderOp = new WebGlRenderOp(this, quad, bufferIdx);
341
+ private newRenderOp(node: CoreNode, bufferIdx: number) {
342
+ const curRenderOp = node;
343
+ curRenderOp.renderOpBufferIdx = bufferIdx;
344
+ curRenderOp.numQuads = 0;
345
+ curRenderOp.renderOpTextures.length = 0;
346
+
334
347
  this.curRenderOp = curRenderOp;
335
348
  this.renderOps.push(curRenderOp);
336
349
  }
337
350
 
338
- /**
339
- * Add a texture to the current RenderOp. If the texture cannot be added to the
340
- * current RenderOp, a new RenderOp will be created and the texture will be added
341
- * to that one.
342
- *
343
- * If the texture cannot be added to the new RenderOp, an error will be thrown.
344
- *
345
- * @param texture
346
- * @param bufferIdx
347
- * @param recursive
348
- * @returns Assigned Texture Index of the texture in the render op
349
- */
350
- private addTexture(
351
- texture: WebGlCtxTexture,
352
- bufferIdx: number,
353
- recursive?: boolean,
354
- ): number {
355
- const textureIdx = this.curRenderOp!.addTexture(texture);
356
- // TODO: Refactor to be more DRY
357
- if (textureIdx === 0xffffffff) {
358
- if (recursive) {
359
- throw new Error('Unable to add texture to render op');
360
- }
361
- this.newRenderOp(this.curRenderOp!, bufferIdx);
362
- return this.addTexture(texture, bufferIdx, true);
363
- }
364
- return textureIdx;
365
- }
366
-
367
351
  /**
368
352
  * Test if the current Render operation can be reused for the specified parameters.
369
353
  * @param params
370
354
  * @returns
371
355
  */
372
- reuseRenderOp(params: QuadOptions): boolean {
373
- // Switching shader program will require a new render operation
374
- if (
375
- this.curRenderOp?.shader.shaderKey !==
376
- (params.shader as WebGlShaderNode).shaderKey
377
- ) {
356
+ reuseRenderOp(node: CoreNode): boolean {
357
+ const curRenderOp = this.curRenderOp;
358
+ if (curRenderOp === null) {
359
+ return false;
360
+ }
361
+
362
+ const shader = node.props.shader as WebGlShaderNode;
363
+ const curShader = curRenderOp.shader as WebGlShaderNode;
364
+
365
+ if (curShader?.shaderKey !== shader?.shaderKey) {
378
366
  return false;
379
367
  }
380
368
 
381
369
  // Switching clipping rect will require a new render operation
382
- if (
383
- compareRect(this.curRenderOp.clippingRect, params.clippingRect) === false
384
- ) {
370
+ if (compareRect(curRenderOp.clippingRect, node.clippingRect) === false) {
385
371
  return false;
386
372
  }
387
373
 
388
374
  // Force new render operation if rendering to texture is different
375
+ const curRtt = curRenderOp.rtt;
389
376
  if (
390
- this.curRenderOp.parentHasRenderTexture !==
391
- params.parentHasRenderTexture ||
392
- this.curRenderOp.rtt !== params.rtt
377
+ curRenderOp.parentHasRenderTexture !== node.parentHasRenderTexture ||
378
+ curRtt !== (node.props.rtt === true)
393
379
  ) {
394
380
  return false;
395
381
  }
396
382
 
397
383
  if (
398
- params.parentHasRenderTexture === true &&
399
- this.curRenderOp.framebufferDimensions !== null &&
400
- params.framebufferDimensions !== null
384
+ node.parentHasRenderTexture === true &&
385
+ node.parentFramebufferDimensions !== null
401
386
  ) {
387
+ const curFbDims = curRenderOp.isCoreNode
388
+ ? curRenderOp.parentFramebufferDimensions
389
+ : curRenderOp.framebufferDimensions;
402
390
  if (
403
- this.curRenderOp.framebufferDimensions.w !==
404
- params.framebufferDimensions.w ||
405
- this.curRenderOp.framebufferDimensions.h !==
406
- params.framebufferDimensions.h
391
+ curFbDims === null ||
392
+ curFbDims.w !== node.parentFramebufferDimensions.w ||
393
+ curFbDims.h !== node.parentFramebufferDimensions.h
407
394
  ) {
408
395
  return false;
409
396
  }
410
397
  }
411
398
 
412
- if (
413
- this.curRenderOp.shader.shaderKey === 'default' &&
414
- params.shader?.shaderKey === 'default'
415
- ) {
399
+ if (curShader?.shaderKey === 'default' && shader?.shaderKey === 'default') {
416
400
  return true;
417
401
  }
418
402
 
419
403
  // Check if the shader can batch the shader properties
420
- if (
421
- this.curRenderOp.shader.program.reuseRenderOp(
422
- params,
423
- this.curRenderOp,
424
- ) === false
425
- ) {
404
+ if (curShader?.program.reuseRenderOp(node, curRenderOp) === false) {
426
405
  return false;
427
406
  }
428
407
 
429
- // Render operation can be reused
430
408
  return true;
431
409
  }
432
410
 
@@ -454,9 +432,9 @@ export class WebGlRenderer extends CoreRenderer {
454
432
  glw.arrayBufferData(buffer, arr, glw.STATIC_DRAW);
455
433
 
456
434
  for (let i = 0, length = this.renderOps.length; i < length; i++) {
457
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
458
- this.renderOps[i]!.draw();
435
+ this.renderOps[i]!.draw(this);
459
436
  }
437
+
460
438
  this.quadBufferUsage = this.curBufferIdx * arr.BYTES_PER_ELEMENT;
461
439
 
462
440
  // Calculate the size of each quad in bytes (4 vertices per quad) times the size of each vertex in bytes
@@ -2,7 +2,6 @@ import type { CoreNode } from '../../CoreNode.js';
2
2
  import { getNormalizedRgbaComponents } from '../../lib/utils.js';
3
3
  import type { WebGlContextWrapper } from '../../lib/WebGlContextWrapper.js';
4
4
  import type { Stage } from '../../Stage.js';
5
- import type { QuadOptions } from '../CoreRenderer.js';
6
5
  import { CoreShaderNode, type CoreShaderType } from '../CoreShaderNode.js';
7
6
  import type {
8
7
  UniformCollection,
@@ -10,8 +9,7 @@ import type {
10
9
  Vec3,
11
10
  Vec4,
12
11
  } from './internal/ShaderUtils.js';
13
- import type { WebGlRenderer } from './WebGlRenderer.js';
14
- import type { WebGlRenderOp } from './WebGlRenderOp.js';
12
+ import type { WebGlRenderer, WebGlRenderOp } from './WebGlRenderer.js';
15
13
  import type { WebGlShaderProgram } from './WebGlShaderProgram.js';
16
14
 
17
15
  export type ShaderSource<T> =
@@ -47,10 +45,7 @@ export type WebGlShaderType<T extends object = Record<string, unknown>> =
47
45
  * This function is used to check if the shader can be reused based on quad info
48
46
  * @param props
49
47
  */
50
- canBatch?: (
51
- incomingQuad: QuadOptions,
52
- currentRenderOp: WebGlRenderOp,
53
- ) => boolean;
48
+ canBatch?: (node: CoreNode, currentRenderOp: WebGlRenderOp) => boolean;
54
49
  /**
55
50
  * extensions required for specific shader?
56
51
  */
@@ -18,12 +18,11 @@
18
18
  */
19
19
  import type { WebGlContextWrapper } from '../../lib/WebGlContextWrapper.js';
20
20
  import { Default } from '../../shaders/webgl/Default.js';
21
- import type { QuadOptions } from '../CoreRenderer.js';
22
21
  import type { CoreShaderProgram } from '../CoreShaderProgram.js';
23
22
  import type { WebGlCtxTexture } from './WebGlCtxTexture.js';
24
- import type { WebGlRenderOp } from './WebGlRenderOp.js';
25
- import type { WebGlRenderer } from './WebGlRenderer.js';
23
+ import type { WebGlRenderer, WebGlRenderOp } from './WebGlRenderer.js';
26
24
  import type { WebGlShaderType } from './WebGlShaderNode.js';
25
+ import { WebGlShaderNode } from './WebGlShaderNode.js';
27
26
  import type { BufferCollection } from './internal/BufferCollection.js';
28
27
  import {
29
28
  createProgram,
@@ -33,6 +32,7 @@ import {
33
32
  type UniformSet3Params,
34
33
  type UniformSet4Params,
35
34
  } from './internal/ShaderUtils.js';
35
+ import { CoreNode } from '../../CoreNode.js';
36
36
 
37
37
  export class WebGlShaderProgram implements CoreShaderProgram {
38
38
  protected program: WebGLProgram | null;
@@ -146,43 +146,43 @@ export class WebGlShaderProgram implements CoreShaderProgram {
146
146
  }
147
147
  }
148
148
 
149
- reuseRenderOp(
150
- incomingQuad: QuadOptions,
151
- currentRenderOp: WebGlRenderOp,
152
- ): boolean {
149
+ reuseRenderOp(node: CoreNode, currentRenderOp: WebGlRenderOp): boolean {
153
150
  if (this.lifecycle.canBatch !== undefined) {
154
- return this.lifecycle.canBatch(incomingQuad, currentRenderOp);
151
+ return this.lifecycle.canBatch(node, currentRenderOp);
155
152
  }
156
153
 
154
+ const { time, worldAlpha, w, h } = node;
155
+
157
156
  if (this.useTimeValue === true) {
158
- if (incomingQuad.time !== currentRenderOp.time) {
157
+ if (time !== currentRenderOp.time) {
159
158
  return false;
160
159
  }
161
160
  }
162
161
 
163
162
  if (this.useSystemAlpha === true) {
164
- if (incomingQuad.alpha !== currentRenderOp.alpha) {
163
+ if (worldAlpha !== currentRenderOp.worldAlpha) {
165
164
  return false;
166
165
  }
167
166
  }
168
167
 
169
168
  if (this.useSystemDimensions === true) {
170
- if (
171
- incomingQuad.width !== currentRenderOp.width ||
172
- incomingQuad.height !== currentRenderOp.height
173
- ) {
169
+ if (w !== currentRenderOp.w || h !== currentRenderOp.h) {
174
170
  return false;
175
171
  }
176
172
  }
173
+
177
174
  let shaderPropsA: Record<string, unknown> | undefined = undefined;
178
175
  let shaderPropsB: Record<string, unknown> | undefined = undefined;
179
176
 
180
- if (incomingQuad.shader !== null) {
181
- shaderPropsA = incomingQuad.shader.resolvedProps;
177
+ const shader = node.props.shader;
178
+
179
+ if (shader !== null) {
180
+ shaderPropsA = (shader as WebGlShaderNode).resolvedProps;
182
181
  }
183
182
 
184
- if (currentRenderOp.shader !== null) {
185
- shaderPropsB = currentRenderOp.shader.resolvedProps;
183
+ const opShader = currentRenderOp.shader;
184
+ if (opShader !== null) {
185
+ shaderPropsB = (opShader as WebGlShaderNode).resolvedProps;
186
186
  }
187
187
 
188
188
  if (
@@ -204,10 +204,15 @@ export class WebGlShaderProgram implements CoreShaderProgram {
204
204
  }
205
205
 
206
206
  bindRenderOp(renderOp: WebGlRenderOp) {
207
- this.bindBufferCollection(renderOp.buffers);
208
- this.bindTextures(renderOp.textures);
207
+ const isCoreNode = renderOp.isCoreNode;
209
208
 
210
- const { parentHasRenderTexture } = renderOp;
209
+ this.bindTextures(renderOp.renderOpTextures);
210
+ this.bindBufferCollection(renderOp.quadBufferCollection);
211
+
212
+ const parentHasRenderTexture = renderOp.parentHasRenderTexture;
213
+ const framebufferDimensions = isCoreNode
214
+ ? renderOp.parentFramebufferDimensions
215
+ : renderOp.framebufferDimensions;
211
216
 
212
217
  // Skip if the parent and current operation both have render textures
213
218
  if (renderOp.rtt === true && parentHasRenderTexture === true) {
@@ -216,8 +221,8 @@ export class WebGlShaderProgram implements CoreShaderProgram {
216
221
 
217
222
  // Bind render texture framebuffer dimensions as resolution
218
223
  // if the parent has a render texture
219
- if (parentHasRenderTexture === true) {
220
- const { w, h } = renderOp.framebufferDimensions!;
224
+ if (parentHasRenderTexture === true && framebufferDimensions) {
225
+ const { w, h } = framebufferDimensions;
221
226
  // Force pixel ratio to 1.0 for render textures since they are always 1:1
222
227
  // the final render texture will be rendered to the screen with the correct pixel ratio
223
228
  this.glw.uniform1f('u_pixelRatio', 1.0);
@@ -225,7 +230,8 @@ export class WebGlShaderProgram implements CoreShaderProgram {
225
230
  // Set resolution to the framebuffer dimensions
226
231
  this.glw.uniform2f('u_resolution', w, h);
227
232
  } else {
228
- this.glw.uniform1f('u_pixelRatio', renderOp.renderer.stage.pixelRatio);
233
+ this.glw.uniform1f('u_pixelRatio', renderOp.stage.pixelRatio);
234
+
229
235
  this.glw.uniform2f(
230
236
  'u_resolution',
231
237
  this.glw.canvas.width,
@@ -234,42 +240,46 @@ export class WebGlShaderProgram implements CoreShaderProgram {
234
240
  }
235
241
 
236
242
  if (this.useTimeValue === true) {
237
- this.glw.uniform1f('u_time', renderOp.time as number);
243
+ this.glw.uniform1f('u_time', renderOp.time);
238
244
  }
239
245
 
240
246
  if (this.useSystemAlpha === true) {
241
- this.glw.uniform1f('u_alpha', renderOp.alpha);
247
+ this.glw.uniform1f('u_alpha', renderOp.worldAlpha);
242
248
  }
243
249
 
244
250
  if (this.useSystemDimensions === true) {
245
- this.glw.uniform2f('u_dimensions', renderOp.width, renderOp.height);
251
+ this.glw.uniform2f('u_dimensions', renderOp.w, renderOp.h);
246
252
  }
247
253
 
248
254
  /**temporary fix to make sdf texts work */
249
- if (renderOp.sdfShaderProps !== undefined) {
250
- (renderOp.shader.shaderType as WebGlShaderType).onSdfBind?.call(
255
+ if (isCoreNode === false && renderOp.sdfShaderProps !== undefined) {
256
+ const opShader = renderOp.shader; // SdfRenderOp has .shader
257
+ (opShader.shaderType as WebGlShaderType).onSdfBind?.call(
251
258
  this.glw,
252
259
  renderOp.sdfShaderProps,
253
260
  );
254
261
  return;
255
262
  }
256
263
 
257
- if (renderOp.shader.props !== undefined) {
264
+ const shader = renderOp.shader as WebGlShaderNode;
265
+ if (shader.props !== undefined) {
258
266
  /**
259
267
  * loop over all precalculated uniform types
260
268
  */
261
- for (const key in renderOp.shader.uniforms.single) {
262
- const { method, value } = renderOp.shader.uniforms.single[key]!;
269
+ const uniforms = shader.uniforms;
270
+
271
+ for (const key in uniforms.single) {
272
+ const { method, value } = uniforms.single[key]!;
263
273
  this.glw[method as keyof UniformSet1Param](key, value as never);
264
274
  }
265
275
 
266
- for (const key in renderOp.shader.uniforms.vec2) {
267
- const { method, value } = renderOp.shader.uniforms.vec2[key]!;
276
+ for (const key in uniforms.vec2) {
277
+ const { method, value } = uniforms.vec2[key]!;
268
278
  this.glw[method as keyof UniformSet2Params](key, value[0], value[1]);
269
279
  }
270
280
 
271
- for (const key in renderOp.shader.uniforms.vec3) {
272
- const { method, value } = renderOp.shader.uniforms.vec3[key]!;
281
+ for (const key in uniforms.vec3) {
282
+ const { method, value } = uniforms.vec3[key]!;
273
283
  this.glw[method as keyof UniformSet3Params](
274
284
  key,
275
285
  value[0],
@@ -278,8 +288,8 @@ export class WebGlShaderProgram implements CoreShaderProgram {
278
288
  );
279
289
  }
280
290
 
281
- for (const key in renderOp.shader.uniforms.vec4) {
282
- const { method, value } = renderOp.shader.uniforms.vec4[key]!;
291
+ for (const key in uniforms.vec4) {
292
+ const { method, value } = uniforms.vec4[key]!;
283
293
  this.glw[method as keyof UniformSet4Params](
284
294
  key,
285
295
  value[0],
@@ -23,12 +23,18 @@ import {
23
23
  BorderTemplate,
24
24
  type BorderProps,
25
25
  } from '../templates/BorderTemplate.js';
26
- import { strokeLine } from './utils/render.js';
27
26
 
28
27
  export interface ComputedBorderValues {
29
28
  borderColor: string;
30
29
  borderAsym: boolean;
31
- borderRadius: Vec4;
30
+ innerX: number;
31
+ innerY: number;
32
+ innerW: number;
33
+ innerH: number;
34
+ outerX: number;
35
+ outerY: number;
36
+ outerW: number;
37
+ outerH: number;
32
38
  }
33
39
 
34
40
  export const Border: CanvasShaderType<BorderProps, ComputedBorderValues> = {
@@ -36,40 +42,91 @@ export const Border: CanvasShaderType<BorderProps, ComputedBorderValues> = {
36
42
  update() {
37
43
  this.computed.borderColor = formatRgba(parseColorRgba(this.props!.color));
38
44
  this.computed.borderAsym = !valuesAreEqual(this.props!.w as number[]);
39
- },
40
- render(ctx, quad, renderContext) {
41
- renderContext();
42
- ctx.strokeStyle = this.computed.borderColor!;
43
- if (this.computed.borderAsym === false && this.props!.w[0] > 0) {
44
- const bWidth = this.props!.w[0];
45
- const bHalfWidth = bWidth * 0.5;
46
- ctx.lineWidth = bWidth;
47
- ctx.beginPath();
48
- ctx.strokeRect(
49
- quad.tx + bHalfWidth,
50
- quad.ty + bHalfWidth,
51
- quad.width - bWidth,
52
- quad.height - bWidth,
53
- );
45
+ const borderAlign = this.props!.align as number;
46
+ const borderGap = this.props!.gap as number;
47
+
48
+ const borderW = this.props!.w as Vec4;
49
+
50
+ if (this.computed.borderAsym === false) {
51
+ const bWidth = borderW[0] * 0.5;
52
+ //inside
53
+ const baseline = bWidth - borderW[0] * borderAlign - borderGap;
54
+ this.computed.outerX = baseline;
55
+ this.computed.outerY = baseline;
56
+
57
+ this.computed.outerW = -baseline * 2;
58
+ this.computed.outerH = -baseline * 2;
54
59
  return;
55
60
  }
56
61
 
57
- const { 0: t, 1: r, 2: b, 3: l } = this.props!.w as Vec4;
58
- if (t > 0) {
59
- const y = quad.ty + t * 0.5;
60
- strokeLine(ctx, quad.tx, y, quad.tx + quad.width, y, t);
61
- }
62
+ // Calculate outer and inner rectangle dimensions
63
+ const [t, r, b, l] = this.props!.w as Vec4;
64
+
65
+ const outerX = (this.computed.outerX = -l * borderAlign - borderGap);
66
+ const outerY = (this.computed.outerY = -t * borderAlign - borderGap);
67
+ let outerW = 0;
68
+ let outerH = 0;
69
+
62
70
  if (r > 0) {
63
- const x = quad.tx + quad.width - r * 0.5;
64
- strokeLine(ctx, x, quad.ty, x, quad.ty + quad.height, r);
71
+ outerW += r * borderAlign + borderGap;
65
72
  }
73
+ if (l > 0) {
74
+ outerW += l * borderAlign + borderGap;
75
+ }
76
+
66
77
  if (b > 0) {
67
- const y = quad.ty + quad.height - b * 0.5;
68
- strokeLine(ctx, quad.tx, y, quad.tx + quad.width, y, b);
78
+ outerH += b * borderAlign + borderGap;
69
79
  }
70
- if (l > 0) {
71
- const x = quad.tx + l * 0.5;
72
- strokeLine(ctx, x, quad.ty, x, quad.ty + quad.height, l);
80
+ if (t > 0) {
81
+ outerH += t * borderAlign + borderGap;
82
+ }
83
+
84
+ this.computed.outerW = outerW;
85
+ this.computed.outerH = outerH;
86
+
87
+ this.computed.innerX = outerX + l;
88
+ this.computed.innerY = outerY + t;
89
+ this.computed.innerW = outerW - l - r;
90
+ this.computed.innerH = outerH - t - b;
91
+ },
92
+ render(ctx, node, renderContext) {
93
+ renderContext();
94
+ const computed = this.computed as ComputedBorderValues;
95
+ const { tx, ty } = node.globalTransform!;
96
+ const { w, h } = node.props;
97
+ ctx.strokeStyle = computed.borderColor!;
98
+ if (computed.borderAsym === false && this.props!.w[0] > 0) {
99
+ ctx.lineWidth = this.props!.w[0];
100
+ ctx.beginPath();
101
+ ctx.strokeRect(
102
+ tx + computed.outerX,
103
+ ty + computed.outerY,
104
+ w + computed.outerW,
105
+ h + computed.outerH,
106
+ );
107
+ return;
73
108
  }
109
+
110
+ // Calculate outer rectangle (including border)
111
+ const outerX = tx + computed.outerX;
112
+ const outerY = ty + computed.outerY;
113
+ const outerW = w + computed.outerW;
114
+ const outerH = h + computed.outerH;
115
+
116
+ // Calculate inner rectangle (excluding border)
117
+ const innerX = tx + computed.innerX;
118
+ const innerY = ty + computed.innerY;
119
+ const innerW = w + computed.innerW;
120
+ const innerH = h + computed.innerH;
121
+
122
+ // Use clip to subtract inner from outer
123
+ ctx.save();
124
+ ctx.beginPath();
125
+ ctx.rect(outerX, outerY, outerW, outerH);
126
+ ctx.rect(innerX, innerY, innerW, innerH);
127
+ ctx.clip('evenodd');
128
+ ctx.fillStyle = this.computed.borderColor!;
129
+ ctx.fillRect(outerX, outerY, outerW, outerH);
130
+ ctx.restore();
74
131
  },
75
132
  };
@@ -44,8 +44,9 @@ export const HolePunch: CanvasShaderType<
44
44
  ctx.save();
45
45
  renderContext();
46
46
  const { x, y, w, h } = this.props!;
47
+ const gt = quad.globalTransform!;
47
48
  ctx.beginPath();
48
- roundRect(ctx, quad.tx + x, quad.ty + y, w, h, this.computed.radius!);
49
+ roundRect(ctx, gt.tx + x, gt.ty + y, w, h, this.computed.radius!);
49
50
  ctx.closePath();
50
51
  ctx.fillStyle = 'black';
51
52
  ctx.globalCompositeOperation = 'destination-out';
@@ -51,14 +51,16 @@ export const LinearGradient: CanvasShaderType<
51
51
  colors: this.props!.colors.map((value) => this.toColorString(value)),
52
52
  };
53
53
  },
54
- render(ctx, quad, renderContext) {
54
+ render(ctx, node, renderContext) {
55
55
  renderContext();
56
56
  const computed = this.computed as ComputedLinearGradientValues;
57
+ const { tx, ty } = node.globalTransform!;
58
+ const { w, h } = node.props;
57
59
  const gradient = ctx.createLinearGradient(
58
- quad.tx + computed.x0,
59
- quad.ty + computed.y0,
60
- quad.tx + computed.x1,
61
- quad.ty + computed.y1,
60
+ tx + computed.x0,
61
+ ty + computed.y0,
62
+ tx + computed.x1,
63
+ ty + computed.y1,
62
64
  );
63
65
  const colors = computed.colors;
64
66
  const stops = this.props!.stops;
@@ -66,6 +68,6 @@ export const LinearGradient: CanvasShaderType<
66
68
  gradient.addColorStop(stops[i]!, colors[i]!);
67
69
  }
68
70
  ctx.fillStyle = gradient;
69
- ctx.fillRect(quad.tx, quad.ty, quad.width, quad.height);
71
+ ctx.fillRect(tx, ty, w, h);
70
72
  },
71
73
  };
@@ -56,12 +56,14 @@ export const RadialGradient: CanvasShaderType<
56
56
  colors: props.colors.map((value) => this.toColorString(value)),
57
57
  };
58
58
  },
59
- render(ctx, quad, renderContext) {
59
+ render(ctx, node, renderContext) {
60
60
  renderContext();
61
61
  const { scaleX, scaleY, pivotX, pivotY, colors, size } = this
62
62
  .computed as ComputedRadialGradientValues;
63
- let x = quad.tx + pivotX;
64
- let y = quad.ty + pivotY;
63
+ const { tx, ty } = node.globalTransform!;
64
+ const { w, h } = node.props;
65
+ let x = tx + pivotX;
66
+ let y = ty + pivotY;
65
67
  const stops = this.props!.stops;
66
68
 
67
69
  if (scaleX === scaleY) {
@@ -72,7 +74,7 @@ export const RadialGradient: CanvasShaderType<
72
74
  }
73
75
 
74
76
  ctx.fillStyle = gradient;
75
- ctx.fillRect(quad.tx, quad.ty, quad.width, quad.height);
77
+ ctx.fillRect(tx, ty, w, h);
76
78
  return;
77
79
  }
78
80
 
@@ -87,12 +89,7 @@ export const RadialGradient: CanvasShaderType<
87
89
  }
88
90
 
89
91
  ctx.fillStyle = gradient;
90
- ctx.fillRect(
91
- quad.tx / scaleX,
92
- quad.ty / scaleY,
93
- quad.width / scaleX,
94
- quad.height / scaleY,
95
- );
92
+ ctx.fillRect(tx / scaleX, ty / scaleY, w / scaleX, h / scaleY);
96
93
 
97
94
  ctx.restore();
98
95
  },