q5 4.3.0 → 4.4.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/deno.json +1 -1
- package/package.json +1 -1
- package/q5.d.ts +50 -16
- package/q5.js +437 -109
- package/q5.min.js +2 -2
package/q5.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* q5.js
|
|
3
|
-
* @version 4.
|
|
3
|
+
* @version 4.4
|
|
4
4
|
* @author quinton-ashley
|
|
5
5
|
* @contributors evanalulu, Tezumie, ormaq, Dukemz, LingDong-
|
|
6
6
|
* @license LGPL-3.0
|
|
@@ -490,7 +490,7 @@ if (typeof window == 'object') {
|
|
|
490
490
|
window.addEventListener('pagehide', cleanup);
|
|
491
491
|
} else global.window = 0;
|
|
492
492
|
|
|
493
|
-
Q5.version = Q5.VERSION = '4.
|
|
493
|
+
Q5.version = Q5.VERSION = '4.4';
|
|
494
494
|
|
|
495
495
|
if (typeof document == 'object') {
|
|
496
496
|
document.addEventListener('DOMContentLoaded', () => {
|
|
@@ -6153,11 +6153,16 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
6153
6153
|
$.pop();
|
|
6154
6154
|
} else {
|
|
6155
6155
|
addColor(r, g, b, a);
|
|
6156
|
-
let
|
|
6156
|
+
let ci = colorIndex,
|
|
6157
|
+
lx = -c.hw,
|
|
6157
6158
|
rx = c.hw,
|
|
6158
6159
|
ty = -c.hh,
|
|
6159
6160
|
by = c.hh;
|
|
6160
|
-
|
|
6161
|
+
addVert(lx, ty, ci, 0);
|
|
6162
|
+
addVert(rx, ty, ci, 0);
|
|
6163
|
+
addVert(lx, by, ci, 0);
|
|
6164
|
+
addVert(rx, by, ci, 0);
|
|
6165
|
+
drawStack.push(1, 4); // always use the default shapes pipeline
|
|
6161
6166
|
}
|
|
6162
6167
|
};
|
|
6163
6168
|
|
|
@@ -6197,7 +6202,15 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
6197
6202
|
shouldClear = false;
|
|
6198
6203
|
};
|
|
6199
6204
|
|
|
6200
|
-
let transformsBuffer,
|
|
6205
|
+
let transformsBuffer,
|
|
6206
|
+
colorsBuffer,
|
|
6207
|
+
shapesVertBuff,
|
|
6208
|
+
imgVertBuff,
|
|
6209
|
+
polygonVertBuff,
|
|
6210
|
+
polyPtsBuffer,
|
|
6211
|
+
polyPtsBindGroup,
|
|
6212
|
+
charBuffer,
|
|
6213
|
+
textBuffer;
|
|
6201
6214
|
let mainBindGroup, lastTransformsBuffer, lastColorsBuffer;
|
|
6202
6215
|
|
|
6203
6216
|
$._render = () => {
|
|
@@ -6276,6 +6289,37 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
6276
6289
|
|
|
6277
6290
|
// prepare to render images and videos
|
|
6278
6291
|
|
|
6292
|
+
if (polygonVertIdx) {
|
|
6293
|
+
let polygonVertSize = polygonVertIdx * 4; // 4 bytes per float
|
|
6294
|
+
if (!polygonVertBuff || polygonVertBuff.size < polygonVertSize) {
|
|
6295
|
+
if (polygonVertBuff) polygonVertBuff.destroy();
|
|
6296
|
+
polygonVertBuff = Q5.device.createBuffer({
|
|
6297
|
+
size: polygonVertSize * 2,
|
|
6298
|
+
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
|
|
6299
|
+
});
|
|
6300
|
+
}
|
|
6301
|
+
|
|
6302
|
+
Q5.device.queue.writeBuffer(polygonVertBuff, 0, polygonVertStack.subarray(0, polygonVertIdx));
|
|
6303
|
+
$._pass.setVertexBuffer(2, polygonVertBuff);
|
|
6304
|
+
|
|
6305
|
+
if (polyPtsIdx) {
|
|
6306
|
+
let polyPtsSize = polyPtsIdx * 4;
|
|
6307
|
+
if (!polyPtsBuffer || polyPtsBuffer.size < polyPtsSize) {
|
|
6308
|
+
if (polyPtsBuffer) polyPtsBuffer.destroy();
|
|
6309
|
+
polyPtsBuffer = Q5.device.createBuffer({
|
|
6310
|
+
size: Math.max(polyPtsSize * 2, 64),
|
|
6311
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
|
|
6312
|
+
});
|
|
6313
|
+
}
|
|
6314
|
+
Q5.device.queue.writeBuffer(polyPtsBuffer, 0, polyPtsStack.subarray(0, polyPtsIdx));
|
|
6315
|
+
|
|
6316
|
+
polyPtsBindGroup = Q5.device.createBindGroup({
|
|
6317
|
+
layout: polygonBindGroupLayout,
|
|
6318
|
+
entries: [{ binding: 0, resource: { buffer: polyPtsBuffer } }]
|
|
6319
|
+
});
|
|
6320
|
+
}
|
|
6321
|
+
}
|
|
6322
|
+
|
|
6279
6323
|
if (imgVertIdx) {
|
|
6280
6324
|
$._pass.setPipeline($._pipelines[2]); // images pipeline
|
|
6281
6325
|
|
|
@@ -6374,6 +6418,7 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
6374
6418
|
let drawVertOffset = 0,
|
|
6375
6419
|
imageVertOffset = 0,
|
|
6376
6420
|
textCharOffset = 0,
|
|
6421
|
+
polygonVertOffset = 0,
|
|
6377
6422
|
rectIdx = 0,
|
|
6378
6423
|
ellipseIdx = 0,
|
|
6379
6424
|
curPipelineIndex = -1;
|
|
@@ -6401,12 +6446,18 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
6401
6446
|
} else if (curPipelineIndex == 6) {
|
|
6402
6447
|
pass.setIndexBuffer(ellipseIndexBuffer, 'uint16');
|
|
6403
6448
|
pass.setBindGroup(1, ellipseBindGroup);
|
|
6449
|
+
} else if (curPipelineIndex == 7) {
|
|
6450
|
+
pass.setBindGroup(1, polyPtsBindGroup);
|
|
6404
6451
|
} else if ($._customBindHandlers[curPipelineIndex]) {
|
|
6405
6452
|
$._customBindHandlers[curPipelineIndex](pass);
|
|
6406
6453
|
}
|
|
6407
6454
|
}
|
|
6408
6455
|
|
|
6409
|
-
if (curPipelineIndex ==
|
|
6456
|
+
if (curPipelineIndex == 7) {
|
|
6457
|
+
// draw a polygon
|
|
6458
|
+
pass.draw(v, 1, polygonVertOffset, 0);
|
|
6459
|
+
polygonVertOffset += v;
|
|
6460
|
+
} else if (curPipelineIndex == 6) {
|
|
6410
6461
|
// draw an ellipse
|
|
6411
6462
|
pass.drawIndexed(18, v, 0, 0, ellipseIdx);
|
|
6412
6463
|
ellipseIdx += v;
|
|
@@ -6483,6 +6534,8 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
6483
6534
|
|
|
6484
6535
|
// reset
|
|
6485
6536
|
shapesVertIdx = 0;
|
|
6537
|
+
polygonVertIdx = 0;
|
|
6538
|
+
polyPtsIdx = 0;
|
|
6486
6539
|
imgVertIdx = 0;
|
|
6487
6540
|
// Remove video frames without creating new array
|
|
6488
6541
|
if (vidFrames > 0) {
|
|
@@ -6633,19 +6686,16 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6633
6686
|
};
|
|
6634
6687
|
|
|
6635
6688
|
$.vertex = (x, y) => {
|
|
6636
|
-
|
|
6637
|
-
sv.push(x, y, fillIdx, matrixIdx);
|
|
6689
|
+
sv.push(x, y, fillIdx);
|
|
6638
6690
|
shapeVertCount++;
|
|
6639
6691
|
};
|
|
6640
6692
|
|
|
6641
6693
|
$.curveVertex = (x, y) => {
|
|
6642
|
-
if (matrixDirty) saveMatrix();
|
|
6643
6694
|
curveVertices.push({ x, y });
|
|
6644
6695
|
};
|
|
6645
6696
|
|
|
6646
6697
|
$.bezierVertex = function (cx1, cy1, cx2, cy2, x, y) {
|
|
6647
6698
|
if (shapeVertCount === 0) throw new Error('Shape needs a vertex()');
|
|
6648
|
-
if (matrixDirty) saveMatrix();
|
|
6649
6699
|
|
|
6650
6700
|
// Get the last vertex as the starting point (P₀)
|
|
6651
6701
|
let prevIndex = (shapeVertCount - 1) * 4;
|
|
@@ -6681,136 +6731,413 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6681
6731
|
vy = mt3 * startY + 3 * mt2 * t * cy1 + 3 * mt * t2 * cy2 + t3 * y;
|
|
6682
6732
|
}
|
|
6683
6733
|
|
|
6684
|
-
sv.push(vx, vy, fillIdx
|
|
6734
|
+
sv.push(vx, vy, fillIdx);
|
|
6685
6735
|
shapeVertCount++;
|
|
6686
6736
|
}
|
|
6687
6737
|
};
|
|
6688
6738
|
|
|
6689
6739
|
$.quadraticVertex = (cx, cy, x, y) => $.bezierVertex(cx, cy, x, y);
|
|
6690
6740
|
|
|
6741
|
+
function addQuad(x1, y1, x2, y2, x3, y3, x4, y4, ci, ti) {
|
|
6742
|
+
addVert(x1, y1, ci, ti); // v0
|
|
6743
|
+
addVert(x2, y2, ci, ti); // v1
|
|
6744
|
+
addVert(x4, y4, ci, ti); // v3
|
|
6745
|
+
addVert(x3, y3, ci, ti); // v2
|
|
6746
|
+
drawStack.push(shapesPL, 4);
|
|
6747
|
+
}
|
|
6748
|
+
|
|
6749
|
+
$.plane = (x, y, w, h) => {
|
|
6750
|
+
h ??= w;
|
|
6751
|
+
let [l, r, t, b] = calcBox(x, y, w, h, 'center');
|
|
6752
|
+
if (matrixDirty) saveMatrix();
|
|
6753
|
+
addQuad(l, t, r, t, r, b, l, b, fillIdx, matrixIdx);
|
|
6754
|
+
};
|
|
6755
|
+
|
|
6756
|
+
$.curve = (x1, y1, x2, y2, x3, y3, x4, y4) => {
|
|
6757
|
+
$.beginShape();
|
|
6758
|
+
$.curveVertex(x1, y1);
|
|
6759
|
+
$.curveVertex(x2, y2);
|
|
6760
|
+
$.curveVertex(x3, y3);
|
|
6761
|
+
$.curveVertex(x4, y4);
|
|
6762
|
+
$.endShape();
|
|
6763
|
+
};
|
|
6764
|
+
|
|
6765
|
+
$.bezier = (x1, y1, x2, y2, x3, y3, x4, y4) => {
|
|
6766
|
+
$.beginShape();
|
|
6767
|
+
$.vertex(x1, y1);
|
|
6768
|
+
$.bezierVertex(x2, y2, x3, y3, x4, y4);
|
|
6769
|
+
$.endShape();
|
|
6770
|
+
};
|
|
6771
|
+
|
|
6772
|
+
/* POLYGONS */
|
|
6773
|
+
|
|
6774
|
+
let polygonPL = 7;
|
|
6775
|
+
|
|
6776
|
+
$._polygonShaderCode =
|
|
6777
|
+
$._baseShaderCode +
|
|
6778
|
+
/* wgsl */ `
|
|
6779
|
+
struct VertexParams {
|
|
6780
|
+
@builtin(vertex_index) vertexIndex : u32,
|
|
6781
|
+
@location(0) pos: vec2f,
|
|
6782
|
+
@location(1) polyStart: f32,
|
|
6783
|
+
@location(2) polyCount: f32,
|
|
6784
|
+
@location(3) fillIndex: f32,
|
|
6785
|
+
@location(4) strokeIndex: f32,
|
|
6786
|
+
@location(5) strokeWeight: f32,
|
|
6787
|
+
@location(6) matrixIndex: f32
|
|
6788
|
+
}
|
|
6789
|
+
|
|
6790
|
+
struct FragParams {
|
|
6791
|
+
@builtin(position) position: vec4f,
|
|
6792
|
+
@location(0) localPos: vec2f,
|
|
6793
|
+
@location(1) @interpolate(flat) polyStart: u32,
|
|
6794
|
+
@location(2) @interpolate(flat) polyCount: u32,
|
|
6795
|
+
@location(3) @interpolate(flat) fillIndex: f32,
|
|
6796
|
+
@location(4) @interpolate(flat) strokeIndex: f32,
|
|
6797
|
+
@location(5) @interpolate(flat) strokeWeight: f32,
|
|
6798
|
+
@location(6) @interpolate(flat) isClosed: f32
|
|
6799
|
+
}
|
|
6800
|
+
|
|
6801
|
+
@group(0) @binding(0) var<uniform> q: Q5;
|
|
6802
|
+
@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;
|
|
6803
|
+
@group(0) @binding(2) var<storage> colors : array<vec4f>;
|
|
6804
|
+
|
|
6805
|
+
@group(1) @binding(0) var<storage, read> polyPts: array<vec4f>;
|
|
6806
|
+
|
|
6807
|
+
fn transformVertex(pos: vec2f, matrixIndex: f32) -> vec4f {
|
|
6808
|
+
var vert = vec4f(pos, 0.0, 1.0);
|
|
6809
|
+
vert = transforms[i32(matrixIndex)] * vert;
|
|
6810
|
+
vert.x /= q.halfWidth;
|
|
6811
|
+
vert.y /= q.halfHeight;
|
|
6812
|
+
return vert;
|
|
6813
|
+
}
|
|
6814
|
+
|
|
6815
|
+
fn getPolyColor(p: vec2f, start: u32, count: u32, fIdx: f32) -> vec4f {
|
|
6816
|
+
let uniformColor = colors[i32(fIdx)];
|
|
6817
|
+
if (uniformColor.a == 0.0) {
|
|
6818
|
+
return uniformColor;
|
|
6819
|
+
}
|
|
6820
|
+
|
|
6821
|
+
var sumWeight: f32 = 0.0;
|
|
6822
|
+
var sumColor = vec4f(0.0);
|
|
6823
|
+
for (var i: u32 = 0u; i < count; i = i + 1u) {
|
|
6824
|
+
let pt = polyPts[start + i];
|
|
6825
|
+
let d = distance(p, pt.xy);
|
|
6826
|
+
if (d < 0.1) {
|
|
6827
|
+
return colors[i32(pt.z)];
|
|
6828
|
+
}
|
|
6829
|
+
let w = 1.0 / (d * d * d);
|
|
6830
|
+
sumWeight += w;
|
|
6831
|
+
sumColor += colors[i32(pt.z)] * w;
|
|
6832
|
+
}
|
|
6833
|
+
return sumColor / sumWeight;
|
|
6834
|
+
}
|
|
6835
|
+
|
|
6836
|
+
fn sdPolygon(p: vec2f, start: u32, count: u32, isClosed: f32) -> f32 {
|
|
6837
|
+
var d: f32 = dot(p - polyPts[start].xy, p - polyPts[start].xy);
|
|
6838
|
+
var s: f32 = 1.0;
|
|
6839
|
+
var j: u32 = count - 1u;
|
|
6840
|
+
for (var i: u32 = 0u; i < count; i = i + 1u) {
|
|
6841
|
+
let vi = polyPts[start + i].xy;
|
|
6842
|
+
let vj = polyPts[start + j].xy;
|
|
6843
|
+
let e = vj - vi;
|
|
6844
|
+
let w = p - vi;
|
|
6845
|
+
let b = w - e * clamp(dot(w, e) / dot(e, e), 0.0, 1.0);
|
|
6846
|
+
let bSq = dot(b, b);
|
|
6847
|
+
if (isClosed != 0.0 || i != 0u) {
|
|
6848
|
+
if (bSq < d) { d = bSq; }
|
|
6849
|
+
}
|
|
6850
|
+
|
|
6851
|
+
let condX = p.y >= vi.y;
|
|
6852
|
+
let condY = p.y < vj.y;
|
|
6853
|
+
let condZ = e.x * w.y > e.y * w.x;
|
|
6854
|
+
if ((condX && condY && condZ) || (!condX && !condY && !condZ)) {
|
|
6855
|
+
s = -s;
|
|
6856
|
+
}
|
|
6857
|
+
j = i;
|
|
6858
|
+
}
|
|
6859
|
+
if (isClosed == 0.0) {
|
|
6860
|
+
return sqrt(d);
|
|
6861
|
+
}
|
|
6862
|
+
return s * sqrt(d);
|
|
6863
|
+
}
|
|
6864
|
+
|
|
6865
|
+
@vertex
|
|
6866
|
+
fn vertexMain(v: VertexParams) -> FragParams {
|
|
6867
|
+
var f: FragParams;
|
|
6868
|
+
|
|
6869
|
+
// manually apply transform
|
|
6870
|
+
var vert = vec4f(v.pos, 0.0, 1.0);
|
|
6871
|
+
vert = transforms[i32(v.matrixIndex)] * vert;
|
|
6872
|
+
vert.x /= q.halfWidth;
|
|
6873
|
+
vert.y /= q.halfHeight;
|
|
6874
|
+
|
|
6875
|
+
f.position = vert;
|
|
6876
|
+
f.localPos = v.pos;
|
|
6877
|
+
f.polyStart = u32(v.polyStart + 0.1);
|
|
6878
|
+
f.polyCount = u32(abs(v.polyCount) + 0.1);
|
|
6879
|
+
f.isClosed = step(0.0, v.polyCount);
|
|
6880
|
+
f.fillIndex = v.fillIndex;
|
|
6881
|
+
f.strokeIndex = v.strokeIndex;
|
|
6882
|
+
f.strokeWeight = v.strokeWeight;
|
|
6883
|
+
return f;
|
|
6884
|
+
}
|
|
6885
|
+
|
|
6886
|
+
@fragment
|
|
6887
|
+
fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
6888
|
+
let dist = sdPolygon(f.localPos, f.polyStart, f.polyCount, f.isClosed);
|
|
6889
|
+
let fill = getPolyColor(f.localPos, f.polyStart, f.polyCount, f.fillIndex);
|
|
6890
|
+
let stroke = colors[i32(f.strokeIndex)];
|
|
6891
|
+
|
|
6892
|
+
let dpdx_d = dpdx(dist);
|
|
6893
|
+
let dpdy_d = dpdy(dist);
|
|
6894
|
+
let distGrad = sqrt(dpdx_d * dpdx_d + dpdy_d * dpdy_d);
|
|
6895
|
+
let aa = clamp(distGrad * 1.5, 0.001, 2.0);
|
|
6896
|
+
|
|
6897
|
+
let halfStroke = f.strokeWeight * 0.5;
|
|
6898
|
+
|
|
6899
|
+
var outFragColor: vec4f;
|
|
6900
|
+
|
|
6901
|
+
if (fill.a != 0.0 && f.strokeWeight == 0.0) {
|
|
6902
|
+
let fillAlpha = 1.0 - smoothstep(-aa, aa, dist);
|
|
6903
|
+
if (fillAlpha <= 0.0) { discard; }
|
|
6904
|
+
outFragColor = vec4f(fill.rgb, fill.a * fillAlpha);
|
|
6905
|
+
} else if (fill.a != 0.0) {
|
|
6906
|
+
let fillAlpha = 1.0 - smoothstep(-aa, aa, dist);
|
|
6907
|
+
let strokeDist = abs(dist) - halfStroke;
|
|
6908
|
+
let strokeAlphaMask = 1.0 - smoothstep(-aa, aa, strokeDist);
|
|
6909
|
+
|
|
6910
|
+
if (fillAlpha <= 0.0 && strokeAlphaMask <= 0.0) { discard; }
|
|
6911
|
+
|
|
6912
|
+
let sA = stroke.a * strokeAlphaMask;
|
|
6913
|
+
let fA = fill.a * fillAlpha;
|
|
6914
|
+
let outAlpha = sA + fA * (1.0 - sA);
|
|
6915
|
+
let outCol = stroke.rgb * sA + fill.rgb * fA * (1.0 - sA);
|
|
6916
|
+
outFragColor = vec4f(outCol / max(outAlpha, 1e-5), outAlpha);
|
|
6917
|
+
} else {
|
|
6918
|
+
let strokeDist = abs(dist) - halfStroke;
|
|
6919
|
+
let strokeAlpha = 1.0 - smoothstep(-aa, aa, strokeDist);
|
|
6920
|
+
|
|
6921
|
+
if (strokeAlpha <= 0.0) { discard; }
|
|
6922
|
+
outFragColor = vec4f(stroke.rgb, stroke.a * strokeAlpha);
|
|
6923
|
+
}
|
|
6924
|
+
return outFragColor;
|
|
6925
|
+
}
|
|
6926
|
+
`;
|
|
6927
|
+
|
|
6928
|
+
let polygonShader = Q5.device.createShaderModule({
|
|
6929
|
+
label: 'polygonShader',
|
|
6930
|
+
code: $._polygonShaderCode
|
|
6931
|
+
});
|
|
6932
|
+
|
|
6933
|
+
let polygonVertStack = new Float32Array($._isGraphics ? 1000 : 1e7),
|
|
6934
|
+
polygonVertIdx = 0;
|
|
6935
|
+
let polyPtsStack = new Float32Array($._isGraphics ? 1000 : 1e7),
|
|
6936
|
+
polyPtsIdx = 0;
|
|
6937
|
+
|
|
6938
|
+
let polygonVertBuffLayout = {
|
|
6939
|
+
arrayStride: 32, // 8 floats * 4 bytes
|
|
6940
|
+
attributes: [
|
|
6941
|
+
{ format: 'float32x2', offset: 0, shaderLocation: 0 },
|
|
6942
|
+
{ format: 'float32', offset: 8, shaderLocation: 1 },
|
|
6943
|
+
{ format: 'float32', offset: 12, shaderLocation: 2 },
|
|
6944
|
+
{ format: 'float32', offset: 16, shaderLocation: 3 },
|
|
6945
|
+
{ format: 'float32', offset: 20, shaderLocation: 4 },
|
|
6946
|
+
{ format: 'float32', offset: 24, shaderLocation: 5 },
|
|
6947
|
+
{ format: 'float32', offset: 28, shaderLocation: 6 }
|
|
6948
|
+
]
|
|
6949
|
+
};
|
|
6950
|
+
|
|
6951
|
+
let polygonBindGroupLayout = Q5.device.createBindGroupLayout({
|
|
6952
|
+
entries: [{ binding: 0, visibility: GPUShaderStage.FRAGMENT, buffer: { type: 'read-only-storage' } }]
|
|
6953
|
+
});
|
|
6954
|
+
|
|
6955
|
+
let polygonPipelineLayout = Q5.device.createPipelineLayout({
|
|
6956
|
+
label: 'polygonPipelineLayout',
|
|
6957
|
+
bindGroupLayouts: [mainLayout, polygonBindGroupLayout]
|
|
6958
|
+
});
|
|
6959
|
+
|
|
6960
|
+
$._pipelineConfigs[7] = {
|
|
6961
|
+
label: 'polygonPipeline',
|
|
6962
|
+
layout: polygonPipelineLayout,
|
|
6963
|
+
vertex: { module: polygonShader, entryPoint: 'vertexMain', buffers: [null, null, polygonVertBuffLayout] },
|
|
6964
|
+
fragment: {
|
|
6965
|
+
module: polygonShader,
|
|
6966
|
+
entryPoint: 'fragMain',
|
|
6967
|
+
targets: [{ format: 'bgra8unorm', blend: $.blendConfigs['source-over'] }]
|
|
6968
|
+
},
|
|
6969
|
+
primitive: { topology: 'triangle-list' },
|
|
6970
|
+
multisample: { count: 4 }
|
|
6971
|
+
};
|
|
6972
|
+
$._pipelines[7] = Q5.device.createRenderPipeline($._pipelineConfigs[7]);
|
|
6973
|
+
|
|
6974
|
+
const addPolygonVert = (x, y, start, count, fIdx, sIdx, sWeight, mIdx) => {
|
|
6975
|
+
let v = polygonVertStack,
|
|
6976
|
+
i = polygonVertIdx;
|
|
6977
|
+
v[i++] = x;
|
|
6978
|
+
v[i++] = y;
|
|
6979
|
+
v[i++] = start;
|
|
6980
|
+
v[i++] = count;
|
|
6981
|
+
v[i++] = fIdx;
|
|
6982
|
+
v[i++] = sIdx;
|
|
6983
|
+
v[i++] = sWeight;
|
|
6984
|
+
v[i++] = mIdx;
|
|
6985
|
+
polygonVertIdx = i;
|
|
6986
|
+
};
|
|
6987
|
+
|
|
6691
6988
|
$.endShape = (close) => {
|
|
6692
6989
|
if (curveVertices.length > 0) {
|
|
6693
|
-
// duplicate start and end points if necessary
|
|
6694
6990
|
let points = [...curveVertices];
|
|
6695
6991
|
if (points.length < 4) {
|
|
6696
|
-
// duplicate first and last points
|
|
6697
6992
|
while (points.length < 4) {
|
|
6698
6993
|
points.unshift(points[0]);
|
|
6699
6994
|
points.push(points[points.length - 1]);
|
|
6700
6995
|
}
|
|
6701
6996
|
}
|
|
6702
|
-
|
|
6703
|
-
// Use curveSegments to determine step size
|
|
6704
6997
|
let step = 1 / curveSegments;
|
|
6705
|
-
|
|
6706
|
-
// calculate catmull-rom spline curve points
|
|
6707
6998
|
for (let i = 0; i < points.length - 3; i++) {
|
|
6708
|
-
let p0 = points[i]
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
for (let
|
|
6714
|
-
let
|
|
6715
|
-
let
|
|
6716
|
-
|
|
6999
|
+
let p0 = points[i],
|
|
7000
|
+
p1 = points[i + 1],
|
|
7001
|
+
p2 = points[i + 2],
|
|
7002
|
+
p3 = points[i + 3];
|
|
7003
|
+
let startT = i === 0 ? 0 : 1;
|
|
7004
|
+
for (let j = startT; j <= curveSegments; j++) {
|
|
7005
|
+
let t = j / curveSegments;
|
|
7006
|
+
let t2 = t * t,
|
|
7007
|
+
t3 = t2 * t;
|
|
6717
7008
|
let x =
|
|
6718
7009
|
0.5 *
|
|
6719
7010
|
(2 * p1.x +
|
|
6720
7011
|
(-p0.x + p2.x) * t +
|
|
6721
7012
|
(2 * p0.x - 5 * p1.x + 4 * p2.x - p3.x) * t2 +
|
|
6722
7013
|
(-p0.x + 3 * p1.x - 3 * p2.x + p3.x) * t3);
|
|
6723
|
-
|
|
6724
7014
|
let y =
|
|
6725
7015
|
0.5 *
|
|
6726
7016
|
(2 * p1.y +
|
|
6727
7017
|
(-p0.y + p2.y) * t +
|
|
6728
7018
|
(2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * t2 +
|
|
6729
7019
|
(-p0.y + 3 * p1.y - 3 * p2.y + p3.y) * t3);
|
|
6730
|
-
|
|
6731
|
-
sv.push(x, y, fillIdx, matrixIdx);
|
|
7020
|
+
sv.push(x, y, fillIdx);
|
|
6732
7021
|
shapeVertCount++;
|
|
6733
7022
|
}
|
|
6734
7023
|
}
|
|
6735
7024
|
}
|
|
6736
7025
|
|
|
6737
7026
|
if (!shapeVertCount) return;
|
|
6738
|
-
if (shapeVertCount == 1)
|
|
6739
|
-
|
|
6740
|
-
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
if (firstX !== lastX || firstY !== lastY) {
|
|
6752
|
-
sv.push(firstX, firstY, sv[firstIndex + 2], sv[firstIndex + 3]);
|
|
6753
|
-
shapeVertCount++;
|
|
6754
|
-
}
|
|
7027
|
+
if (shapeVertCount == 1) {
|
|
7028
|
+
$.point(sv[0], sv[1]);
|
|
7029
|
+
shapeVertCount = 0;
|
|
7030
|
+
sv = [];
|
|
7031
|
+
curveVertices = [];
|
|
7032
|
+
return;
|
|
7033
|
+
}
|
|
7034
|
+
if (shapeVertCount == 2) {
|
|
7035
|
+
$.line(sv[0], sv[1], sv[3], sv[4]);
|
|
7036
|
+
shapeVertCount = 0;
|
|
7037
|
+
sv = [];
|
|
7038
|
+
curveVertices = [];
|
|
7039
|
+
return;
|
|
6755
7040
|
}
|
|
6756
7041
|
|
|
6757
|
-
if (
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
addVert(sv[v2], sv[v2 + 1], sv[v2 + 2], sv[v2 + 3]);
|
|
6775
|
-
}
|
|
6776
|
-
drawStack.push(shapesPL, (shapeVertCount - 2) * 3);
|
|
6777
|
-
}
|
|
7042
|
+
if (matrixDirty) saveMatrix();
|
|
7043
|
+
let ti = matrixIdx;
|
|
7044
|
+
|
|
7045
|
+
let isAutoClosed = false;
|
|
7046
|
+
let isClosedPath = false;
|
|
7047
|
+
let firstX = sv[0],
|
|
7048
|
+
firstY = sv[1];
|
|
7049
|
+
let lastX = sv[(shapeVertCount - 1) * 3],
|
|
7050
|
+
lastY = sv[(shapeVertCount - 1) * 3 + 1];
|
|
7051
|
+
|
|
7052
|
+
if (firstX === lastX && firstY === lastY) {
|
|
7053
|
+
isClosedPath = true;
|
|
7054
|
+
} else if (close || doFill) {
|
|
7055
|
+
sv.push(firstX, firstY, sv[2]);
|
|
7056
|
+
shapeVertCount++;
|
|
7057
|
+
isAutoClosed = !close;
|
|
7058
|
+
isClosedPath = true;
|
|
6778
7059
|
}
|
|
6779
7060
|
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
7061
|
+
let runSDF = shapeVertCount >= 3 && doStroke;
|
|
7062
|
+
|
|
7063
|
+
if (runSDF) {
|
|
7064
|
+
let fi = doFill ? fillIdx : 0,
|
|
7065
|
+
si = strokeIdx;
|
|
7066
|
+
|
|
7067
|
+
let polyStart = polyPtsIdx / 4,
|
|
7068
|
+
polyCount = isClosedPath ? shapeVertCount - 1 : shapeVertCount;
|
|
7069
|
+
for (let i = 0; i < polyCount; i++) {
|
|
7070
|
+
polyPtsStack[polyPtsIdx++] = sv[i * 3];
|
|
7071
|
+
polyPtsStack[polyPtsIdx++] = sv[i * 3 + 1];
|
|
7072
|
+
polyPtsStack[polyPtsIdx++] = sv[i * 3 + 2];
|
|
7073
|
+
polyPtsStack[polyPtsIdx++] = ti;
|
|
7074
|
+
}
|
|
7075
|
+
|
|
7076
|
+
let minX = Infinity,
|
|
7077
|
+
minY = Infinity,
|
|
7078
|
+
maxX = -Infinity,
|
|
7079
|
+
maxY = -Infinity;
|
|
7080
|
+
for (let i = 0; i < shapeVertCount; i++) {
|
|
7081
|
+
let vx = sv[i * 3],
|
|
7082
|
+
vy = sv[i * 3 + 1];
|
|
7083
|
+
if (vx < minX) minX = vx;
|
|
7084
|
+
if (vx > maxX) maxX = vx;
|
|
7085
|
+
if (vy < minY) minY = vy;
|
|
7086
|
+
if (vy > maxY) maxY = vy;
|
|
7087
|
+
}
|
|
7088
|
+
let padding = sw * 0.5 + 1.0; // padding for stroke and AA
|
|
7089
|
+
minX -= padding;
|
|
7090
|
+
minY -= padding;
|
|
7091
|
+
maxX += padding;
|
|
7092
|
+
maxY += padding;
|
|
7093
|
+
|
|
7094
|
+
let passedCount = isClosedPath ? polyCount : -polyCount;
|
|
7095
|
+
addPolygonVert(minX, minY, polyStart, passedCount, fi, si, sw, ti);
|
|
7096
|
+
addPolygonVert(maxX, minY, polyStart, passedCount, fi, si, sw, ti);
|
|
7097
|
+
addPolygonVert(minX, maxY, polyStart, passedCount, fi, si, sw, ti);
|
|
7098
|
+
|
|
7099
|
+
addPolygonVert(maxX, minY, polyStart, passedCount, fi, si, sw, ti);
|
|
7100
|
+
addPolygonVert(maxX, maxY, polyStart, passedCount, fi, si, sw, ti);
|
|
7101
|
+
addPolygonVert(minX, maxY, polyStart, passedCount, fi, si, sw, ti);
|
|
7102
|
+
|
|
7103
|
+
drawStack.push(polygonPL, 6);
|
|
7104
|
+
} else {
|
|
7105
|
+
if (doFill) {
|
|
7106
|
+
if (shapeVertCount == 5) {
|
|
7107
|
+
// Quads
|
|
7108
|
+
addVert(sv[0], sv[1], sv[2], ti);
|
|
7109
|
+
addVert(sv[3], sv[4], sv[5], ti);
|
|
7110
|
+
addVert(sv[9], sv[10], sv[11], ti);
|
|
7111
|
+
addVert(sv[6], sv[7], sv[8], ti);
|
|
7112
|
+
drawStack.push(shapesPL, 4);
|
|
7113
|
+
} else {
|
|
7114
|
+
// Triangulation fan
|
|
7115
|
+
for (let i = 1; i < shapeVertCount - 1; i++) {
|
|
7116
|
+
let v0 = 0,
|
|
7117
|
+
v1 = i * 3,
|
|
7118
|
+
v2 = (i + 1) * 3;
|
|
7119
|
+
addVert(sv[v0], sv[v0 + 1], sv[v0 + 2], ti);
|
|
7120
|
+
addVert(sv[v1], sv[v1 + 1], sv[v1 + 2], ti);
|
|
7121
|
+
addVert(sv[v2], sv[v2 + 1], sv[v2 + 2], ti);
|
|
7122
|
+
}
|
|
7123
|
+
drawStack.push(shapesPL, (shapeVertCount - 2) * 3);
|
|
7124
|
+
}
|
|
7125
|
+
}
|
|
7126
|
+
if (doStroke) {
|
|
7127
|
+
let maxLines = isAutoClosed ? shapeVertCount - 2 : shapeVertCount - 1;
|
|
7128
|
+
for (let i = 0; i < maxLines; i++) {
|
|
7129
|
+
let v1 = i * 3,
|
|
7130
|
+
v2 = (i + 1) * 3;
|
|
7131
|
+
$.line(sv[v1], sv[v1 + 1], sv[v2], sv[v2 + 1]);
|
|
7132
|
+
}
|
|
6786
7133
|
}
|
|
6787
|
-
let v1 = (shapeVertCount - 1) * 4;
|
|
6788
|
-
let v2 = 0;
|
|
6789
|
-
if (close) $.line(sv[v1], sv[v1 + 1], sv[v2], sv[v2 + 1]);
|
|
6790
7134
|
}
|
|
6791
7135
|
|
|
6792
|
-
// reset for the next shape
|
|
6793
7136
|
shapeVertCount = 0;
|
|
6794
7137
|
sv = [];
|
|
6795
7138
|
curveVertices = [];
|
|
6796
7139
|
};
|
|
6797
7140
|
|
|
6798
|
-
$.curve = (x1, y1, x2, y2, x3, y3, x4, y4) => {
|
|
6799
|
-
$.beginShape();
|
|
6800
|
-
$.curveVertex(x1, y1);
|
|
6801
|
-
$.curveVertex(x2, y2);
|
|
6802
|
-
$.curveVertex(x3, y3);
|
|
6803
|
-
$.curveVertex(x4, y4);
|
|
6804
|
-
$.endShape();
|
|
6805
|
-
};
|
|
6806
|
-
|
|
6807
|
-
$.bezier = (x1, y1, x2, y2, x3, y3, x4, y4) => {
|
|
6808
|
-
$.beginShape();
|
|
6809
|
-
$.vertex(x1, y1);
|
|
6810
|
-
$.bezierVertex(x2, y2, x3, y3, x4, y4);
|
|
6811
|
-
$.endShape();
|
|
6812
|
-
};
|
|
6813
|
-
|
|
6814
7141
|
$.triangle = (x1, y1, x2, y2, x3, y3) => {
|
|
6815
7142
|
$.beginShape();
|
|
6816
7143
|
$.vertex(x1, y1);
|
|
@@ -6828,21 +7155,6 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6828
7155
|
$.endShape(true);
|
|
6829
7156
|
};
|
|
6830
7157
|
|
|
6831
|
-
function addQuad(x1, y1, x2, y2, x3, y3, x4, y4, ci, ti) {
|
|
6832
|
-
addVert(x1, y1, ci, ti); // v0
|
|
6833
|
-
addVert(x2, y2, ci, ti); // v1
|
|
6834
|
-
addVert(x4, y4, ci, ti); // v3
|
|
6835
|
-
addVert(x3, y3, ci, ti); // v2
|
|
6836
|
-
drawStack.push(shapesPL, 4);
|
|
6837
|
-
}
|
|
6838
|
-
|
|
6839
|
-
$.plane = (x, y, w, h) => {
|
|
6840
|
-
h ??= w;
|
|
6841
|
-
let [l, r, t, b] = calcBox(x, y, w, h, 'center');
|
|
6842
|
-
if (matrixDirty) saveMatrix();
|
|
6843
|
-
addQuad(l, t, r, t, r, b, l, b, fillIdx, matrixIdx);
|
|
6844
|
-
};
|
|
6845
|
-
|
|
6846
7158
|
/* RECT */
|
|
6847
7159
|
|
|
6848
7160
|
let rectPL = 5;
|
|
@@ -7135,7 +7447,21 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
7135
7447
|
};
|
|
7136
7448
|
|
|
7137
7449
|
$.line = (x1, y1, x2, y2) => {
|
|
7138
|
-
if (doStroke)
|
|
7450
|
+
if (!doStroke) return;
|
|
7451
|
+
if (matrixDirty) saveMatrix();
|
|
7452
|
+
|
|
7453
|
+
let dx = x2 - x1,
|
|
7454
|
+
dy = y2 - y1,
|
|
7455
|
+
sqLen = dx * dx + dy * dy;
|
|
7456
|
+
|
|
7457
|
+
if (sqLen === 0) return;
|
|
7458
|
+
|
|
7459
|
+
let len = Math.sqrt(sqLen),
|
|
7460
|
+
ratio = hsw / len,
|
|
7461
|
+
nx = -dy * ratio,
|
|
7462
|
+
ny = dx * ratio;
|
|
7463
|
+
|
|
7464
|
+
addQuad(x1 + nx, y1 + ny, x1 - nx, y1 - ny, x2 - nx, y2 - ny, x2 + nx, y2 + ny, strokeIdx, matrixIdx);
|
|
7139
7465
|
};
|
|
7140
7466
|
|
|
7141
7467
|
/* ELLIPSE */
|
|
@@ -8778,6 +9104,8 @@ fn fragMain(f : FragParams) -> @location(0) vec4f {
|
|
|
8778
9104
|
transformsBuffer?.destroy();
|
|
8779
9105
|
colorsBuffer?.destroy();
|
|
8780
9106
|
shapesVertBuff?.destroy();
|
|
9107
|
+
polygonVertBuff?.destroy();
|
|
9108
|
+
polyPtsBuffer?.destroy();
|
|
8781
9109
|
imgVertBuff?.destroy();
|
|
8782
9110
|
charBuffer?.destroy();
|
|
8783
9111
|
textBuffer?.destroy();
|