@oh-just-another/renderer-canvas 0.57.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 +18 -0
- package/LICENSE +21 -0
- package/README.md +36 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/canvas-target.d.ts +83 -0
- package/dist/canvas-target.d.ts.map +1 -0
- package/dist/canvas-target.js +208 -0
- package/dist/canvas-target.js.map +1 -0
- package/dist/canvas-text-shaper.d.ts +11 -0
- package/dist/canvas-text-shaper.d.ts.map +1 -0
- package/dist/canvas-text-shaper.js +56 -0
- package/dist/canvas-text-shaper.js.map +1 -0
- package/dist/constants.d.ts +52 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +52 -0
- package/dist/constants.js.map +1 -0
- package/dist/hi-dpi.d.ts +26 -0
- package/dist/hi-dpi.d.ts.map +1 -0
- package/dist/hi-dpi.js +62 -0
- package/dist/hi-dpi.js.map +1 -0
- package/dist/image-source.d.ts +3 -0
- package/dist/image-source.d.ts.map +1 -0
- package/dist/image-source.js +65 -0
- package/dist/image-source.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/layered-canvas.d.ts +46 -0
- package/dist/layered-canvas.d.ts.map +1 -0
- package/dist/layered-canvas.js +95 -0
- package/dist/layered-canvas.js.map +1 -0
- package/dist/layered-surface.d.ts +75 -0
- package/dist/layered-surface.d.ts.map +1 -0
- package/dist/layered-surface.js +262 -0
- package/dist/layered-surface.js.map +1 -0
- package/dist/offscreen.d.ts +30 -0
- package/dist/offscreen.d.ts.map +1 -0
- package/dist/offscreen.js +50 -0
- package/dist/offscreen.js.map +1 -0
- package/dist/recording-target.d.ts +203 -0
- package/dist/recording-target.d.ts.map +1 -0
- package/dist/recording-target.js +260 -0
- package/dist/recording-target.js.map +1 -0
- package/dist/render-worker.d.ts +2 -0
- package/dist/render-worker.d.ts.map +1 -0
- package/dist/render-worker.js +112 -0
- package/dist/render-worker.js.map +1 -0
- package/dist/tile-compositor.d.ts +44 -0
- package/dist/tile-compositor.d.ts.map +1 -0
- package/dist/tile-compositor.js +110 -0
- package/dist/tile-compositor.js.map +1 -0
- package/dist/webgl2-color.d.ts +13 -0
- package/dist/webgl2-color.d.ts.map +1 -0
- package/dist/webgl2-color.js +26 -0
- package/dist/webgl2-color.js.map +1 -0
- package/dist/webgl2-curve.d.ts +46 -0
- package/dist/webgl2-curve.d.ts.map +1 -0
- package/dist/webgl2-curve.js +162 -0
- package/dist/webgl2-curve.js.map +1 -0
- package/dist/webgl2-ellipse.d.ts +52 -0
- package/dist/webgl2-ellipse.d.ts.map +1 -0
- package/dist/webgl2-ellipse.js +171 -0
- package/dist/webgl2-ellipse.js.map +1 -0
- package/dist/webgl2-msdf-text.d.ts +84 -0
- package/dist/webgl2-msdf-text.d.ts.map +1 -0
- package/dist/webgl2-msdf-text.js +306 -0
- package/dist/webgl2-msdf-text.js.map +1 -0
- package/dist/webgl2-stroke.d.ts +52 -0
- package/dist/webgl2-stroke.d.ts.map +1 -0
- package/dist/webgl2-stroke.js +318 -0
- package/dist/webgl2-stroke.js.map +1 -0
- package/dist/webgl2-target.d.ts +311 -0
- package/dist/webgl2-target.d.ts.map +1 -0
- package/dist/webgl2-target.js +1368 -0
- package/dist/webgl2-target.js.map +1 -0
- package/dist/webgpu-detect.d.ts +30 -0
- package/dist/webgpu-detect.d.ts.map +1 -0
- package/dist/webgpu-detect.js +74 -0
- package/dist/webgpu-detect.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type Point } from "@oh-just-another/curve-mesh";
|
|
2
|
+
import type { Transform } from "@oh-just-another/types";
|
|
3
|
+
/**
|
|
4
|
+
* Loop-Blinn curve rendering for WebGL2Target. Owns the dedicated
|
|
5
|
+
* shader program (vertex (x, y, u, v, w) → fragment `(u² - v) * w`
|
|
6
|
+
* inside / outside test) and the buffer plumbing.
|
|
7
|
+
*
|
|
8
|
+
* Curves stay vector-perfect at any zoom (no facets at high zoom, no
|
|
9
|
+
* over-tessellated triangle counts at 1×), and packing all curve
|
|
10
|
+
* triangles into one buffer means one draw per `fill()` regardless of
|
|
11
|
+
* curve count.
|
|
12
|
+
*
|
|
13
|
+
* A curve triangle covers the convex hull of the three control points,
|
|
14
|
+
* and the fragment test discards the side that lies outside the
|
|
15
|
+
* parabola. So a curve that bulges outward from the polygon needs its
|
|
16
|
+
* triangle added on top of the polygon fill; a curve bulging inward
|
|
17
|
+
* needs the triangle subtracted. The sign field `w` in each vertex's UV
|
|
18
|
+
* encodes which side to keep.
|
|
19
|
+
*/
|
|
20
|
+
export interface CurveSegment {
|
|
21
|
+
readonly kind: "q" | "c";
|
|
22
|
+
readonly points: readonly Point[];
|
|
23
|
+
}
|
|
24
|
+
export declare class LoopBlinnCurvePipeline {
|
|
25
|
+
private readonly gl;
|
|
26
|
+
private readonly program;
|
|
27
|
+
private readonly vbo;
|
|
28
|
+
private readonly uvBuf;
|
|
29
|
+
private readonly uTransform;
|
|
30
|
+
private readonly uColor;
|
|
31
|
+
private readonly uOpacity;
|
|
32
|
+
private readonly aPos;
|
|
33
|
+
private readonly aUVW;
|
|
34
|
+
constructor(gl: WebGL2RenderingContext);
|
|
35
|
+
/**
|
|
36
|
+
* Triangulate every segment in `curves`, batch the triangles into one
|
|
37
|
+
* draw, and emit them through the Loop-Blinn fragment test. No-op when
|
|
38
|
+
* `curves` is empty.
|
|
39
|
+
*/
|
|
40
|
+
draw(curves: readonly CurveSegment[], color: readonly [number, number, number], opacity: number, transform: Transform, surfaceSize: {
|
|
41
|
+
width: number;
|
|
42
|
+
height: number;
|
|
43
|
+
}): void;
|
|
44
|
+
dispose(): void;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=webgl2-curve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webgl2-curve.d.ts","sourceRoot":"","sources":["../src/webgl2-curve.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,KAAK,EACX,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD;;;;;;;;;;;;;;;;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,CAAuB;IAClD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuB;IAChD,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;IAsCP,OAAO,IAAI,IAAI;CAKhB"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { cubicToTriangles, packCurveTriangles, quadraticToTriangle, } from "@oh-just-another/curve-mesh";
|
|
2
|
+
export class LoopBlinnCurvePipeline {
|
|
3
|
+
gl;
|
|
4
|
+
program;
|
|
5
|
+
vbo;
|
|
6
|
+
uvBuf;
|
|
7
|
+
uTransform;
|
|
8
|
+
uColor;
|
|
9
|
+
uOpacity;
|
|
10
|
+
aPos;
|
|
11
|
+
aUVW;
|
|
12
|
+
constructor(gl) {
|
|
13
|
+
this.gl = gl;
|
|
14
|
+
const vert = compile(gl, gl.VERTEX_SHADER, VERTEX_SRC);
|
|
15
|
+
const frag = compile(gl, gl.FRAGMENT_SHADER, FRAGMENT_SRC);
|
|
16
|
+
this.program = link(gl, vert, frag);
|
|
17
|
+
this.vbo = glReq(gl.createBuffer());
|
|
18
|
+
this.uvBuf = glReq(gl.createBuffer());
|
|
19
|
+
this.aPos = gl.getAttribLocation(this.program, "aPos");
|
|
20
|
+
this.aUVW = gl.getAttribLocation(this.program, "aUVW");
|
|
21
|
+
this.uTransform = glReq(gl.getUniformLocation(this.program, "uTransform"));
|
|
22
|
+
this.uColor = glReq(gl.getUniformLocation(this.program, "uColor"));
|
|
23
|
+
this.uOpacity = glReq(gl.getUniformLocation(this.program, "uOpacity"));
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Triangulate every segment in `curves`, batch the triangles into one
|
|
27
|
+
* draw, and emit them through the Loop-Blinn fragment test. No-op when
|
|
28
|
+
* `curves` is empty.
|
|
29
|
+
*/
|
|
30
|
+
draw(curves, color, opacity, transform, surfaceSize) {
|
|
31
|
+
if (curves.length === 0 || opacity <= 0)
|
|
32
|
+
return;
|
|
33
|
+
const triangles = [];
|
|
34
|
+
for (const seg of curves) {
|
|
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)
|
|
52
|
+
return;
|
|
53
|
+
const { positions, uvs } = packCurveTriangles(triangles);
|
|
54
|
+
const gl = this.gl;
|
|
55
|
+
gl.useProgram(this.program);
|
|
56
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
|
|
57
|
+
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.DYNAMIC_DRAW);
|
|
58
|
+
gl.enableVertexAttribArray(this.aPos);
|
|
59
|
+
gl.vertexAttribPointer(this.aPos, 2, gl.FLOAT, false, 0, 0);
|
|
60
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuf);
|
|
61
|
+
gl.bufferData(gl.ARRAY_BUFFER, uvs, gl.DYNAMIC_DRAW);
|
|
62
|
+
gl.enableVertexAttribArray(this.aUVW);
|
|
63
|
+
gl.vertexAttribPointer(this.aUVW, 3, gl.FLOAT, false, 0, 0);
|
|
64
|
+
gl.uniformMatrix3fv(this.uTransform, false, affineToClipMat3(transform, surfaceSize.width, surfaceSize.height));
|
|
65
|
+
gl.uniform3f(this.uColor, color[0], color[1], color[2]);
|
|
66
|
+
gl.uniform1f(this.uOpacity, opacity);
|
|
67
|
+
gl.drawArrays(gl.TRIANGLES, 0, positions.length / 2);
|
|
68
|
+
}
|
|
69
|
+
dispose() {
|
|
70
|
+
this.gl.deleteBuffer(this.vbo);
|
|
71
|
+
this.gl.deleteBuffer(this.uvBuf);
|
|
72
|
+
this.gl.deleteProgram(this.program);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const affineToClipMat3 = (t, w, h) => {
|
|
76
|
+
const sx = 2 / w;
|
|
77
|
+
const sy = -2 / h;
|
|
78
|
+
return new Float32Array([
|
|
79
|
+
t.a * sx, t.b * sy, 0,
|
|
80
|
+
t.c * sx, t.d * sy, 0,
|
|
81
|
+
t.e * sx - 1, t.f * sy + 1, 1,
|
|
82
|
+
]);
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Vertex shader passes through the Loop-Blinn (u, v, w) coordinates as
|
|
86
|
+
* a varying; the fragment shader runs the inside / outside test.
|
|
87
|
+
*/
|
|
88
|
+
const VERTEX_SRC = `#version 300 es
|
|
89
|
+
in vec2 aPos;
|
|
90
|
+
in vec3 aUVW;
|
|
91
|
+
uniform mat3 uTransform;
|
|
92
|
+
out vec3 vUVW;
|
|
93
|
+
void main() {
|
|
94
|
+
vec3 p = uTransform * vec3(aPos, 1.0);
|
|
95
|
+
gl_Position = vec4(p.xy, 0.0, 1.0);
|
|
96
|
+
vUVW = aUVW;
|
|
97
|
+
}`;
|
|
98
|
+
/**
|
|
99
|
+
* Loop-Blinn implicit Bezier test:
|
|
100
|
+
* procedural = u² - v
|
|
101
|
+
* discard if `procedural * w > 0` — `w` encodes which side of the
|
|
102
|
+
* parabola is the "filled" region. `fwidth(procedural)` gives the
|
|
103
|
+
* screen-pixel derivative used to feather the edge for AA.
|
|
104
|
+
*/
|
|
105
|
+
const FRAGMENT_SRC = `#version 300 es
|
|
106
|
+
precision mediump float;
|
|
107
|
+
uniform vec3 uColor;
|
|
108
|
+
uniform float uOpacity;
|
|
109
|
+
in vec3 vUVW;
|
|
110
|
+
out vec4 fragColor;
|
|
111
|
+
|
|
112
|
+
void main() {
|
|
113
|
+
float u = vUVW.x;
|
|
114
|
+
float v = vUVW.y;
|
|
115
|
+
float w = vUVW.z;
|
|
116
|
+
float p = u * u - v;
|
|
117
|
+
float dp = fwidth(p);
|
|
118
|
+
// Signed distance to the curve in procedural units; multiplied by w
|
|
119
|
+
// so the "outside" side discards regardless of curve orientation.
|
|
120
|
+
// smoothstep antialiases the edge over one screen pixel of
|
|
121
|
+
// procedural-space.
|
|
122
|
+
float coverage = smoothstep(dp, -dp, p * w);
|
|
123
|
+
if (coverage <= 0.0) discard;
|
|
124
|
+
// Premultiplied output to match the context's premultipliedAlpha
|
|
125
|
+
// contract + blendFunc(ONE, 1-SRC_ALPHA).
|
|
126
|
+
float a = coverage * uOpacity;
|
|
127
|
+
fragColor = vec4(uColor * a, a);
|
|
128
|
+
}`;
|
|
129
|
+
/**
|
|
130
|
+
* Asserts a WebGL resource handle is non-null. `gl.createBuffer` /
|
|
131
|
+
* `getUniformLocation` / `createShader` are typed non-null but return
|
|
132
|
+
* `null` on context loss; this surfaces that as a throw.
|
|
133
|
+
*/
|
|
134
|
+
const glReq = (v) => {
|
|
135
|
+
if (v === null)
|
|
136
|
+
throw new Error("packages/renderer-canvas: WebGL resource creation failed");
|
|
137
|
+
return v;
|
|
138
|
+
};
|
|
139
|
+
const compile = (gl, type, src) => {
|
|
140
|
+
const sh = glReq(gl.createShader(type));
|
|
141
|
+
gl.shaderSource(sh, src);
|
|
142
|
+
gl.compileShader(sh);
|
|
143
|
+
if (!gl.getShaderParameter(sh, gl.COMPILE_STATUS)) {
|
|
144
|
+
const log = gl.getShaderInfoLog(sh);
|
|
145
|
+
gl.deleteShader(sh);
|
|
146
|
+
throw new Error(`Loop-Blinn shader compile failed: ${log}`);
|
|
147
|
+
}
|
|
148
|
+
return sh;
|
|
149
|
+
};
|
|
150
|
+
const link = (gl, vert, frag) => {
|
|
151
|
+
const program = gl.createProgram();
|
|
152
|
+
gl.attachShader(program, vert);
|
|
153
|
+
gl.attachShader(program, frag);
|
|
154
|
+
gl.linkProgram(program);
|
|
155
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
156
|
+
const log = gl.getProgramInfoLog(program);
|
|
157
|
+
gl.deleteProgram(program);
|
|
158
|
+
throw new Error(`Loop-Blinn program link failed: ${log}`);
|
|
159
|
+
}
|
|
160
|
+
return program;
|
|
161
|
+
};
|
|
162
|
+
//# sourceMappingURL=webgl2-curve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webgl2-curve.js","sourceRoot":"","sources":["../src/webgl2-curve.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
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
|
+
export declare class EllipsePipeline {
|
|
30
|
+
private readonly gl;
|
|
31
|
+
private readonly program;
|
|
32
|
+
private readonly vbo;
|
|
33
|
+
private readonly aPos;
|
|
34
|
+
private readonly aLocal;
|
|
35
|
+
private readonly uTransform;
|
|
36
|
+
private readonly uColor;
|
|
37
|
+
private readonly uOpacity;
|
|
38
|
+
constructor(gl: WebGL2RenderingContext);
|
|
39
|
+
/**
|
|
40
|
+
* Draw a filled ellipse. `cx, cy` — centre in caller's coordinate
|
|
41
|
+
* system. `rx, ry` — radii. The caller's affine `transform` combines
|
|
42
|
+
* with the unit-square → bbox mapping into a single uniform matrix.
|
|
43
|
+
*
|
|
44
|
+
* Degenerate cases (`rx ≤ 0`, `ry ≤ 0`, `opacity ≤ 0`) early-return.
|
|
45
|
+
*/
|
|
46
|
+
draw(cx: number, cy: number, rx: number, ry: number, color: readonly [number, number, number], opacity: number, transform: Transform, surfaceSize: {
|
|
47
|
+
width: number;
|
|
48
|
+
height: number;
|
|
49
|
+
}): void;
|
|
50
|
+
dispose(): void;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=webgl2-ellipse.d.ts.map
|
|
@@ -0,0 +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;AAExD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,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,CAAuB;IAClD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuB;gBAEnB,EAAE,EAAE,sBAAsB;IAwBvD;;;;;;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;IAmCP,OAAO,IAAI,IAAI;CAIhB"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fragment-shader SDF ellipse pipeline for `WebGL2Target`. Renders an
|
|
3
|
+
* ellipse as a single textured quad (4 vertices, 2 triangles)
|
|
4
|
+
* regardless of radius — the fragment shader does an inside/outside
|
|
5
|
+
* test against the unit circle in normalised local coordinates.
|
|
6
|
+
*
|
|
7
|
+
* Vertex layout (static, interleaved):
|
|
8
|
+
* aPos aLocal
|
|
9
|
+
* 0,0 -1,-1
|
|
10
|
+
* 1,0 1,-1
|
|
11
|
+
* 0,1 -1, 1
|
|
12
|
+
* 1,1 1, 1
|
|
13
|
+
*
|
|
14
|
+
* `uTransform` maps `aPos` (unit square [0,1]²) through:
|
|
15
|
+
* 1. scale to ellipse bbox (2*rx, 2*ry)
|
|
16
|
+
* 2. translate to (cx-rx, cy-ry)
|
|
17
|
+
* 3. apply caller's world→screen affine
|
|
18
|
+
* 4. pixel→clip-space (NDC)
|
|
19
|
+
*
|
|
20
|
+
* The fragment shader gets `vLocal` interpolated across the quad:
|
|
21
|
+
* inside the ellipse → dot(vLocal, vLocal) < 1
|
|
22
|
+
* on the boundary → dot(vLocal, vLocal) = 1
|
|
23
|
+
* outside → dot(vLocal, vLocal) > 1
|
|
24
|
+
*
|
|
25
|
+
* `smoothstep(1+fwidth, 1-fwidth, r²)` gives sub-pixel AA at the
|
|
26
|
+
* boundary independent of zoom.
|
|
27
|
+
*/
|
|
28
|
+
export class EllipsePipeline {
|
|
29
|
+
gl;
|
|
30
|
+
program;
|
|
31
|
+
vbo;
|
|
32
|
+
aPos;
|
|
33
|
+
aLocal;
|
|
34
|
+
uTransform;
|
|
35
|
+
uColor;
|
|
36
|
+
uOpacity;
|
|
37
|
+
constructor(gl) {
|
|
38
|
+
this.gl = gl;
|
|
39
|
+
const vert = compile(gl, gl.VERTEX_SHADER, VERTEX_SRC);
|
|
40
|
+
const frag = compile(gl, gl.FRAGMENT_SHADER, FRAGMENT_SRC);
|
|
41
|
+
this.program = link(gl, vert, frag);
|
|
42
|
+
this.aPos = gl.getAttribLocation(this.program, "aPos");
|
|
43
|
+
this.aLocal = gl.getAttribLocation(this.program, "aLocal");
|
|
44
|
+
this.uTransform = glReq(gl.getUniformLocation(this.program, "uTransform"));
|
|
45
|
+
this.uColor = glReq(gl.getUniformLocation(this.program, "uColor"));
|
|
46
|
+
this.uOpacity = glReq(gl.getUniformLocation(this.program, "uOpacity"));
|
|
47
|
+
// Static interleaved buffer — never re-uploaded.
|
|
48
|
+
this.vbo = glReq(gl.createBuffer());
|
|
49
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
|
|
50
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
|
|
51
|
+
0, 0, -1, -1,
|
|
52
|
+
1, 0, 1, -1,
|
|
53
|
+
0, 1, -1, 1,
|
|
54
|
+
1, 1, 1, 1,
|
|
55
|
+
]), gl.STATIC_DRAW);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Draw a filled ellipse. `cx, cy` — centre in caller's coordinate
|
|
59
|
+
* system. `rx, ry` — radii. The caller's affine `transform` combines
|
|
60
|
+
* with the unit-square → bbox mapping into a single uniform matrix.
|
|
61
|
+
*
|
|
62
|
+
* Degenerate cases (`rx ≤ 0`, `ry ≤ 0`, `opacity ≤ 0`) early-return.
|
|
63
|
+
*/
|
|
64
|
+
draw(cx, cy, rx, ry, color, opacity, transform, surfaceSize) {
|
|
65
|
+
if (opacity <= 0 || rx <= 0 || ry <= 0)
|
|
66
|
+
return;
|
|
67
|
+
const gl = this.gl;
|
|
68
|
+
gl.useProgram(this.program);
|
|
69
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
|
|
70
|
+
gl.enableVertexAttribArray(this.aPos);
|
|
71
|
+
gl.vertexAttribPointer(this.aPos, 2, gl.FLOAT, false, 16, 0);
|
|
72
|
+
gl.enableVertexAttribArray(this.aLocal);
|
|
73
|
+
gl.vertexAttribPointer(this.aLocal, 2, gl.FLOAT, false, 16, 8);
|
|
74
|
+
const w = 2 * rx;
|
|
75
|
+
const h = 2 * ry;
|
|
76
|
+
const left = cx - rx;
|
|
77
|
+
const top = cy - ry;
|
|
78
|
+
const sx = 2 / surfaceSize.width;
|
|
79
|
+
const sy = -2 / surfaceSize.height;
|
|
80
|
+
// Combined matrix: (aPos.x, aPos.y) ∈ [0,1]² → clip-space NDC.
|
|
81
|
+
// Steps folded into one column-major mat3:
|
|
82
|
+
// scaleSq = (aPos.x * w, aPos.y * h)
|
|
83
|
+
// inWorld = transform · (scaleSq + (left, top))
|
|
84
|
+
// inClip = pixel→clip(inWorld)
|
|
85
|
+
const t = transform;
|
|
86
|
+
const mat = new Float32Array([
|
|
87
|
+
t.a * w * sx, t.b * w * sy, 0,
|
|
88
|
+
t.c * h * sx, t.d * h * sy, 0,
|
|
89
|
+
(t.a * left + t.c * top + t.e) * sx - 1,
|
|
90
|
+
(t.b * left + t.d * top + t.f) * sy + 1,
|
|
91
|
+
1,
|
|
92
|
+
]);
|
|
93
|
+
gl.uniformMatrix3fv(this.uTransform, false, mat);
|
|
94
|
+
gl.uniform3f(this.uColor, color[0], color[1], color[2]);
|
|
95
|
+
gl.uniform1f(this.uOpacity, opacity);
|
|
96
|
+
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
97
|
+
}
|
|
98
|
+
dispose() {
|
|
99
|
+
this.gl.deleteBuffer(this.vbo);
|
|
100
|
+
this.gl.deleteProgram(this.program);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const VERTEX_SRC = `#version 300 es
|
|
104
|
+
in vec2 aPos;
|
|
105
|
+
in vec2 aLocal;
|
|
106
|
+
uniform mat3 uTransform;
|
|
107
|
+
out vec2 vLocal;
|
|
108
|
+
void main() {
|
|
109
|
+
vec3 p = uTransform * vec3(aPos, 1.0);
|
|
110
|
+
gl_Position = vec4(p.xy, 0.0, 1.0);
|
|
111
|
+
vLocal = aLocal;
|
|
112
|
+
}`;
|
|
113
|
+
/**
|
|
114
|
+
* SDF circle test in normalised local space (-1..1 over ellipse bbox).
|
|
115
|
+
* r² = dot(vLocal, vLocal) — squared distance from centre.
|
|
116
|
+
* Inside circle: r² < 1. Outside: r² > 1. Boundary: r² = 1.
|
|
117
|
+
*
|
|
118
|
+
* `fwidth(r²)` gives the screen-space rate of change of r²; it sets the
|
|
119
|
+
* smoothstep width so the boundary stays a 1-screen-pixel band
|
|
120
|
+
* regardless of zoom.
|
|
121
|
+
*
|
|
122
|
+
* Output premultiplied (rgb·a, a) to match the context's
|
|
123
|
+
* `premultipliedAlpha: true` + `blendFunc(ONE, 1 - SRC_ALPHA)`.
|
|
124
|
+
*/
|
|
125
|
+
const FRAGMENT_SRC = `#version 300 es
|
|
126
|
+
precision mediump float;
|
|
127
|
+
uniform vec3 uColor;
|
|
128
|
+
uniform float uOpacity;
|
|
129
|
+
in vec2 vLocal;
|
|
130
|
+
out vec4 fragColor;
|
|
131
|
+
void main() {
|
|
132
|
+
float r2 = dot(vLocal, vLocal);
|
|
133
|
+
float dr = fwidth(r2);
|
|
134
|
+
float coverage = smoothstep(1.0 + dr, 1.0 - dr, r2);
|
|
135
|
+
if (coverage <= 0.0) discard;
|
|
136
|
+
float a = coverage * uOpacity;
|
|
137
|
+
fragColor = vec4(uColor * a, a);
|
|
138
|
+
}`;
|
|
139
|
+
/**
|
|
140
|
+
* Asserts a WebGL resource handle is non-null. Creation APIs are typed
|
|
141
|
+
* non-null but return `null` on context loss; surface that as a throw.
|
|
142
|
+
*/
|
|
143
|
+
const glReq = (v) => {
|
|
144
|
+
if (v === null)
|
|
145
|
+
throw new Error("packages/renderer-canvas: WebGL resource creation failed");
|
|
146
|
+
return v;
|
|
147
|
+
};
|
|
148
|
+
const compile = (gl, type, src) => {
|
|
149
|
+
const sh = glReq(gl.createShader(type));
|
|
150
|
+
gl.shaderSource(sh, src);
|
|
151
|
+
gl.compileShader(sh);
|
|
152
|
+
if (!gl.getShaderParameter(sh, gl.COMPILE_STATUS)) {
|
|
153
|
+
const log = gl.getShaderInfoLog(sh);
|
|
154
|
+
gl.deleteShader(sh);
|
|
155
|
+
throw new Error(`Ellipse shader compile failed: ${log}`);
|
|
156
|
+
}
|
|
157
|
+
return sh;
|
|
158
|
+
};
|
|
159
|
+
const link = (gl, vert, frag) => {
|
|
160
|
+
const program = gl.createProgram();
|
|
161
|
+
gl.attachShader(program, vert);
|
|
162
|
+
gl.attachShader(program, frag);
|
|
163
|
+
gl.linkProgram(program);
|
|
164
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
165
|
+
const log = gl.getProgramInfoLog(program);
|
|
166
|
+
gl.deleteProgram(program);
|
|
167
|
+
throw new Error(`Ellipse program link failed: ${log}`);
|
|
168
|
+
}
|
|
169
|
+
return program;
|
|
170
|
+
};
|
|
171
|
+
//# sourceMappingURL=webgl2-ellipse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webgl2-ellipse.js","sourceRoot":"","sources":["../src/webgl2-ellipse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { AtlasGlyph, GlyphAtlas } from "@oh-just-another/glyph-atlas";
|
|
2
|
+
import type { Transform } from "@oh-just-another/types";
|
|
3
|
+
/**
|
|
4
|
+
* MSDF text-rendering glue for WebGL2Target. Owns the dedicated shader
|
|
5
|
+
* program (vertex quad + median3 + smoothstep AA fragment), a reusable
|
|
6
|
+
* VBO, and the per-frame batching logic.
|
|
7
|
+
*
|
|
8
|
+
* The MSDF pipeline has its own shader, uniforms and vertex layout that
|
|
9
|
+
* share nothing with the solid / stroke / image programs, so it lives
|
|
10
|
+
* in its own module and is independently testable.
|
|
11
|
+
*
|
|
12
|
+
* One instance per WebGL2 context. `dispose()` releases the program and
|
|
13
|
+
* VBO.
|
|
14
|
+
*/
|
|
15
|
+
export interface Msdf2DTextStyle {
|
|
16
|
+
/** Premultiplied alpha 0..1. */
|
|
17
|
+
readonly opacity: number;
|
|
18
|
+
/** Fill colour as normalised RGB (0..1 per channel). */
|
|
19
|
+
readonly color: readonly [number, number, number];
|
|
20
|
+
/** Current world→screen affine. */
|
|
21
|
+
readonly transform: Transform;
|
|
22
|
+
}
|
|
23
|
+
export declare class MsdfTextPipeline {
|
|
24
|
+
private readonly gl;
|
|
25
|
+
private readonly program;
|
|
26
|
+
private readonly vbo;
|
|
27
|
+
private readonly uTransform;
|
|
28
|
+
private readonly uColor;
|
|
29
|
+
private readonly uOpacity;
|
|
30
|
+
private readonly uAtlasSize;
|
|
31
|
+
private readonly uPxRange;
|
|
32
|
+
private readonly uAtlas;
|
|
33
|
+
private readonly aPos;
|
|
34
|
+
private readonly aUV;
|
|
35
|
+
constructor(gl: WebGL2RenderingContext);
|
|
36
|
+
/**
|
|
37
|
+
* Build per-glyph quads for `text` starting at the cursor position
|
|
38
|
+
* `(x, y)` in world coordinates (top-left baseline convention —
|
|
39
|
+
* caller adjusts for textAlign / textBaseline upstream).
|
|
40
|
+
*
|
|
41
|
+
* Returns the screen-width of the rendered string in world units so
|
|
42
|
+
* callers can chain text or compute hit-test boxes. Returns 0 if the
|
|
43
|
+
* atlas couldn't bake one of the glyphs (atlas full) — the partial
|
|
44
|
+
* draw still lands.
|
|
45
|
+
*/
|
|
46
|
+
drawText(text: string, x: number, y: number, fontSize: number, atlas: GlyphAtlas, style: Msdf2DTextStyle, surfaceSize: {
|
|
47
|
+
width: number;
|
|
48
|
+
height: number;
|
|
49
|
+
},
|
|
50
|
+
/**
|
|
51
|
+
* Horizontal alignment factor: 0 = left (cursor at `x`), 0.5 =
|
|
52
|
+
* centre, 1 = right. Applied as a single world-space x shift after
|
|
53
|
+
* measuring the run, so there's no separate width-measuring walk
|
|
54
|
+
* over the atlas.
|
|
55
|
+
*/
|
|
56
|
+
alignFactor?: number,
|
|
57
|
+
/** Embedded font id (0=sans, 1=serif, 2=mono); selects atlas glyphs. */
|
|
58
|
+
fontId?: number): number;
|
|
59
|
+
dispose(): void;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Pure-math helper: compute the screen-space rect + atlas UV rect for
|
|
63
|
+
* one glyph. Exported so tests can verify the geometry without booting
|
|
64
|
+
* a real WebGL2 context.
|
|
65
|
+
*
|
|
66
|
+
* Returns `{ left, top, right, bottom, u0, v0, u1, v1 }` in screen
|
|
67
|
+
* pixels / normalised UVs. Caller packs the six vertices into a vertex
|
|
68
|
+
* buffer.
|
|
69
|
+
*/
|
|
70
|
+
export declare const glyphQuadGeometry: (g: AtlasGlyph, cursorX: number, cursorY: number, fontSize: number, atlas: {
|
|
71
|
+
atlasSize: number;
|
|
72
|
+
tileSize: number;
|
|
73
|
+
range: number;
|
|
74
|
+
}) => {
|
|
75
|
+
left: number;
|
|
76
|
+
top: number;
|
|
77
|
+
right: number;
|
|
78
|
+
bottom: number;
|
|
79
|
+
u0: number;
|
|
80
|
+
v0: number;
|
|
81
|
+
u1: number;
|
|
82
|
+
v1: number;
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=webgl2-msdf-text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webgl2-msdf-text.d.ts","sourceRoot":"","sources":["../src/webgl2-msdf-text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,eAAe;IAC9B,gCAAgC;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAClD,mCAAmC;IACnC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;CAC/B;AAED,qBAAa,gBAAgB;IAYf,OAAO,CAAC,QAAQ,CAAC,EAAE;IAX/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAc;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAClD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuB;IAChD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAClD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuB;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;gBAEA,EAAE,EAAE,sBAAsB;IAevD;;;;;;;;;OASG;IACH,QAAQ,CACN,IAAI,EAAE,MAAM,EACZ,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,eAAe,EACtB,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IAC9C;;;;;OAKG;IACH,WAAW,SAAI;IACf,wEAAwE;IACxE,MAAM,SAAI,GACT,MAAM;IAmET,OAAO,IAAI,IAAI;CAIhB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,GAC5B,GAAG,UAAU,EACb,SAAS,MAAM,EACf,SAAS,MAAM,EACf,UAAU,MAAM,EAChB,OAAO;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,KAC5D;IACD,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CA2CZ,CAAC"}
|