@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.
- package/dist/src/core/CoreNode.d.ts +53 -7
- package/dist/src/core/CoreNode.js +175 -65
- package/dist/src/core/CoreNode.js.map +1 -1
- package/dist/src/core/CoreTextNode.d.ts +1 -1
- package/dist/src/core/CoreTextNode.js +3 -5
- package/dist/src/core/CoreTextNode.js.map +1 -1
- package/dist/src/core/CoreTextureManager.js +1 -1
- package/dist/src/core/CoreTextureManager.js.map +1 -1
- package/dist/src/core/Stage.d.ts +2 -1
- package/dist/src/core/Stage.js +9 -7
- package/dist/src/core/Stage.js.map +1 -1
- package/dist/src/core/TextureMemoryManager.d.ts +1 -1
- package/dist/src/core/TextureMemoryManager.js +3 -3
- package/dist/src/core/TextureMemoryManager.js.map +1 -1
- package/dist/src/core/animations/Animation.d.ts +21 -0
- package/dist/src/core/animations/Animation.js +194 -0
- package/dist/src/core/animations/Animation.js.map +1 -0
- package/dist/src/core/animations/Playback.d.ts +64 -0
- package/dist/src/core/animations/Playback.js +169 -0
- package/dist/src/core/animations/Playback.js.map +1 -0
- package/dist/src/core/animations/Transition.d.ts +27 -0
- package/dist/src/core/animations/Transition.js +52 -0
- package/dist/src/core/animations/Transition.js.map +1 -0
- package/dist/src/core/animations/utils.d.ts +2 -0
- package/dist/src/core/animations/utils.js +136 -0
- package/dist/src/core/animations/utils.js.map +1 -0
- package/dist/src/core/lib/ImageWorker.d.ts +2 -2
- package/dist/src/core/lib/ImageWorker.js +30 -11
- package/dist/src/core/lib/ImageWorker.js.map +1 -1
- package/dist/src/core/lib/WebGlContextWrapper.js +1 -1
- package/dist/src/core/lib/WebGlContextWrapper.js.map +1 -1
- package/dist/src/core/lib/utils.d.ts +6 -2
- package/dist/src/core/lib/utils.js +21 -21
- package/dist/src/core/lib/utils.js.map +1 -1
- package/dist/src/core/renderers/CoreRenderer.d.ts +1 -31
- package/dist/src/core/renderers/CoreRenderer.js.map +1 -1
- package/dist/src/core/renderers/CoreShaderNode.d.ts +4 -0
- package/dist/src/core/renderers/CoreShaderNode.js +15 -0
- package/dist/src/core/renderers/CoreShaderNode.js.map +1 -1
- package/dist/src/core/renderers/canvas/CanvasRenderer.d.ts +3 -3
- package/dist/src/core/renderers/canvas/CanvasRenderer.js +38 -33
- package/dist/src/core/renderers/canvas/CanvasRenderer.js.map +1 -1
- package/dist/src/core/renderers/canvas/CanvasShaderNode.d.ts +1 -2
- package/dist/src/core/renderers/canvas/CanvasShaderNode.js.map +1 -1
- package/dist/src/core/renderers/webgl/SdfRenderOp.d.ts +33 -0
- package/dist/src/core/renderers/webgl/SdfRenderOp.js +97 -0
- package/dist/src/core/renderers/webgl/SdfRenderOp.js.map +1 -0
- package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js +1 -1
- package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlCtxTexture.js +12 -8
- package/dist/src/core/renderers/webgl/WebGlCtxTexture.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlRenderOp.d.ts +2 -3
- package/dist/src/core/renderers/webgl/WebGlRenderOp.js +1 -3
- package/dist/src/core/renderers/webgl/WebGlRenderOp.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlRenderer.d.ts +6 -18
- package/dist/src/core/renderers/webgl/WebGlRenderer.js +48 -61
- package/dist/src/core/renderers/webgl/WebGlRenderer.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlShaderNode.d.ts +2 -4
- package/dist/src/core/renderers/webgl/WebGlShaderNode.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlShaderProgram.d.ts +3 -4
- package/dist/src/core/renderers/webgl/WebGlShaderProgram.js +40 -29
- package/dist/src/core/renderers/webgl/WebGlShaderProgram.js.map +1 -1
- package/dist/src/core/shaders/canvas/Border.d.ts +8 -2
- package/dist/src/core/shaders/canvas/Border.js +62 -23
- package/dist/src/core/shaders/canvas/Border.js.map +1 -1
- package/dist/src/core/shaders/canvas/HolePunch.js +2 -1
- package/dist/src/core/shaders/canvas/HolePunch.js.map +1 -1
- package/dist/src/core/shaders/canvas/LinearGradient.js +5 -3
- package/dist/src/core/shaders/canvas/LinearGradient.js.map +1 -1
- package/dist/src/core/shaders/canvas/RadialGradient.js +7 -5
- package/dist/src/core/shaders/canvas/RadialGradient.js.map +1 -1
- package/dist/src/core/shaders/canvas/Rounded.js +2 -2
- package/dist/src/core/shaders/canvas/Rounded.js.map +1 -1
- package/dist/src/core/shaders/canvas/RoundedWithBorder.d.ts +6 -3
- package/dist/src/core/shaders/canvas/RoundedWithBorder.js +39 -9
- package/dist/src/core/shaders/canvas/RoundedWithBorder.js.map +1 -1
- package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.d.ts +2 -3
- package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js +44 -7
- package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js.map +1 -1
- package/dist/src/core/shaders/canvas/RoundedWithShadow.js +5 -4
- package/dist/src/core/shaders/canvas/RoundedWithShadow.js.map +1 -1
- package/dist/src/core/shaders/canvas/Shadow.js +4 -2
- package/dist/src/core/shaders/canvas/Shadow.js.map +1 -1
- package/dist/src/core/shaders/canvas/utils/render.d.ts +1 -1
- package/dist/src/core/shaders/canvas/utils/render.js +31 -18
- package/dist/src/core/shaders/canvas/utils/render.js.map +1 -1
- package/dist/src/core/shaders/templates/BorderTemplate.d.ts +10 -0
- package/dist/src/core/shaders/templates/BorderTemplate.js +20 -0
- package/dist/src/core/shaders/templates/BorderTemplate.js.map +1 -1
- package/dist/src/core/shaders/webgl/Border.js +72 -14
- package/dist/src/core/shaders/webgl/Border.js.map +1 -1
- package/dist/src/core/shaders/webgl/RoundedWithBorder.js +101 -31
- package/dist/src/core/shaders/webgl/RoundedWithBorder.js.map +1 -1
- package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js +102 -38
- package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js.map +1 -1
- package/dist/src/core/shaders/webgl/RoundedWithShadow.js +5 -4
- package/dist/src/core/shaders/webgl/RoundedWithShadow.js.map +1 -1
- package/dist/src/core/shaders/webgl/SdfShadowShader.d.ts +9 -0
- package/dist/src/core/shaders/webgl/SdfShadowShader.js +100 -0
- package/dist/src/core/shaders/webgl/SdfShadowShader.js.map +1 -0
- package/dist/src/core/shaders/webgl/Shadow.js +12 -6
- package/dist/src/core/shaders/webgl/Shadow.js.map +1 -1
- package/dist/src/core/text-rendering/SdfTextRenderer.js +12 -20
- package/dist/src/core/text-rendering/SdfTextRenderer.js.map +1 -1
- package/dist/src/core/utils.d.ts +1 -1
- package/dist/src/main-api/Inspector.d.ts +1 -1
- package/dist/src/main-api/Inspector.js +4 -1
- package/dist/src/main-api/Inspector.js.map +1 -1
- package/dist/src/main-api/Renderer.d.ts +10 -0
- package/dist/src/main-api/Renderer.js +2 -0
- package/dist/src/main-api/Renderer.js.map +1 -1
- package/dist/tsconfig.dist.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/core/Autosizer.ts +224 -0
- package/src/core/CoreNode.test.ts +116 -2
- package/src/core/CoreNode.ts +247 -78
- package/src/core/CoreTextNode.ts +3 -5
- package/src/core/CoreTextureManager.ts +1 -1
- package/src/core/Stage.ts +10 -7
- package/src/core/TextureMemoryManager.ts +3 -3
- package/src/core/lib/ImageWorker.ts +36 -11
- package/src/core/lib/WebGlContextWrapper.ts +1 -1
- package/src/core/lib/utils.ts +28 -25
- package/src/core/renderers/CoreRenderer.ts +1 -32
- package/src/core/renderers/CoreShaderNode.ts +20 -0
- package/src/core/renderers/canvas/CanvasRenderer.ts +43 -51
- package/src/core/renderers/canvas/CanvasShaderNode.ts +1 -2
- package/src/core/renderers/webgl/SdfRenderOp.ts +105 -0
- package/src/core/renderers/webgl/WebGlCtxTexture.ts +16 -9
- package/src/core/renderers/webgl/WebGlRenderer.ts +56 -78
- package/src/core/renderers/webgl/WebGlShaderNode.ts +2 -7
- package/src/core/renderers/webgl/WebGlShaderProgram.ts +48 -38
- package/src/core/shaders/canvas/Border.ts +86 -29
- package/src/core/shaders/canvas/HolePunch.ts +2 -1
- package/src/core/shaders/canvas/LinearGradient.ts +8 -6
- package/src/core/shaders/canvas/RadialGradient.ts +7 -10
- package/src/core/shaders/canvas/Rounded.ts +5 -5
- package/src/core/shaders/canvas/RoundedWithBorder.ts +68 -18
- package/src/core/shaders/canvas/RoundedWithBorderAndShadow.ts +71 -23
- package/src/core/shaders/canvas/RoundedWithShadow.ts +6 -5
- package/src/core/shaders/canvas/Shadow.ts +7 -5
- package/src/core/shaders/canvas/utils/render.ts +45 -36
- package/src/core/shaders/templates/BorderTemplate.ts +30 -0
- package/src/core/shaders/webgl/Border.ts +72 -15
- package/src/core/shaders/webgl/RoundedWithBorder.ts +101 -31
- package/src/core/shaders/webgl/RoundedWithBorderAndShadow.ts +102 -38
- package/src/core/shaders/webgl/RoundedWithShadow.ts +5 -4
- package/src/core/shaders/webgl/Shadow.ts +12 -6
- package/src/core/text-rendering/SdfTextRenderer.ts +18 -21
- package/src/main-api/Inspector.ts +6 -3
- package/src/main-api/Renderer.ts +13 -0
- package/src/core/renderers/webgl/WebGlRenderOp.ts +0 -170
|
@@ -178,7 +178,7 @@ export class ImageWorkerManager {
|
|
|
178
178
|
imageWorkersEnabled = true;
|
|
179
179
|
messageManager: Record<number, MessageCallback> = {};
|
|
180
180
|
workers: Worker[] = [];
|
|
181
|
-
|
|
181
|
+
workerLoad: number[] = [];
|
|
182
182
|
nextId = 0;
|
|
183
183
|
|
|
184
184
|
constructor(
|
|
@@ -189,14 +189,19 @@ export class ImageWorkerManager {
|
|
|
189
189
|
numImageWorkers,
|
|
190
190
|
createImageBitmapSupport,
|
|
191
191
|
);
|
|
192
|
-
this.workers.forEach((worker) => {
|
|
193
|
-
worker.onmessage = this.handleMessage
|
|
192
|
+
this.workers.forEach((worker, index) => {
|
|
193
|
+
worker.onmessage = (event) => this.handleMessage(event, index);
|
|
194
194
|
});
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
private handleMessage(event: MessageEvent) {
|
|
197
|
+
private handleMessage(event: MessageEvent, workerIndex: number) {
|
|
198
198
|
const { id, data, error } = event.data as ImageWorkerMessage;
|
|
199
199
|
const msg = this.messageManager[id];
|
|
200
|
+
|
|
201
|
+
if (this.workerLoad[workerIndex]) {
|
|
202
|
+
this.workerLoad[workerIndex]--;
|
|
203
|
+
}
|
|
204
|
+
|
|
200
205
|
if (msg) {
|
|
201
206
|
const [resolve, reject] = msg;
|
|
202
207
|
delete this.messageManager[id];
|
|
@@ -242,14 +247,30 @@ export class ImageWorkerManager {
|
|
|
242
247
|
const workers: Worker[] = [];
|
|
243
248
|
for (let i = 0; i < numWorkers; i++) {
|
|
244
249
|
workers.push(new Worker(blobURL));
|
|
250
|
+
this.workerLoad.push(0);
|
|
245
251
|
}
|
|
246
252
|
return workers;
|
|
247
253
|
}
|
|
248
254
|
|
|
249
|
-
private
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
255
|
+
private getNextWorkerIndex(): number {
|
|
256
|
+
if (this.workers.length === 0) return -1;
|
|
257
|
+
|
|
258
|
+
let minLoad = 99;
|
|
259
|
+
let workerIndex = 0;
|
|
260
|
+
|
|
261
|
+
for (let i = 0; i < this.workers.length; i++) {
|
|
262
|
+
const load = this.workerLoad[i] || 0;
|
|
263
|
+
|
|
264
|
+
if (load === 0) {
|
|
265
|
+
return i;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (load < minLoad) {
|
|
269
|
+
minLoad = load;
|
|
270
|
+
workerIndex = i;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return workerIndex;
|
|
253
274
|
}
|
|
254
275
|
|
|
255
276
|
getImage(
|
|
@@ -265,9 +286,13 @@ export class ImageWorkerManager {
|
|
|
265
286
|
if (this.workers) {
|
|
266
287
|
const id = this.nextId++;
|
|
267
288
|
this.messageManager[id] = [resolve, reject];
|
|
268
|
-
const
|
|
269
|
-
|
|
270
|
-
|
|
289
|
+
const nextWorkerIndex = this.getNextWorkerIndex();
|
|
290
|
+
|
|
291
|
+
if (nextWorkerIndex !== -1) {
|
|
292
|
+
const worker = this.workers[nextWorkerIndex];
|
|
293
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
294
|
+
this.workerLoad[nextWorkerIndex]!++;
|
|
295
|
+
worker!.postMessage({
|
|
271
296
|
id,
|
|
272
297
|
src: src,
|
|
273
298
|
premultiplyAlpha,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
3
|
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
4
4
|
|
|
5
|
-
import { assertTruthy } from '../../utils.js';
|
|
5
|
+
import { assertTruthy, isProductionEnvironment } from '../../utils.js';
|
|
6
6
|
import type {
|
|
7
7
|
Vec2,
|
|
8
8
|
Vec3,
|
package/src/core/lib/utils.ts
CHANGED
|
@@ -82,8 +82,8 @@ export function getRgbaString(color: RGBA) {
|
|
|
82
82
|
export interface Rect {
|
|
83
83
|
x: number;
|
|
84
84
|
y: number;
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
w: number;
|
|
86
|
+
h: number;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
export interface RectWithValid extends Rect {
|
|
@@ -97,6 +97,11 @@ export interface Bound {
|
|
|
97
97
|
y2: number;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
export interface Coord {
|
|
101
|
+
x: number;
|
|
102
|
+
y: number;
|
|
103
|
+
}
|
|
104
|
+
|
|
100
105
|
export interface BoundWithValid extends Bound {
|
|
101
106
|
valid: boolean;
|
|
102
107
|
}
|
|
@@ -154,15 +159,15 @@ export function convertBoundToRect(bound: Bound, out?: Rect): Rect {
|
|
|
154
159
|
if (out) {
|
|
155
160
|
out.x = bound.x1;
|
|
156
161
|
out.y = bound.y1;
|
|
157
|
-
out.
|
|
158
|
-
out.
|
|
162
|
+
out.w = bound.x2 - bound.x1;
|
|
163
|
+
out.h = bound.y2 - bound.y1;
|
|
159
164
|
return out;
|
|
160
165
|
}
|
|
161
166
|
return {
|
|
162
167
|
x: bound.x1,
|
|
163
168
|
y: bound.y1,
|
|
164
|
-
|
|
165
|
-
|
|
169
|
+
w: bound.x2 - bound.x1,
|
|
170
|
+
h: bound.y2 - bound.y1,
|
|
166
171
|
};
|
|
167
172
|
}
|
|
168
173
|
|
|
@@ -175,35 +180,35 @@ export function intersectRect<T extends Rect = Rect>(
|
|
|
175
180
|
export function intersectRect(a: Rect, b: Rect, out?: Rect): Rect {
|
|
176
181
|
const x = Math.max(a.x, b.x);
|
|
177
182
|
const y = Math.max(a.y, b.y);
|
|
178
|
-
const
|
|
179
|
-
const
|
|
180
|
-
if (
|
|
183
|
+
const w = Math.min(a.x + a.w, b.x + b.w) - x;
|
|
184
|
+
const h = Math.min(a.y + a.h, b.y + b.h) - y;
|
|
185
|
+
if (w > 0 && h > 0) {
|
|
181
186
|
if (out) {
|
|
182
187
|
out.x = x;
|
|
183
188
|
out.y = y;
|
|
184
|
-
out.
|
|
185
|
-
out.
|
|
189
|
+
out.w = w;
|
|
190
|
+
out.h = h;
|
|
186
191
|
return out;
|
|
187
192
|
}
|
|
188
193
|
return {
|
|
189
194
|
x,
|
|
190
195
|
y,
|
|
191
|
-
|
|
192
|
-
|
|
196
|
+
w,
|
|
197
|
+
h,
|
|
193
198
|
};
|
|
194
199
|
}
|
|
195
200
|
if (out) {
|
|
196
201
|
out.x = 0;
|
|
197
202
|
out.y = 0;
|
|
198
|
-
out.
|
|
199
|
-
out.
|
|
203
|
+
out.w = 0;
|
|
204
|
+
out.h = 0;
|
|
200
205
|
return out;
|
|
201
206
|
}
|
|
202
207
|
return {
|
|
203
208
|
x: 0,
|
|
204
209
|
y: 0,
|
|
205
|
-
|
|
206
|
-
|
|
210
|
+
w: 0,
|
|
211
|
+
h: 0,
|
|
207
212
|
};
|
|
208
213
|
}
|
|
209
214
|
|
|
@@ -213,15 +218,15 @@ export function copyRect(a: Rect, out?: Rect): Rect {
|
|
|
213
218
|
if (out) {
|
|
214
219
|
out.x = a.x;
|
|
215
220
|
out.y = a.y;
|
|
216
|
-
out.
|
|
217
|
-
out.
|
|
221
|
+
out.w = a.w;
|
|
222
|
+
out.h = a.h;
|
|
218
223
|
return out;
|
|
219
224
|
}
|
|
220
225
|
return {
|
|
221
226
|
x: a.x,
|
|
222
227
|
y: a.y,
|
|
223
|
-
|
|
224
|
-
|
|
228
|
+
w: a.w,
|
|
229
|
+
h: a.h,
|
|
225
230
|
};
|
|
226
231
|
}
|
|
227
232
|
|
|
@@ -232,9 +237,7 @@ export function compareRect(a: Rect | null, b: Rect | null): boolean {
|
|
|
232
237
|
if (a === null || b === null) {
|
|
233
238
|
return false;
|
|
234
239
|
}
|
|
235
|
-
return
|
|
236
|
-
a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height
|
|
237
|
-
);
|
|
240
|
+
return a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h;
|
|
238
241
|
}
|
|
239
242
|
|
|
240
243
|
export function boundInsideBound(bound1: Bound, bound2: Bound) {
|
|
@@ -264,7 +267,7 @@ export function isBoundPositive(bound: Bound): boolean {
|
|
|
264
267
|
}
|
|
265
268
|
|
|
266
269
|
export function isRectPositive(rect: Rect): boolean {
|
|
267
|
-
return rect.
|
|
270
|
+
return rect.w > 0 && rect.h > 0;
|
|
268
271
|
}
|
|
269
272
|
|
|
270
273
|
/**
|
|
@@ -17,45 +17,14 @@
|
|
|
17
17
|
* limitations under the License.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import type { Dimensions } from '../../common/CommonTypes.js';
|
|
21
20
|
import type { CoreNode } from '../CoreNode.js';
|
|
22
|
-
import type { TextureOptions } from '../CoreTextureManager.js';
|
|
23
21
|
import type { Stage } from '../Stage.js';
|
|
24
22
|
import type { ContextSpy } from '../lib/ContextSpy.js';
|
|
25
|
-
import type { RenderCoords } from '../lib/RenderCoords.js';
|
|
26
|
-
import type { RectWithValid } from '../lib/utils.js';
|
|
27
23
|
import type { CoreShaderProgram } from './CoreShaderProgram.js';
|
|
28
24
|
import type { Texture, TextureCoords } from '../textures/Texture.js';
|
|
29
25
|
import { CoreContextTexture } from './CoreContextTexture.js';
|
|
30
26
|
import type { CoreShaderType, CoreShaderNode } from './CoreShaderNode.js';
|
|
31
27
|
|
|
32
|
-
export interface QuadOptions {
|
|
33
|
-
width: number;
|
|
34
|
-
height: number;
|
|
35
|
-
colorTl: number;
|
|
36
|
-
colorTr: number;
|
|
37
|
-
colorBl: number;
|
|
38
|
-
colorBr: number;
|
|
39
|
-
texture: Texture | null;
|
|
40
|
-
textureOptions: TextureOptions | null;
|
|
41
|
-
textureCoords: TextureCoords | undefined;
|
|
42
|
-
zIndex: number;
|
|
43
|
-
shader: CoreShaderNode | null;
|
|
44
|
-
alpha: number;
|
|
45
|
-
clippingRect: RectWithValid;
|
|
46
|
-
tx: number;
|
|
47
|
-
ty: number;
|
|
48
|
-
ta: number;
|
|
49
|
-
tb: number;
|
|
50
|
-
tc: number;
|
|
51
|
-
td: number;
|
|
52
|
-
renderCoords?: RenderCoords;
|
|
53
|
-
rtt: boolean;
|
|
54
|
-
parentHasRenderTexture: boolean;
|
|
55
|
-
framebufferDimensions: Dimensions | null;
|
|
56
|
-
time?: number | null;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
28
|
export interface CoreRendererOptions {
|
|
60
29
|
stage: Stage;
|
|
61
30
|
canvas: HTMLCanvasElement | OffscreenCanvas;
|
|
@@ -84,7 +53,7 @@ export abstract class CoreRenderer {
|
|
|
84
53
|
|
|
85
54
|
abstract reset(): void;
|
|
86
55
|
abstract render(surface?: 'screen' | CoreContextTexture): void;
|
|
87
|
-
abstract addQuad(
|
|
56
|
+
abstract addQuad(node: CoreNode): void;
|
|
88
57
|
abstract createCtxTexture(textureSource: Texture): CoreContextTexture;
|
|
89
58
|
abstract createShaderProgram(
|
|
90
59
|
shaderConfig: Readonly<CoreShaderType>,
|
|
@@ -96,6 +96,10 @@ export class CoreShaderNode<Props extends object = Record<string, unknown>> {
|
|
|
96
96
|
protected node: CoreNode | null = null;
|
|
97
97
|
readonly time: CoreShaderType['time'] = undefined;
|
|
98
98
|
update: (() => void) | undefined = undefined;
|
|
99
|
+
private _valueKeyCache = '';
|
|
100
|
+
private _valueKeyDirty = true;
|
|
101
|
+
private _lastW = 0;
|
|
102
|
+
private _lastH = 0;
|
|
99
103
|
|
|
100
104
|
constructor(
|
|
101
105
|
readonly shaderKey: string,
|
|
@@ -141,6 +145,7 @@ export class CoreShaderNode<Props extends object = Record<string, unknown>> {
|
|
|
141
145
|
} else {
|
|
142
146
|
this.resolvedProps![key] = value;
|
|
143
147
|
}
|
|
148
|
+
this._valueKeyDirty = true;
|
|
144
149
|
|
|
145
150
|
if (this.update !== undefined && this.node !== null) {
|
|
146
151
|
this.node.setUpdateType(UpdateType.RecalcUniforms);
|
|
@@ -158,12 +163,27 @@ export class CoreShaderNode<Props extends object = Record<string, unknown>> {
|
|
|
158
163
|
}
|
|
159
164
|
|
|
160
165
|
createValueKey() {
|
|
166
|
+
if (
|
|
167
|
+
this._valueKeyDirty === false &&
|
|
168
|
+
this.node !== null &&
|
|
169
|
+
this.node.w === this._lastW &&
|
|
170
|
+
this.node.h === this._lastH
|
|
171
|
+
) {
|
|
172
|
+
return this._valueKeyCache;
|
|
173
|
+
}
|
|
174
|
+
|
|
161
175
|
let valueKey = '';
|
|
162
176
|
for (const key in this.resolvedProps) {
|
|
163
177
|
valueKey += `${key}:${this.resolvedProps[key]!};`;
|
|
164
178
|
}
|
|
165
179
|
valueKey += `node-width:${this.node!.w}`;
|
|
166
180
|
valueKey += `node-height:${this.node!.h}`;
|
|
181
|
+
|
|
182
|
+
this._valueKeyCache = valueKey;
|
|
183
|
+
this._valueKeyDirty = false;
|
|
184
|
+
this._lastW = this.node!.w;
|
|
185
|
+
this._lastH = this.node!.h;
|
|
186
|
+
|
|
167
187
|
return valueKey;
|
|
168
188
|
}
|
|
169
189
|
|
|
@@ -20,11 +20,7 @@ import type { CoreNode } from '../../CoreNode.js';
|
|
|
20
20
|
import { SubTexture } from '../../textures/SubTexture.js';
|
|
21
21
|
import { TextureType, type Texture } from '../../textures/Texture.js';
|
|
22
22
|
import type { CoreContextTexture } from '../CoreContextTexture.js';
|
|
23
|
-
import {
|
|
24
|
-
CoreRenderer,
|
|
25
|
-
type CoreRendererOptions,
|
|
26
|
-
type QuadOptions,
|
|
27
|
-
} from '../CoreRenderer.js';
|
|
23
|
+
import { CoreRenderer, type CoreRendererOptions } from '../CoreRenderer.js';
|
|
28
24
|
import { CanvasTexture } from './CanvasTexture.js';
|
|
29
25
|
import { parseColor } from '../../lib/colorParser.js';
|
|
30
26
|
import { CanvasShaderNode, type CanvasShaderType } from './CanvasShaderNode.js';
|
|
@@ -66,10 +62,11 @@ export class CanvasRenderer extends CoreRenderer {
|
|
|
66
62
|
// noop
|
|
67
63
|
}
|
|
68
64
|
|
|
69
|
-
addQuad(
|
|
65
|
+
addQuad(node: CoreNode): void {
|
|
70
66
|
const ctx = this.context;
|
|
71
|
-
const { tx, ty, ta, tb, tc, td
|
|
72
|
-
|
|
67
|
+
const { tx, ty, ta, tb, tc, td } = node.globalTransform!;
|
|
68
|
+
const clippingRect = node.clippingRect;
|
|
69
|
+
let texture = (node.props.texture || this.stage.defaultTexture) as Texture;
|
|
73
70
|
// The Canvas2D renderer only supports image textures, no textures are used for color blocks
|
|
74
71
|
if (texture !== null) {
|
|
75
72
|
const textureType = texture.type;
|
|
@@ -84,13 +81,13 @@ export class CanvasRenderer extends CoreRenderer {
|
|
|
84
81
|
}
|
|
85
82
|
|
|
86
83
|
const hasTransform = ta !== 1;
|
|
87
|
-
const hasClipping = clippingRect.
|
|
88
|
-
const
|
|
84
|
+
const hasClipping = clippingRect.w !== 0 && clippingRect.h !== 0;
|
|
85
|
+
const shader = node.props.shader;
|
|
86
|
+
const hasShader = shader !== null;
|
|
89
87
|
|
|
90
88
|
let saveAndRestore = hasTransform === true || hasClipping === true;
|
|
91
89
|
if (hasShader === true) {
|
|
92
|
-
saveAndRestore =
|
|
93
|
-
saveAndRestore || (quad.shader as CanvasShaderNode).applySNR;
|
|
90
|
+
saveAndRestore = saveAndRestore || (shader as CanvasShaderNode).applySNR;
|
|
94
91
|
}
|
|
95
92
|
|
|
96
93
|
if (saveAndRestore) {
|
|
@@ -99,8 +96,8 @@ export class CanvasRenderer extends CoreRenderer {
|
|
|
99
96
|
|
|
100
97
|
if (hasClipping === true) {
|
|
101
98
|
const path = new Path2D();
|
|
102
|
-
const { x, y,
|
|
103
|
-
path.rect(x, y,
|
|
99
|
+
const { x, y, w, h } = clippingRect;
|
|
100
|
+
path.rect(x, y, w, h);
|
|
104
101
|
ctx.clip(path);
|
|
105
102
|
}
|
|
106
103
|
|
|
@@ -121,12 +118,13 @@ export class CanvasRenderer extends CoreRenderer {
|
|
|
121
118
|
|
|
122
119
|
if (hasShader === true) {
|
|
123
120
|
let renderContext: (() => void) | null = () => {
|
|
124
|
-
this.renderContext(
|
|
121
|
+
this.renderContext(node, texture);
|
|
125
122
|
};
|
|
126
|
-
|
|
123
|
+
|
|
124
|
+
(shader as CanvasShaderNode).render(ctx, node, renderContext);
|
|
127
125
|
renderContext = null;
|
|
128
126
|
} else {
|
|
129
|
-
this.renderContext(
|
|
127
|
+
this.renderContext(node, texture);
|
|
130
128
|
}
|
|
131
129
|
|
|
132
130
|
if (saveAndRestore) {
|
|
@@ -134,22 +132,20 @@ export class CanvasRenderer extends CoreRenderer {
|
|
|
134
132
|
}
|
|
135
133
|
}
|
|
136
134
|
|
|
137
|
-
renderContext(
|
|
138
|
-
const color =
|
|
139
|
-
const texture = quad.texture!;
|
|
135
|
+
renderContext(node: CoreNode, texture: Texture) {
|
|
136
|
+
const color = node.premultipliedColorTl;
|
|
140
137
|
const textureType = texture.type;
|
|
138
|
+
const tx = node.globalTransform!.tx;
|
|
139
|
+
const ty = node.globalTransform!.ty;
|
|
140
|
+
const width = node.props.w;
|
|
141
|
+
const height = node.props.h;
|
|
142
|
+
|
|
141
143
|
if (textureType !== TextureType.color) {
|
|
142
144
|
const tintColor = parseColor(color);
|
|
143
145
|
if (textureType !== TextureType.subTexture) {
|
|
144
146
|
const image = (texture.ctxTexture as CanvasTexture).getImage(tintColor);
|
|
145
|
-
this.context.globalAlpha = tintColor.a ??
|
|
146
|
-
this.context.drawImage(
|
|
147
|
-
image,
|
|
148
|
-
quad.tx,
|
|
149
|
-
quad.ty,
|
|
150
|
-
quad.width,
|
|
151
|
-
quad.height,
|
|
152
|
-
);
|
|
147
|
+
this.context.globalAlpha = tintColor.a ?? node.worldAlpha;
|
|
148
|
+
this.context.drawImage(image, tx, ty, width, height);
|
|
153
149
|
this.context.globalAlpha = 1;
|
|
154
150
|
return;
|
|
155
151
|
}
|
|
@@ -158,51 +154,47 @@ export class CanvasRenderer extends CoreRenderer {
|
|
|
158
154
|
).getImage(tintColor);
|
|
159
155
|
const props = (texture as SubTexture).props;
|
|
160
156
|
|
|
161
|
-
this.context.globalAlpha = tintColor.a ??
|
|
157
|
+
this.context.globalAlpha = tintColor.a ?? node.worldAlpha;
|
|
162
158
|
this.context.drawImage(
|
|
163
159
|
image,
|
|
164
160
|
props.x,
|
|
165
161
|
props.y,
|
|
166
162
|
props.w,
|
|
167
163
|
props.h,
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
164
|
+
tx,
|
|
165
|
+
ty,
|
|
166
|
+
width,
|
|
167
|
+
height,
|
|
172
168
|
);
|
|
173
169
|
this.context.globalAlpha = 1;
|
|
174
170
|
return;
|
|
175
171
|
}
|
|
176
172
|
const hasGradient =
|
|
177
|
-
|
|
173
|
+
node.premultipliedColorTl !== node.premultipliedColorTr ||
|
|
174
|
+
node.premultipliedColorTl !== node.premultipliedColorBr;
|
|
178
175
|
if (hasGradient === true) {
|
|
179
|
-
let endX: number =
|
|
180
|
-
let endY: number =
|
|
176
|
+
let endX: number = tx;
|
|
177
|
+
let endY: number = ty;
|
|
181
178
|
let endColor: number;
|
|
182
|
-
if (
|
|
179
|
+
if (node.premultipliedColorTl === node.premultipliedColorTr) {
|
|
183
180
|
// vertical
|
|
184
|
-
endX =
|
|
185
|
-
endY =
|
|
186
|
-
endColor =
|
|
181
|
+
endX = tx;
|
|
182
|
+
endY = ty + height;
|
|
183
|
+
endColor = node.premultipliedColorBr;
|
|
187
184
|
} else {
|
|
188
185
|
// horizontal
|
|
189
|
-
endX =
|
|
190
|
-
endY =
|
|
191
|
-
endColor =
|
|
186
|
+
endX = tx + width;
|
|
187
|
+
endY = ty;
|
|
188
|
+
endColor = node.premultipliedColorTr;
|
|
192
189
|
}
|
|
193
|
-
const gradient = this.context.createLinearGradient(
|
|
194
|
-
quad.tx,
|
|
195
|
-
quad.ty,
|
|
196
|
-
endX,
|
|
197
|
-
endY,
|
|
198
|
-
);
|
|
190
|
+
const gradient = this.context.createLinearGradient(tx, ty, endX, endY);
|
|
199
191
|
gradient.addColorStop(0, normalizeCanvasColor(color));
|
|
200
192
|
gradient.addColorStop(1, normalizeCanvasColor(endColor));
|
|
201
193
|
this.context.fillStyle = gradient;
|
|
202
|
-
this.context.fillRect(
|
|
194
|
+
this.context.fillRect(tx, ty, width, height);
|
|
203
195
|
} else {
|
|
204
196
|
this.context.fillStyle = normalizeCanvasColor(color);
|
|
205
|
-
this.context.fillRect(
|
|
197
|
+
this.context.fillRect(tx, ty, width, height);
|
|
206
198
|
}
|
|
207
199
|
}
|
|
208
200
|
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
import type { CoreNode } from '../../CoreNode.js';
|
|
19
19
|
import { normalizeCanvasColor } from '../../lib/colorCache.js';
|
|
20
20
|
import type { Stage } from '../../Stage.js';
|
|
21
|
-
import type { QuadOptions } from '../CoreRenderer.js';
|
|
22
21
|
import { CoreShaderNode, type CoreShaderType } from '../CoreShaderNode.js';
|
|
23
22
|
|
|
24
23
|
export type CanvasShaderType<
|
|
@@ -28,7 +27,7 @@ export type CanvasShaderType<
|
|
|
28
27
|
render: (
|
|
29
28
|
this: CanvasShaderNode<T, C>,
|
|
30
29
|
ctx: CanvasRenderingContext2D,
|
|
31
|
-
|
|
30
|
+
node: CoreNode,
|
|
32
31
|
renderContext: () => void,
|
|
33
32
|
) => void;
|
|
34
33
|
update?: (this: CanvasShaderNode<T, C>, node: CoreNode) => void;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* If not stated otherwise in this file or this component's LICENSE file the
|
|
3
|
+
* following copyright and licenses apply:
|
|
4
|
+
*
|
|
5
|
+
* Copyright 2023 Comcast Cable Communications Management, LLC.
|
|
6
|
+
*
|
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the License);
|
|
8
|
+
* you may not use this file except in compliance with the License.
|
|
9
|
+
* You may obtain a copy of the License at
|
|
10
|
+
*
|
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
*
|
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
* See the License for the specific language governing permissions and
|
|
17
|
+
* limitations under the License.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { CoreRenderOp } from '../CoreRenderOp.js';
|
|
21
|
+
import type { WebGlCtxTexture } from './WebGlCtxTexture.js';
|
|
22
|
+
import type { WebGlRenderer } from './WebGlRenderer.js';
|
|
23
|
+
import type { BufferCollection } from './internal/BufferCollection.js';
|
|
24
|
+
import type { WebGlShaderNode } from './WebGlShaderNode.js';
|
|
25
|
+
import type { RectWithValid } from '../../lib/utils.js';
|
|
26
|
+
import type { Dimensions } from '../../../common/CommonTypes.js';
|
|
27
|
+
import type { Stage } from '../../Stage.js';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Can render multiple quads with multiple textures (up to vertex shader texture limit)
|
|
31
|
+
*
|
|
32
|
+
*/
|
|
33
|
+
export class SdfRenderOp extends CoreRenderOp {
|
|
34
|
+
public numQuads = 0;
|
|
35
|
+
public readonly isCoreNode = false as const;
|
|
36
|
+
public renderOpTextures: WebGlCtxTexture[] = [];
|
|
37
|
+
public time: number = 0;
|
|
38
|
+
readonly stage: Stage;
|
|
39
|
+
|
|
40
|
+
constructor(
|
|
41
|
+
readonly renderer: WebGlRenderer,
|
|
42
|
+
readonly shader: WebGlShaderNode,
|
|
43
|
+
readonly sdfShaderProps: Record<string, unknown>,
|
|
44
|
+
readonly quadBufferCollection: BufferCollection,
|
|
45
|
+
readonly worldAlpha: number,
|
|
46
|
+
readonly clippingRect: RectWithValid,
|
|
47
|
+
readonly w: number,
|
|
48
|
+
readonly h: number,
|
|
49
|
+
readonly rtt: boolean,
|
|
50
|
+
readonly parentHasRenderTexture: boolean,
|
|
51
|
+
readonly framebufferDimensions: Dimensions | null,
|
|
52
|
+
) {
|
|
53
|
+
super();
|
|
54
|
+
this.stage = renderer.stage;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
addTexture(texture: WebGlCtxTexture): number {
|
|
58
|
+
const { renderOpTextures } = this;
|
|
59
|
+
const length = renderOpTextures.length;
|
|
60
|
+
|
|
61
|
+
// We only support 1 texture (atlas) for SDF for now, but following the pattern
|
|
62
|
+
for (let i = 0; i < length; i++) {
|
|
63
|
+
if (renderOpTextures[i] === texture) {
|
|
64
|
+
return i;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
renderOpTextures.push(texture);
|
|
69
|
+
return length;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
draw() {
|
|
73
|
+
const { glw, options, stage } = this.renderer;
|
|
74
|
+
|
|
75
|
+
stage.shManager.useShader(this.shader.program);
|
|
76
|
+
this.shader.program.bindRenderOp(this);
|
|
77
|
+
|
|
78
|
+
// Clipping
|
|
79
|
+
if (this.clippingRect.valid === true) {
|
|
80
|
+
const pixelRatio = this.parentHasRenderTexture ? 1 : stage.pixelRatio;
|
|
81
|
+
const clipX = Math.round(this.clippingRect.x * pixelRatio);
|
|
82
|
+
const clipWidth = Math.round(this.clippingRect.w * pixelRatio);
|
|
83
|
+
const clipHeight = Math.round(this.clippingRect.h * pixelRatio);
|
|
84
|
+
let clipY = Math.round(
|
|
85
|
+
options.canvas.height - clipHeight - this.clippingRect.y * pixelRatio,
|
|
86
|
+
);
|
|
87
|
+
// if parent has render texture, we need to adjust the scissor rect
|
|
88
|
+
// to be relative to the parent's framebuffer
|
|
89
|
+
if (this.parentHasRenderTexture) {
|
|
90
|
+
clipY = this.framebufferDimensions
|
|
91
|
+
? this.framebufferDimensions.h - this.h
|
|
92
|
+
: 0;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
glw.setScissorTest(true);
|
|
96
|
+
glw.scissor(clipX, clipY, clipWidth, clipHeight);
|
|
97
|
+
} else {
|
|
98
|
+
glw.setScissorTest(false);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// SDF rendering uses drawArrays with explicit triangle vertices (6 vertices per quad)
|
|
102
|
+
// Note: buffers should be bound by bindRenderOp -> bindBufferCollection
|
|
103
|
+
glw.drawArrays(glw.TRIANGLES, 0, 6 * this.numQuads);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -25,6 +25,7 @@ import { uploadCompressedTexture } from '../../lib/textureCompression.js';
|
|
|
25
25
|
import { CoreContextTexture } from '../CoreContextTexture.js';
|
|
26
26
|
import { isHTMLImageElement } from './internal/RendererUtils.js';
|
|
27
27
|
import type { Bound } from '../../lib/utils.js';
|
|
28
|
+
import { isProductionEnvironment } from '../../../utils.js';
|
|
28
29
|
|
|
29
30
|
const TRANSPARENT_TEXTURE_DATA = new Uint8Array([0, 0, 0, 0]);
|
|
30
31
|
|
|
@@ -69,11 +70,16 @@ export class WebGlCtxTexture extends CoreContextTexture {
|
|
|
69
70
|
return true;
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
if (isProductionEnvironment === false) {
|
|
74
|
+
const error = this.glw.getError();
|
|
75
|
+
if (error !== 0) {
|
|
76
|
+
this.state = 'failed';
|
|
77
|
+
this.textureSource.setState(
|
|
78
|
+
'failed',
|
|
79
|
+
new Error(`WebGL Error: ${error}`),
|
|
80
|
+
);
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
77
83
|
}
|
|
78
84
|
return false;
|
|
79
85
|
}
|
|
@@ -187,11 +193,13 @@ export class WebGlCtxTexture extends CoreContextTexture {
|
|
|
187
193
|
const format = glw.RGBA;
|
|
188
194
|
const formatBytes = 4;
|
|
189
195
|
const memoryPadding = 1.1; // Add padding to account for GPU Padding
|
|
196
|
+
const isImageBitmap =
|
|
197
|
+
typeof ImageBitmap !== 'undefined' && tdata instanceof ImageBitmap;
|
|
190
198
|
|
|
191
199
|
// If textureData is null, the texture is empty (0, 0) and we don't need to
|
|
192
200
|
// upload any data to the GPU.
|
|
193
201
|
if (
|
|
194
|
-
|
|
202
|
+
isImageBitmap ||
|
|
195
203
|
tdata instanceof ImageData ||
|
|
196
204
|
// not using typeof HTMLI mageElement due to web worker
|
|
197
205
|
isHTMLImageElement(tdata) === true
|
|
@@ -201,7 +209,7 @@ export class WebGlCtxTexture extends CoreContextTexture {
|
|
|
201
209
|
glw.bindTexture(this._nativeCtxTexture);
|
|
202
210
|
glw.pixelStorei(
|
|
203
211
|
glw.UNPACK_PREMULTIPLY_ALPHA_WEBGL,
|
|
204
|
-
!!textureData.premultiplyAlpha,
|
|
212
|
+
isImageBitmap ? false : !!textureData.premultiplyAlpha,
|
|
205
213
|
);
|
|
206
214
|
|
|
207
215
|
glw.texImage2D(0, format, format, glw.UNSIGNED_BYTE, tdata);
|
|
@@ -265,9 +273,8 @@ export class WebGlCtxTexture extends CoreContextTexture {
|
|
|
265
273
|
|
|
266
274
|
this.setTextureMemUse(w * h * formatBytes);
|
|
267
275
|
} else {
|
|
268
|
-
|
|
276
|
+
throw new Error(
|
|
269
277
|
`WebGlCoreCtxTexture.onLoadRequest: Unexpected textureData returned`,
|
|
270
|
-
textureData,
|
|
271
278
|
);
|
|
272
279
|
}
|
|
273
280
|
|