@oh-just-another/renderer-canvas 0.58.1 → 0.60.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.
- package/CHANGELOG.md +78 -0
- package/README.md +63 -15
- package/dist/.tsbuildinfo +1 -1
- package/dist/canvas-target.d.ts +6 -1
- package/dist/canvas-target.d.ts.map +1 -1
- package/dist/canvas-target.js +18 -5
- package/dist/canvas-target.js.map +1 -1
- package/dist/constants.d.ts +81 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +81 -0
- package/dist/constants.js.map +1 -1
- package/dist/hi-dpi.d.ts +21 -13
- package/dist/hi-dpi.d.ts.map +1 -1
- package/dist/hi-dpi.js +28 -33
- package/dist/hi-dpi.js.map +1 -1
- package/dist/image-source.d.ts +11 -0
- package/dist/image-source.d.ts.map +1 -1
- package/dist/image-source.js +20 -0
- package/dist/image-source.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -12
- package/dist/index.js.map +1 -1
- package/dist/layered-canvas.d.ts +7 -1
- package/dist/layered-canvas.d.ts.map +1 -1
- package/dist/layered-canvas.js +6 -3
- package/dist/layered-canvas.js.map +1 -1
- package/dist/layered-surface.d.ts +16 -0
- package/dist/layered-surface.d.ts.map +1 -1
- package/dist/layered-surface.js +53 -15
- package/dist/layered-surface.js.map +1 -1
- package/dist/recording-target.d.ts +85 -25
- package/dist/recording-target.d.ts.map +1 -1
- package/dist/recording-target.js +250 -50
- package/dist/recording-target.js.map +1 -1
- package/dist/render-worker.js +16 -3
- package/dist/render-worker.js.map +1 -1
- package/dist/tile-compositor.d.ts +43 -1
- package/dist/tile-compositor.d.ts.map +1 -1
- package/dist/tile-compositor.js +48 -5
- package/dist/tile-compositor.js.map +1 -1
- package/dist/webgl-helpers.d.ts +7 -0
- package/dist/webgl-helpers.d.ts.map +1 -0
- package/dist/webgl-helpers.js +32 -0
- package/dist/webgl-helpers.js.map +1 -0
- package/dist/webgl2-curve.d.ts +11 -0
- package/dist/webgl2-curve.d.ts.map +1 -1
- package/dist/webgl2-curve.js +151 -68
- package/dist/webgl2-curve.js.map +1 -1
- package/dist/webgl2-ellipse.d.ts +0 -27
- package/dist/webgl2-ellipse.d.ts.map +1 -1
- package/dist/webgl2-ellipse.js +21 -47
- package/dist/webgl2-ellipse.js.map +1 -1
- package/dist/webgl2-msdf-text.d.ts +14 -0
- package/dist/webgl2-msdf-text.d.ts.map +1 -1
- package/dist/webgl2-msdf-text.js +84 -36
- package/dist/webgl2-msdf-text.js.map +1 -1
- package/dist/webgl2-rect-batch.d.ts +81 -0
- package/dist/webgl2-rect-batch.d.ts.map +1 -0
- package/dist/webgl2-rect-batch.js +201 -0
- package/dist/webgl2-rect-batch.js.map +1 -0
- package/dist/webgl2-stroke.d.ts +6 -30
- package/dist/webgl2-stroke.d.ts.map +1 -1
- package/dist/webgl2-stroke.js +17 -30
- package/dist/webgl2-stroke.js.map +1 -1
- package/dist/webgl2-target.d.ts +74 -8
- package/dist/webgl2-target.d.ts.map +1 -1
- package/dist/webgl2-target.js +356 -257
- package/dist/webgl2-target.js.map +1 -1
- package/package.json +10 -8
package/dist/tile-compositor.js
CHANGED
|
@@ -2,8 +2,26 @@ import { TILE_SIZE, } from "@oh-just-another/renderer-core";
|
|
|
2
2
|
import { getElementsInLayer, getElementWorldBounds, getLayersInOrder, } from "@oh-just-another/scene";
|
|
3
3
|
import { createOffscreenCanvas2DTarget } from "./offscreen.js";
|
|
4
4
|
import { getElementRenderer } from "@oh-just-another/renderer-core";
|
|
5
|
+
/** @internal Exported for unit tests; not part of the package API. */
|
|
6
|
+
export const buildDrawOrderIndex = (scene) => {
|
|
7
|
+
const byId = new Map();
|
|
8
|
+
const order = new Map();
|
|
9
|
+
let rank = 0;
|
|
10
|
+
for (const layer of getLayersInOrder(scene)) {
|
|
11
|
+
if (!layer.visible)
|
|
12
|
+
continue;
|
|
13
|
+
for (const shape of getElementsInLayer(scene, layer.id)) {
|
|
14
|
+
byId.set(shape.id, shape);
|
|
15
|
+
order.set(shape.id, rank++);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return { byId, order };
|
|
19
|
+
};
|
|
5
20
|
export const renderViaTiles = (scene, mainTarget, options) => {
|
|
6
|
-
const { viewport, cache, changedElements, zoomBucket } = options;
|
|
21
|
+
const { viewport, cache, changedElements, zoomBucket, index } = options;
|
|
22
|
+
// Build the draw-order lookup once per frame when an index is supplied;
|
|
23
|
+
// each fresh tile reuses it instead of re-walking the scene.
|
|
24
|
+
const drawOrder = index ? buildDrawOrderIndex(scene) : null;
|
|
7
25
|
// 1) Invalidate cached tiles per patch (covers add / remove / move).
|
|
8
26
|
if (changedElements) {
|
|
9
27
|
for (const [id, record] of changedElements) {
|
|
@@ -25,7 +43,7 @@ export const renderViaTiles = (scene, mainTarget, options) => {
|
|
|
25
43
|
const key = { col, row, zoom: zoomBucket };
|
|
26
44
|
let entry = cache.get(key);
|
|
27
45
|
if (!entry) {
|
|
28
|
-
const fresh = rasteriseTile(scene, col, row, zoomBucket);
|
|
46
|
+
const fresh = rasteriseTile(scene, col, row, zoomBucket, index, drawOrder);
|
|
29
47
|
if (!fresh)
|
|
30
48
|
continue;
|
|
31
49
|
cache.set(fresh);
|
|
@@ -42,7 +60,7 @@ export const renderViaTiles = (scene, mainTarget, options) => {
|
|
|
42
60
|
* sized at `TILE_SIZE * zoomBucket` device pixels per side. Returns
|
|
43
61
|
* `null` when the tile contains no shapes.
|
|
44
62
|
*/
|
|
45
|
-
const rasteriseTile = (scene, col, row, zoomBucket) => {
|
|
63
|
+
const rasteriseTile = (scene, col, row, zoomBucket, index, drawOrder) => {
|
|
46
64
|
if (typeof OffscreenCanvas === "undefined")
|
|
47
65
|
return null;
|
|
48
66
|
const worldX = col * TILE_SIZE;
|
|
@@ -53,7 +71,9 @@ const rasteriseTile = (scene, col, row, zoomBucket) => {
|
|
|
53
71
|
width: TILE_SIZE,
|
|
54
72
|
height: TILE_SIZE,
|
|
55
73
|
};
|
|
56
|
-
const shapes =
|
|
74
|
+
const shapes = index && drawOrder
|
|
75
|
+
? elementsIntersectingTileIndexed(index, drawOrder, worldBounds)
|
|
76
|
+
: elementsIntersectingTile(scene, worldBounds);
|
|
57
77
|
if (shapes.length === 0)
|
|
58
78
|
return null;
|
|
59
79
|
// Bitmap size — `TILE_SIZE * zoomBucket` device pixels so the tile
|
|
@@ -90,7 +110,8 @@ const rasteriseTile = (scene, col, row, zoomBucket) => {
|
|
|
90
110
|
elements: shapes.map((s) => s.id),
|
|
91
111
|
};
|
|
92
112
|
};
|
|
93
|
-
|
|
113
|
+
/** @internal Exported for unit tests; not part of the package API. */
|
|
114
|
+
export const elementsIntersectingTile = (scene, tileBounds) => {
|
|
94
115
|
const out = [];
|
|
95
116
|
for (const layer of getLayersInOrder(scene)) {
|
|
96
117
|
if (!layer.visible)
|
|
@@ -103,5 +124,27 @@ const elementsIntersectingTile = (scene, tileBounds) => {
|
|
|
103
124
|
}
|
|
104
125
|
return out;
|
|
105
126
|
};
|
|
127
|
+
/**
|
|
128
|
+
* Index-backed equivalent of {@link elementsIntersectingTile}. Queries the
|
|
129
|
+
* spatial index for candidate ids overlapping the tile, filters them
|
|
130
|
+
* against the precise world-AABB (same predicate the full scan uses), then
|
|
131
|
+
* restores global draw order via `drawOrder.order`. Returns the identical
|
|
132
|
+
* set and ordering as the full scan for a correctly-populated index — only
|
|
133
|
+
* the work is O(candidates) instead of O(shapes).
|
|
134
|
+
*/
|
|
135
|
+
/** @internal Exported for unit tests; not part of the package API. */
|
|
136
|
+
export const elementsIntersectingTileIndexed = (index, drawOrder, tileBounds) => {
|
|
137
|
+
const hits = [];
|
|
138
|
+
for (const id of index.query(tileBounds)) {
|
|
139
|
+
const shape = drawOrder.byId.get(id);
|
|
140
|
+
if (!shape)
|
|
141
|
+
continue; // hidden layer or not in the current scene
|
|
142
|
+
if (!intersects(getElementWorldBounds(shape), tileBounds))
|
|
143
|
+
continue;
|
|
144
|
+
hits.push({ shape, order: drawOrder.order.get(id) ?? 0 });
|
|
145
|
+
}
|
|
146
|
+
hits.sort((a, b) => a.order - b.order);
|
|
147
|
+
return hits.map((h) => h.shape);
|
|
148
|
+
};
|
|
106
149
|
const intersects = (a, b) => a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y;
|
|
107
150
|
//# sourceMappingURL=tile-compositor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tile-compositor.js","sourceRoot":"","sources":["../src/tile-compositor.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,GAIV,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,
|
|
1
|
+
{"version":3,"file":"tile-compositor.js","sourceRoot":"","sources":["../src/tile-compositor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Assert a WebGL resource was created (non-null), or throw. */
|
|
2
|
+
export declare const glReq: <T>(v: T | null) => T;
|
|
3
|
+
/** Compile a shader of `type` from `src`; `label` names the program in errors. */
|
|
4
|
+
export declare const compileShader: (gl: WebGL2RenderingContext, type: number, src: string, label: string) => WebGLShader;
|
|
5
|
+
/** Link a program from compiled shaders; `label` names the program in errors. */
|
|
6
|
+
export declare const linkProgram: (gl: WebGL2RenderingContext, vert: WebGLShader, frag: WebGLShader, label: string) => WebGLProgram;
|
|
7
|
+
//# sourceMappingURL=webgl-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webgl-helpers.d.ts","sourceRoot":"","sources":["../src/webgl-helpers.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,eAAO,MAAM,KAAK,GAAI,CAAC,EAAE,GAAG,CAAC,GAAG,IAAI,KAAG,CAGtC,CAAC;AAEF,kFAAkF;AAClF,eAAO,MAAM,aAAa,GACxB,IAAI,sBAAsB,EAC1B,MAAM,MAAM,EACZ,KAAK,MAAM,EACX,OAAO,MAAM,KACZ,WAUF,CAAC;AAEF,iFAAiF;AACjF,eAAO,MAAM,WAAW,GACtB,IAAI,sBAAsB,EAC1B,MAAM,WAAW,EACjB,MAAM,WAAW,EACjB,OAAO,MAAM,KACZ,YAWF,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Assert a WebGL resource was created (non-null), or throw. */
|
|
2
|
+
export const glReq = (v) => {
|
|
3
|
+
if (v === null)
|
|
4
|
+
throw new Error("packages/renderer-canvas: WebGL resource creation failed");
|
|
5
|
+
return v;
|
|
6
|
+
};
|
|
7
|
+
/** Compile a shader of `type` from `src`; `label` names the program in errors. */
|
|
8
|
+
export const compileShader = (gl, type, src, label) => {
|
|
9
|
+
const sh = glReq(gl.createShader(type));
|
|
10
|
+
gl.shaderSource(sh, src);
|
|
11
|
+
gl.compileShader(sh);
|
|
12
|
+
if (!gl.getShaderParameter(sh, gl.COMPILE_STATUS)) {
|
|
13
|
+
const log = gl.getShaderInfoLog(sh);
|
|
14
|
+
gl.deleteShader(sh);
|
|
15
|
+
throw new Error(`${label} shader compile failed: ${log}`);
|
|
16
|
+
}
|
|
17
|
+
return sh;
|
|
18
|
+
};
|
|
19
|
+
/** Link a program from compiled shaders; `label` names the program in errors. */
|
|
20
|
+
export const linkProgram = (gl, vert, frag, label) => {
|
|
21
|
+
const program = glReq(gl.createProgram());
|
|
22
|
+
gl.attachShader(program, vert);
|
|
23
|
+
gl.attachShader(program, frag);
|
|
24
|
+
gl.linkProgram(program);
|
|
25
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
26
|
+
const log = gl.getProgramInfoLog(program);
|
|
27
|
+
gl.deleteProgram(program);
|
|
28
|
+
throw new Error(`${label} program link failed: ${log}`);
|
|
29
|
+
}
|
|
30
|
+
return program;
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=webgl-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webgl-helpers.js","sourceRoot":"","sources":["../src/webgl-helpers.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,MAAM,CAAC,MAAM,KAAK,GAAG,CAAI,CAAW,EAAK,EAAE;IACzC,IAAI,CAAC,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC5F,OAAO,CAAC,CAAC;AACX,CAAC,CAAC;AAEF,kFAAkF;AAClF,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,EAA0B,EAC1B,IAAY,EACZ,GAAW,EACX,KAAa,EACA,EAAE;IACf,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;IACxC,EAAE,CAAC,YAAY,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IACzB,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IACrB,IAAI,CAAC,EAAE,CAAC,kBAAkB,CAAC,EAAE,EAAE,EAAE,CAAC,cAAc,CAAC,EAAE,CAAC;QAClD,MAAM,GAAG,GAAG,EAAE,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;QACpC,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,2BAA2B,GAAG,EAAE,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC,CAAC;AAEF,iFAAiF;AACjF,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,EAA0B,EAC1B,IAAiB,EACjB,IAAiB,EACjB,KAAa,EACC,EAAE;IAChB,MAAM,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC,CAAC;IAC1C,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC/B,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC/B,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACxB,IAAI,CAAC,EAAE,CAAC,mBAAmB,CAAC,OAAO,EAAE,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC;QACrD,MAAM,GAAG,GAAG,EAAE,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC1C,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,yBAAyB,GAAG,EAAE,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC"}
|
package/dist/webgl2-curve.d.ts
CHANGED
|
@@ -43,4 +43,15 @@ export declare class LoopBlinnCurvePipeline {
|
|
|
43
43
|
}): void;
|
|
44
44
|
dispose(): void;
|
|
45
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Cached triangulation lookup. Returns per-entry packed buffers —
|
|
48
|
+
* valid until the entry is evicted, which can't happen before the
|
|
49
|
+
* caller's synchronous `bufferData` upload.
|
|
50
|
+
*
|
|
51
|
+
* Exported for tests only — not part of the package's public API.
|
|
52
|
+
*/
|
|
53
|
+
export declare const triangulateCached: (curves: readonly CurveSegment[]) => {
|
|
54
|
+
positions: Float32Array;
|
|
55
|
+
uvs: Float32Array;
|
|
56
|
+
};
|
|
46
57
|
//# sourceMappingURL=webgl2-curve.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webgl2-curve.d.ts","sourceRoot":"","sources":["../src/webgl2-curve.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"webgl2-curve.d.ts","sourceRoot":"","sources":["../src/webgl2-curve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAIxD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;CACnC;AAED,qBAAa,sBAAsB;IAUrB,OAAO,CAAC,QAAQ,CAAC,EAAE;IAT/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAc;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA8B;IACzD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8B;IACrD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8B;IACvD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;gBAED,EAAE,EAAE,sBAAsB;IAavD;;;;OAIG;IACH,IAAI,CACF,MAAM,EAAE,SAAS,YAAY,EAAE,EAC/B,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EACxC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,SAAS,EACpB,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAC7C,IAAI;IAwBP,OAAO,IAAI,IAAI;CAKhB;AAyID;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,SAAS,YAAY,EAAE,KAC9B;IAAE,SAAS,EAAE,YAAY,CAAC;IAAC,GAAG,EAAE,YAAY,CAAA;CAoB9C,CAAC"}
|
package/dist/webgl2-curve.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CurveTriangleBatch } from "@oh-just-another/curve-mesh";
|
|
2
|
+
import { WEBGL2_CURVE_TRIANGULATION_CACHE_CAP } from "./constants.js";
|
|
3
|
+
import { compileShader, glReq, linkProgram } from "./webgl-helpers.js";
|
|
2
4
|
export class LoopBlinnCurvePipeline {
|
|
3
5
|
gl;
|
|
4
6
|
program;
|
|
@@ -11,9 +13,9 @@ export class LoopBlinnCurvePipeline {
|
|
|
11
13
|
aUVW;
|
|
12
14
|
constructor(gl) {
|
|
13
15
|
this.gl = gl;
|
|
14
|
-
const vert =
|
|
15
|
-
const frag =
|
|
16
|
-
this.program =
|
|
16
|
+
const vert = compileShader(gl, gl.VERTEX_SHADER, VERTEX_SRC, "Loop-Blinn");
|
|
17
|
+
const frag = compileShader(gl, gl.FRAGMENT_SHADER, FRAGMENT_SRC, "Loop-Blinn");
|
|
18
|
+
this.program = linkProgram(gl, vert, frag, "Loop-Blinn");
|
|
17
19
|
this.vbo = glReq(gl.createBuffer());
|
|
18
20
|
this.uvBuf = glReq(gl.createBuffer());
|
|
19
21
|
this.aPos = gl.getAttribLocation(this.program, "aPos");
|
|
@@ -30,27 +32,9 @@ export class LoopBlinnCurvePipeline {
|
|
|
30
32
|
draw(curves, color, opacity, transform, surfaceSize) {
|
|
31
33
|
if (curves.length === 0 || opacity <= 0)
|
|
32
34
|
return;
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
if (seg.kind === "q") {
|
|
36
|
-
const [p0, p1, p2] = seg.points;
|
|
37
|
-
if (!p0 || !p1 || !p2)
|
|
38
|
-
continue;
|
|
39
|
-
const tri = quadraticToTriangle(p0, p1, p2);
|
|
40
|
-
if (tri)
|
|
41
|
-
triangles.push(tri);
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
const [p0, p1, p2, p3] = seg.points;
|
|
45
|
-
if (!p0 || !p1 || !p2 || !p3)
|
|
46
|
-
continue;
|
|
47
|
-
for (const tri of cubicToTriangles(p0, p1, p2, p3))
|
|
48
|
-
triangles.push(tri);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
if (triangles.length === 0)
|
|
35
|
+
const { positions, uvs } = triangulateCached(curves);
|
|
36
|
+
if (positions.length === 0)
|
|
52
37
|
return;
|
|
53
|
-
const { positions, uvs } = packCurveTriangles(triangles);
|
|
54
38
|
const gl = this.gl;
|
|
55
39
|
gl.useProgram(this.program);
|
|
56
40
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
|
|
@@ -72,20 +56,152 @@ export class LoopBlinnCurvePipeline {
|
|
|
72
56
|
this.gl.deleteProgram(this.program);
|
|
73
57
|
}
|
|
74
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Module-level scratch for `affineToClipMat3` — same reuse pattern as
|
|
61
|
+
* the earcut / stroke / `applyMat` scratch buffers in webgl2-target.
|
|
62
|
+
* Consumed synchronously by `uniformMatrix3fv` (which copies the values
|
|
63
|
+
* into GL state), so one shared buffer avoids a Float32Array allocation
|
|
64
|
+
* per curve draw.
|
|
65
|
+
*/
|
|
66
|
+
const scratchClipMat3 = new Float32Array(9);
|
|
75
67
|
const affineToClipMat3 = (t, w, h) => {
|
|
76
68
|
const sx = 2 / w;
|
|
77
69
|
const sy = -2 / h;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
70
|
+
scratchClipMat3[0] = t.a * sx;
|
|
71
|
+
scratchClipMat3[1] = t.b * sy;
|
|
72
|
+
scratchClipMat3[2] = 0;
|
|
73
|
+
scratchClipMat3[3] = t.c * sx;
|
|
74
|
+
scratchClipMat3[4] = t.d * sy;
|
|
75
|
+
scratchClipMat3[5] = 0;
|
|
76
|
+
scratchClipMat3[6] = t.e * sx - 1;
|
|
77
|
+
scratchClipMat3[7] = t.f * sy + 1;
|
|
78
|
+
scratchClipMat3[8] = 1;
|
|
79
|
+
return scratchClipMat3;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Content-keyed LRU cache of Loop-Blinn triangulations, shared by all
|
|
83
|
+
* `LoopBlinnCurvePipeline` instances (the data is GL-independent).
|
|
84
|
+
*
|
|
85
|
+
* Renderers emit paths in element-local coordinates and `draw()` gets
|
|
86
|
+
* the view transform separately (applied in the vertex shader), so:
|
|
87
|
+
* - identical geometry (every same-size rounded rect) shares one entry;
|
|
88
|
+
* - pan / zoom / drag never invalidate an entry;
|
|
89
|
+
* - no scale bucket is needed — triangulation is scale-independent
|
|
90
|
+
* (fixed cubic subdivision count, no screen-space adaptivity).
|
|
91
|
+
*
|
|
92
|
+
* The `curves` array is rebuilt by `WebGL2Target` on every
|
|
93
|
+
* `beginPath()`, so there is no stable object identity to key a WeakMap
|
|
94
|
+
* on; instead the key is the flat list of segment kinds +
|
|
95
|
+
* control-point coordinates, addressed by a 32-bit FNV-1a hash with a
|
|
96
|
+
* full float comparison on hit (hash collisions fall back to
|
|
97
|
+
* recompute + replace). `Map` insertion order gives LRU: hits re-insert
|
|
98
|
+
* at the tail, overflow evicts the head.
|
|
99
|
+
*/
|
|
100
|
+
const curveMeshCache = new Map();
|
|
101
|
+
/** Scratch for building the flat key without per-draw allocation. */
|
|
102
|
+
let scratchKey = new Float64Array(64);
|
|
103
|
+
const ensureKeyCapacity = (n) => {
|
|
104
|
+
if (scratchKey.length >= n)
|
|
105
|
+
return;
|
|
106
|
+
let cap = scratchKey.length;
|
|
107
|
+
while (cap < n)
|
|
108
|
+
cap *= 2;
|
|
109
|
+
scratchKey = new Float64Array(cap);
|
|
110
|
+
};
|
|
111
|
+
/** Views over one float64 for hashing its bit pattern. */
|
|
112
|
+
const hashFloatBuf = new Float64Array(1);
|
|
113
|
+
const hashFloatBits = new Uint32Array(hashFloatBuf.buffer);
|
|
114
|
+
/** Shared zero-allocation triangulation sink (see `CurveTriangleBatch`). */
|
|
115
|
+
const sharedBatch = new CurveTriangleBatch();
|
|
116
|
+
/**
|
|
117
|
+
* Flatten `curves` into `scratchKey` (kind marker + control points per
|
|
118
|
+
* segment) and return the used length.
|
|
119
|
+
*/
|
|
120
|
+
const buildKey = (curves) => {
|
|
121
|
+
// Worst case per segment: 1 kind marker + 4 points × 2 coords.
|
|
122
|
+
ensureKeyCapacity(curves.length * 9);
|
|
123
|
+
const key = scratchKey;
|
|
124
|
+
let off = 0;
|
|
125
|
+
for (const seg of curves) {
|
|
126
|
+
key[off++] = seg.kind === "q" ? 1 : 2;
|
|
127
|
+
for (const p of seg.points) {
|
|
128
|
+
key[off++] = p.x;
|
|
129
|
+
key[off++] = p.y;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return off;
|
|
133
|
+
};
|
|
134
|
+
/** FNV-1a over the bit patterns of `key[0..len)`. */
|
|
135
|
+
const hashKey = (key, len) => {
|
|
136
|
+
let h = 0x811c9dc5;
|
|
137
|
+
for (let i = 0; i < len; i++) {
|
|
138
|
+
hashFloatBuf[0] = key[i] ?? 0;
|
|
139
|
+
h = Math.imul(h ^ (hashFloatBits[0] ?? 0), 0x01000193);
|
|
140
|
+
h = Math.imul(h ^ (hashFloatBits[1] ?? 0), 0x01000193);
|
|
141
|
+
}
|
|
142
|
+
return h >>> 0;
|
|
143
|
+
};
|
|
144
|
+
const keysEqual = (a, b, len) => {
|
|
145
|
+
if (a.length !== len)
|
|
146
|
+
return false;
|
|
147
|
+
for (let i = 0; i < len; i++) {
|
|
148
|
+
if (a[i] !== b[i])
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
return true;
|
|
152
|
+
};
|
|
153
|
+
/** Triangulate `curves` through the shared batch into a fresh entry. */
|
|
154
|
+
const triangulate = (curves, keyLen) => {
|
|
155
|
+
sharedBatch.reset();
|
|
156
|
+
for (const seg of curves) {
|
|
157
|
+
if (seg.kind === "q") {
|
|
158
|
+
const [p0, p1, p2] = seg.points;
|
|
159
|
+
if (!p0 || !p1 || !p2)
|
|
160
|
+
continue;
|
|
161
|
+
sharedBatch.addQuadratic(p0, p1, p2);
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
const [p0, p1, p2, p3] = seg.points;
|
|
165
|
+
if (!p0 || !p1 || !p2 || !p3)
|
|
166
|
+
continue;
|
|
167
|
+
sharedBatch.addCubic(p0, p1, p2, p3);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
key: scratchKey.slice(0, keyLen),
|
|
172
|
+
// Copy out of the shared batch — entries outlive the next batch use.
|
|
173
|
+
positions: new Float32Array(sharedBatch.positions),
|
|
174
|
+
uvs: new Float32Array(sharedBatch.uvs),
|
|
175
|
+
};
|
|
176
|
+
};
|
|
177
|
+
/**
|
|
178
|
+
* Cached triangulation lookup. Returns per-entry packed buffers —
|
|
179
|
+
* valid until the entry is evicted, which can't happen before the
|
|
180
|
+
* caller's synchronous `bufferData` upload.
|
|
181
|
+
*
|
|
182
|
+
* Exported for tests only — not part of the package's public API.
|
|
183
|
+
*/
|
|
184
|
+
export const triangulateCached = (curves) => {
|
|
185
|
+
const keyLen = buildKey(curves);
|
|
186
|
+
const hash = hashKey(scratchKey, keyLen);
|
|
187
|
+
const cached = curveMeshCache.get(hash);
|
|
188
|
+
if (cached && keysEqual(cached.key, scratchKey, keyLen)) {
|
|
189
|
+
// Touch — re-insert at the tail so LRU eviction picks colder entries.
|
|
190
|
+
curveMeshCache.delete(hash);
|
|
191
|
+
curveMeshCache.set(hash, cached);
|
|
192
|
+
return cached;
|
|
193
|
+
}
|
|
194
|
+
// Miss or hash collision — recompute and (re)place the slot.
|
|
195
|
+
const entry = triangulate(curves, keyLen);
|
|
196
|
+
curveMeshCache.delete(hash);
|
|
197
|
+
curveMeshCache.set(hash, entry);
|
|
198
|
+
while (curveMeshCache.size > WEBGL2_CURVE_TRIANGULATION_CACHE_CAP) {
|
|
199
|
+
const oldest = curveMeshCache.keys().next().value;
|
|
200
|
+
if (oldest === undefined)
|
|
201
|
+
break;
|
|
202
|
+
curveMeshCache.delete(oldest);
|
|
203
|
+
}
|
|
204
|
+
return entry;
|
|
89
205
|
};
|
|
90
206
|
/**
|
|
91
207
|
* Vertex shader passes through the Loop-Blinn (u, v, w) coordinates as
|
|
@@ -132,37 +248,4 @@ void main() {
|
|
|
132
248
|
float a = coverage * uOpacity;
|
|
133
249
|
fragColor = vec4(uColor * a, a);
|
|
134
250
|
}`;
|
|
135
|
-
/**
|
|
136
|
-
* Asserts a WebGL resource handle is non-null. `gl.createBuffer` /
|
|
137
|
-
* `getUniformLocation` / `createShader` are typed non-null but return
|
|
138
|
-
* `null` on context loss; this surfaces that as a throw.
|
|
139
|
-
*/
|
|
140
|
-
const glReq = (v) => {
|
|
141
|
-
if (v === null)
|
|
142
|
-
throw new Error("packages/renderer-canvas: WebGL resource creation failed");
|
|
143
|
-
return v;
|
|
144
|
-
};
|
|
145
|
-
const compile = (gl, type, src) => {
|
|
146
|
-
const sh = glReq(gl.createShader(type));
|
|
147
|
-
gl.shaderSource(sh, src);
|
|
148
|
-
gl.compileShader(sh);
|
|
149
|
-
if (!gl.getShaderParameter(sh, gl.COMPILE_STATUS)) {
|
|
150
|
-
const log = gl.getShaderInfoLog(sh);
|
|
151
|
-
gl.deleteShader(sh);
|
|
152
|
-
throw new Error(`Loop-Blinn shader compile failed: ${log}`);
|
|
153
|
-
}
|
|
154
|
-
return sh;
|
|
155
|
-
};
|
|
156
|
-
const link = (gl, vert, frag) => {
|
|
157
|
-
const program = gl.createProgram();
|
|
158
|
-
gl.attachShader(program, vert);
|
|
159
|
-
gl.attachShader(program, frag);
|
|
160
|
-
gl.linkProgram(program);
|
|
161
|
-
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
162
|
-
const log = gl.getProgramInfoLog(program);
|
|
163
|
-
gl.deleteProgram(program);
|
|
164
|
-
throw new Error(`Loop-Blinn program link failed: ${log}`);
|
|
165
|
-
}
|
|
166
|
-
return program;
|
|
167
|
-
};
|
|
168
251
|
//# sourceMappingURL=webgl2-curve.js.map
|
package/dist/webgl2-curve.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webgl2-curve.js","sourceRoot":"","sources":["../src/webgl2-curve.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"webgl2-curve.js","sourceRoot":"","sources":["../src/webgl2-curve.ts"],"names":[],"mappings":"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"}
|
package/dist/webgl2-ellipse.d.ts
CHANGED
|
@@ -1,31 +1,4 @@
|
|
|
1
1
|
import type { Transform } from "@oh-just-another/types";
|
|
2
|
-
/**
|
|
3
|
-
* Fragment-shader SDF ellipse pipeline for `WebGL2Target`. Renders an
|
|
4
|
-
* ellipse as a single textured quad (4 vertices, 2 triangles)
|
|
5
|
-
* regardless of radius — the fragment shader does an inside/outside
|
|
6
|
-
* test against the unit circle in normalised local coordinates.
|
|
7
|
-
*
|
|
8
|
-
* Vertex layout (static, interleaved):
|
|
9
|
-
* aPos aLocal
|
|
10
|
-
* 0,0 -1,-1
|
|
11
|
-
* 1,0 1,-1
|
|
12
|
-
* 0,1 -1, 1
|
|
13
|
-
* 1,1 1, 1
|
|
14
|
-
*
|
|
15
|
-
* `uTransform` maps `aPos` (unit square [0,1]²) through:
|
|
16
|
-
* 1. scale to ellipse bbox (2*rx, 2*ry)
|
|
17
|
-
* 2. translate to (cx-rx, cy-ry)
|
|
18
|
-
* 3. apply caller's world→screen affine
|
|
19
|
-
* 4. pixel→clip-space (NDC)
|
|
20
|
-
*
|
|
21
|
-
* The fragment shader gets `vLocal` interpolated across the quad:
|
|
22
|
-
* inside the ellipse → dot(vLocal, vLocal) < 1
|
|
23
|
-
* on the boundary → dot(vLocal, vLocal) = 1
|
|
24
|
-
* outside → dot(vLocal, vLocal) > 1
|
|
25
|
-
*
|
|
26
|
-
* `smoothstep(1+fwidth, 1-fwidth, r²)` gives sub-pixel AA at the
|
|
27
|
-
* boundary independent of zoom.
|
|
28
|
-
*/
|
|
29
2
|
export declare class EllipsePipeline {
|
|
30
3
|
private readonly gl;
|
|
31
4
|
private readonly program;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webgl2-ellipse.d.ts","sourceRoot":"","sources":["../src/webgl2-ellipse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"webgl2-ellipse.d.ts","sourceRoot":"","sources":["../src/webgl2-ellipse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAuCxD,qBAAa,eAAe;IASd,OAAO,CAAC,QAAQ,CAAC,EAAE;IAR/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAc;IAClC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA8B;IACzD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8B;IACrD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8B;gBAE1B,EAAE,EAAE,sBAAsB;IAmBvD;;;;;;OAMG;IACH,IAAI,CACF,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EACxC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,SAAS,EACpB,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAC7C,IAAI;IAqCP,OAAO,IAAI,IAAI;CAIhB"}
|
package/dist/webgl2-ellipse.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { compileShader, glReq, linkProgram } from "./webgl-helpers.js";
|
|
1
2
|
/**
|
|
2
3
|
* Fragment-shader SDF ellipse pipeline for `WebGL2Target`. Renders an
|
|
3
4
|
* ellipse as a single textured quad (4 vertices, 2 triangles)
|
|
@@ -25,6 +26,13 @@
|
|
|
25
26
|
* `smoothstep(1+fwidth, 1-fwidth, r²)` gives sub-pixel AA at the
|
|
26
27
|
* boundary independent of zoom.
|
|
27
28
|
*/
|
|
29
|
+
/**
|
|
30
|
+
* Module-level scratch mat3 — same reuse pattern as the earcut / stroke
|
|
31
|
+
* scratch buffers in webgl2-target/webgl2-stroke. `uniformMatrix3fv`
|
|
32
|
+
* copies the values into GL state synchronously, so one shared buffer
|
|
33
|
+
* avoids a Float32Array allocation per ellipse fill.
|
|
34
|
+
*/
|
|
35
|
+
const scratchMat3 = new Float32Array(9);
|
|
28
36
|
export class EllipsePipeline {
|
|
29
37
|
gl;
|
|
30
38
|
program;
|
|
@@ -36,9 +44,9 @@ export class EllipsePipeline {
|
|
|
36
44
|
uOpacity;
|
|
37
45
|
constructor(gl) {
|
|
38
46
|
this.gl = gl;
|
|
39
|
-
const vert =
|
|
40
|
-
const frag =
|
|
41
|
-
this.program =
|
|
47
|
+
const vert = compileShader(gl, gl.VERTEX_SHADER, VERTEX_SRC, "Ellipse");
|
|
48
|
+
const frag = compileShader(gl, gl.FRAGMENT_SHADER, FRAGMENT_SRC, "Ellipse");
|
|
49
|
+
this.program = linkProgram(gl, vert, frag, "Ellipse");
|
|
42
50
|
this.aPos = gl.getAttribLocation(this.program, "aPos");
|
|
43
51
|
this.aLocal = gl.getAttribLocation(this.program, "aLocal");
|
|
44
52
|
this.uTransform = gl.getUniformLocation(this.program, "uTransform");
|
|
@@ -78,18 +86,16 @@ export class EllipsePipeline {
|
|
|
78
86
|
// inWorld = transform · (scaleSq + (left, top))
|
|
79
87
|
// inClip = pixel→clip(inWorld)
|
|
80
88
|
const t = transform;
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
]);
|
|
92
|
-
gl.uniformMatrix3fv(this.uTransform, false, mat);
|
|
89
|
+
scratchMat3[0] = t.a * w * sx;
|
|
90
|
+
scratchMat3[1] = t.b * w * sy;
|
|
91
|
+
scratchMat3[2] = 0;
|
|
92
|
+
scratchMat3[3] = t.c * h * sx;
|
|
93
|
+
scratchMat3[4] = t.d * h * sy;
|
|
94
|
+
scratchMat3[5] = 0;
|
|
95
|
+
scratchMat3[6] = (t.a * left + t.c * top + t.e) * sx - 1;
|
|
96
|
+
scratchMat3[7] = (t.b * left + t.d * top + t.f) * sy + 1;
|
|
97
|
+
scratchMat3[8] = 1;
|
|
98
|
+
gl.uniformMatrix3fv(this.uTransform, false, scratchMat3);
|
|
93
99
|
gl.uniform3f(this.uColor, color[0], color[1], color[2]);
|
|
94
100
|
gl.uniform1f(this.uOpacity, opacity);
|
|
95
101
|
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
@@ -135,36 +141,4 @@ void main() {
|
|
|
135
141
|
float a = coverage * uOpacity;
|
|
136
142
|
fragColor = vec4(uColor * a, a);
|
|
137
143
|
}`;
|
|
138
|
-
/**
|
|
139
|
-
* Asserts a WebGL resource handle is non-null. Creation APIs are typed
|
|
140
|
-
* non-null but return `null` on context loss; surface that as a throw.
|
|
141
|
-
*/
|
|
142
|
-
const glReq = (v) => {
|
|
143
|
-
if (v === null)
|
|
144
|
-
throw new Error("packages/renderer-canvas: WebGL resource creation failed");
|
|
145
|
-
return v;
|
|
146
|
-
};
|
|
147
|
-
const compile = (gl, type, src) => {
|
|
148
|
-
const sh = glReq(gl.createShader(type));
|
|
149
|
-
gl.shaderSource(sh, src);
|
|
150
|
-
gl.compileShader(sh);
|
|
151
|
-
if (!gl.getShaderParameter(sh, gl.COMPILE_STATUS)) {
|
|
152
|
-
const log = gl.getShaderInfoLog(sh);
|
|
153
|
-
gl.deleteShader(sh);
|
|
154
|
-
throw new Error(`Ellipse shader compile failed: ${log}`);
|
|
155
|
-
}
|
|
156
|
-
return sh;
|
|
157
|
-
};
|
|
158
|
-
const link = (gl, vert, frag) => {
|
|
159
|
-
const program = gl.createProgram();
|
|
160
|
-
gl.attachShader(program, vert);
|
|
161
|
-
gl.attachShader(program, frag);
|
|
162
|
-
gl.linkProgram(program);
|
|
163
|
-
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
164
|
-
const log = gl.getProgramInfoLog(program);
|
|
165
|
-
gl.deleteProgram(program);
|
|
166
|
-
throw new Error(`Ellipse program link failed: ${log}`);
|
|
167
|
-
}
|
|
168
|
-
return program;
|
|
169
|
-
};
|
|
170
144
|
//# sourceMappingURL=webgl2-ellipse.js.map
|