q5 2.27.8 → 2.28.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 +2 -2
- package/q5.d.ts +53 -12
- package/q5.js +521 -455
- package/q5.min.js +2 -2
package/q5.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* q5.js
|
|
3
|
-
* @version 2.
|
|
3
|
+
* @version 2.28
|
|
4
4
|
* @author quinton-ashley
|
|
5
5
|
* @contributors evanalulu, Tezumie, ormaq, Dukemz, LingDong-
|
|
6
6
|
* @license LGPL-3.0
|
|
@@ -264,6 +264,7 @@ function Q5(scope, parent, renderer) {
|
|
|
264
264
|
$._isTouchAware = t.touchStarted || t.touchMoved || t.touchEnded;
|
|
265
265
|
|
|
266
266
|
let userFns = [
|
|
267
|
+
'preload',
|
|
267
268
|
'setup',
|
|
268
269
|
'postProcess',
|
|
269
270
|
'mouseMoved',
|
|
@@ -284,18 +285,16 @@ function Q5(scope, parent, renderer) {
|
|
|
284
285
|
// shim if undefined
|
|
285
286
|
for (let name of userFns) $[name] ??= () => {};
|
|
286
287
|
|
|
287
|
-
function wrapWithFES(
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
};
|
|
298
|
-
}
|
|
288
|
+
function wrapWithFES(name) {
|
|
289
|
+
const fn = t[name] || $[name];
|
|
290
|
+
$[name] = (event) => {
|
|
291
|
+
try {
|
|
292
|
+
return fn(event);
|
|
293
|
+
} catch (e) {
|
|
294
|
+
if ($._fes) $._fes(e);
|
|
295
|
+
throw e;
|
|
296
|
+
}
|
|
297
|
+
};
|
|
299
298
|
}
|
|
300
299
|
|
|
301
300
|
async function start() {
|
|
@@ -316,8 +315,8 @@ function Q5(scope, parent, renderer) {
|
|
|
316
315
|
millisStart = performance.now();
|
|
317
316
|
await $.setup();
|
|
318
317
|
$._setupDone = true;
|
|
319
|
-
await runHooks('postsetup');
|
|
320
318
|
if ($.ctx === null) $.createCanvas(200, 200);
|
|
319
|
+
await runHooks('postsetup');
|
|
321
320
|
|
|
322
321
|
if ($.frameCount) return;
|
|
323
322
|
|
|
@@ -384,7 +383,7 @@ function createCanvas(w, h, opt) {
|
|
|
384
383
|
}
|
|
385
384
|
}
|
|
386
385
|
|
|
387
|
-
Q5.version = Q5.VERSION = '2.
|
|
386
|
+
Q5.version = Q5.VERSION = '2.28';
|
|
388
387
|
|
|
389
388
|
if (typeof document == 'object') {
|
|
390
389
|
document.addEventListener('DOMContentLoaded', () => {
|
|
@@ -615,45 +614,6 @@ Q5.modules.canvas = ($, q) => {
|
|
|
615
614
|
} else $._da = 0;
|
|
616
615
|
};
|
|
617
616
|
|
|
618
|
-
$._styleNames = [
|
|
619
|
-
'_fill',
|
|
620
|
-
'_stroke',
|
|
621
|
-
'_strokeWeight',
|
|
622
|
-
'_doStroke',
|
|
623
|
-
'_doFill',
|
|
624
|
-
'_strokeSet',
|
|
625
|
-
'_fillSet',
|
|
626
|
-
'_shadow',
|
|
627
|
-
'_doShadow',
|
|
628
|
-
'_shadowOffsetX',
|
|
629
|
-
'_shadowOffsetY',
|
|
630
|
-
'_shadowBlur',
|
|
631
|
-
'_tint',
|
|
632
|
-
'_colorMode',
|
|
633
|
-
'_colorFormat',
|
|
634
|
-
'Color',
|
|
635
|
-
'_imageMode',
|
|
636
|
-
'_rectMode',
|
|
637
|
-
'_ellipseMode',
|
|
638
|
-
'_textSize',
|
|
639
|
-
'_textAlign',
|
|
640
|
-
'_textBaseline'
|
|
641
|
-
];
|
|
642
|
-
$._styles = [];
|
|
643
|
-
|
|
644
|
-
$.pushStyles = () => {
|
|
645
|
-
let styles = {};
|
|
646
|
-
for (let s of $._styleNames) styles[s] = $[s];
|
|
647
|
-
$._styles.push(styles);
|
|
648
|
-
};
|
|
649
|
-
$.popStyles = () => {
|
|
650
|
-
let styles = $._styles.pop();
|
|
651
|
-
for (let s of $._styleNames) $[s] = styles[s];
|
|
652
|
-
|
|
653
|
-
if ($._webgpu) $.colorMode($._colorMode, $._colorFormat);
|
|
654
|
-
else q.Color = styles.Color;
|
|
655
|
-
};
|
|
656
|
-
|
|
657
617
|
if (window && $._scope != 'graphics') {
|
|
658
618
|
window.addEventListener('resize', () => {
|
|
659
619
|
$._didResize = true;
|
|
@@ -919,13 +879,45 @@ Q5.renderers.c2d.canvas = ($, q) => {
|
|
|
919
879
|
}
|
|
920
880
|
};
|
|
921
881
|
|
|
922
|
-
$.
|
|
923
|
-
|
|
882
|
+
$._styleNames = [
|
|
883
|
+
'_fill',
|
|
884
|
+
'_stroke',
|
|
885
|
+
'_strokeWeight',
|
|
886
|
+
'_doFill',
|
|
887
|
+
'_doStroke',
|
|
888
|
+
'_fillSet',
|
|
889
|
+
'_strokeSet',
|
|
890
|
+
'_shadow',
|
|
891
|
+
'_doShadow',
|
|
892
|
+
'_shadowOffsetX',
|
|
893
|
+
'_shadowOffsetY',
|
|
894
|
+
'_shadowBlur',
|
|
895
|
+
'_tint',
|
|
896
|
+
'_textSize',
|
|
897
|
+
'_textAlign',
|
|
898
|
+
'_textBaseline',
|
|
899
|
+
'_imageMode',
|
|
900
|
+
'_rectMode',
|
|
901
|
+
'_ellipseMode',
|
|
902
|
+
'_colorMode',
|
|
903
|
+
'_colorFormat',
|
|
904
|
+
'Color'
|
|
905
|
+
];
|
|
906
|
+
$._styles = [];
|
|
924
907
|
|
|
925
|
-
|
|
908
|
+
$.pushStyles = () => {
|
|
909
|
+
let styles = {};
|
|
910
|
+
for (let s of $._styleNames) styles[s] = $[s];
|
|
911
|
+
$._styles.push(styles);
|
|
912
|
+
};
|
|
913
|
+
|
|
914
|
+
function popStyles() {
|
|
915
|
+
let styles = $._styles.pop();
|
|
916
|
+
for (let s of $._styleNames) $[s] = styles[s];
|
|
917
|
+
}
|
|
926
918
|
|
|
927
919
|
$.popStyles = () => {
|
|
928
|
-
|
|
920
|
+
popStyles();
|
|
929
921
|
|
|
930
922
|
$.ctx.fillStyle = $._fill;
|
|
931
923
|
$.ctx.strokeStyle = $._stroke;
|
|
@@ -936,13 +928,16 @@ Q5.renderers.c2d.canvas = ($, q) => {
|
|
|
936
928
|
$.ctx.shadowBlur = $._doShadow ? $._shadowBlur : 0;
|
|
937
929
|
};
|
|
938
930
|
|
|
931
|
+
$.pushMatrix = () => $.ctx.save();
|
|
932
|
+
$.popMatrix = () => $.ctx.restore();
|
|
933
|
+
|
|
939
934
|
$.push = () => {
|
|
940
935
|
$.ctx.save();
|
|
941
936
|
$.pushStyles();
|
|
942
937
|
};
|
|
943
938
|
$.pop = () => {
|
|
944
939
|
$.ctx.restore();
|
|
945
|
-
|
|
940
|
+
popStyles();
|
|
946
941
|
};
|
|
947
942
|
};
|
|
948
943
|
Q5.renderers.c2d.shapes = ($) => {
|
|
@@ -3259,10 +3254,10 @@ Q5.modules.input = ($, q) => {
|
|
|
3259
3254
|
};
|
|
3260
3255
|
|
|
3261
3256
|
$._onmouseup = (e) => {
|
|
3257
|
+
q.mouseIsPressed = false;
|
|
3262
3258
|
if (pressAmt > 0) pressAmt--;
|
|
3263
3259
|
else return;
|
|
3264
3260
|
$._updateMouse(e);
|
|
3265
|
-
q.mouseIsPressed = false;
|
|
3266
3261
|
$.mouseReleased(e);
|
|
3267
3262
|
};
|
|
3268
3263
|
|
|
@@ -3367,10 +3362,11 @@ Q5.modules.input = ($, q) => {
|
|
|
3367
3362
|
l('keyup', (e) => $._onkeyup(e), false);
|
|
3368
3363
|
|
|
3369
3364
|
let pointer = window.PointerEvent ? 'pointer' : 'mouse';
|
|
3370
|
-
|
|
3371
3365
|
l(pointer + 'move', (e) => $._onmousemove(e), false);
|
|
3372
|
-
|
|
3373
3366
|
l('touchmove', (e) => $._ontouchmove(e));
|
|
3367
|
+
l(pointer + 'up', (e) => $._onmouseup(e));
|
|
3368
|
+
l('touchend', (e) => $._ontouchend(e));
|
|
3369
|
+
l('touchcancel', (e) => $._ontouchend(e));
|
|
3374
3370
|
|
|
3375
3371
|
if (!c) l('wheel', (e) => $._onwheel(e));
|
|
3376
3372
|
// making the window level event listener for wheel events
|
|
@@ -3381,14 +3377,9 @@ Q5.modules.input = ($, q) => {
|
|
|
3381
3377
|
if (!$._isGlobal && c) l = c.addEventListener.bind(c);
|
|
3382
3378
|
|
|
3383
3379
|
l(pointer + 'down', (e) => $._onmousedown(e));
|
|
3384
|
-
l(
|
|
3385
|
-
|
|
3380
|
+
l('touchstart', (e) => $._ontouchstart(e));
|
|
3386
3381
|
l('click', (e) => $._onclick(e));
|
|
3387
3382
|
l('dblclick', (e) => $._ondblclick(e));
|
|
3388
|
-
|
|
3389
|
-
l('touchstart', (e) => $._ontouchstart(e));
|
|
3390
|
-
l('touchend', (e) => $._ontouchend(e));
|
|
3391
|
-
l('touchcancel', (e) => $._ontouchend(e));
|
|
3392
3383
|
}
|
|
3393
3384
|
};
|
|
3394
3385
|
Q5.modules.math = ($, q) => {
|
|
@@ -4905,11 +4896,6 @@ struct Q5 {
|
|
|
4905
4896
|
$._g = $.createGraphics(1, 1, 'c2d');
|
|
4906
4897
|
if ($._g.colorMode) $._g.colorMode($.RGB, 1);
|
|
4907
4898
|
|
|
4908
|
-
$._hooks = {
|
|
4909
|
-
prerender: [],
|
|
4910
|
-
postrender: []
|
|
4911
|
-
};
|
|
4912
|
-
|
|
4913
4899
|
let encoder,
|
|
4914
4900
|
pass,
|
|
4915
4901
|
mainView,
|
|
@@ -4919,21 +4905,26 @@ struct Q5 {
|
|
|
4919
4905
|
frameSampler,
|
|
4920
4906
|
frameBindGroup,
|
|
4921
4907
|
colorIndex = 1,
|
|
4922
|
-
colorStackIndex = 8
|
|
4908
|
+
colorStackIndex = 8,
|
|
4909
|
+
prevFramePL = 0,
|
|
4910
|
+
framePL = 0;
|
|
4923
4911
|
|
|
4924
4912
|
$._pipelineConfigs = [];
|
|
4925
4913
|
$._pipelines = [];
|
|
4926
4914
|
$._buffers = [];
|
|
4927
|
-
|
|
4928
|
-
$.
|
|
4915
|
+
|
|
4916
|
+
$._hooks = {
|
|
4917
|
+
prerender: [],
|
|
4918
|
+
postrender: []
|
|
4919
|
+
};
|
|
4929
4920
|
|
|
4930
4921
|
// local variables used for slightly better performance
|
|
4931
4922
|
|
|
4932
4923
|
// stores pipeline shifts and vertex counts/image indices
|
|
4933
|
-
let drawStack =
|
|
4924
|
+
let drawStack = [];
|
|
4934
4925
|
|
|
4935
4926
|
// colors used for each draw call
|
|
4936
|
-
let colorStack =
|
|
4927
|
+
let colorStack = new Float32Array(1e6);
|
|
4937
4928
|
|
|
4938
4929
|
// prettier-ignore
|
|
4939
4930
|
colorStack.set([
|
|
@@ -5097,29 +5088,38 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5097
5088
|
// since these values are checked so often in `addColor`,
|
|
5098
5089
|
// they're stored in local variables for better performance
|
|
5099
5090
|
let usingRGB = true,
|
|
5100
|
-
|
|
5091
|
+
_colorMode = 'rgb',
|
|
5092
|
+
_colorFormat = 1;
|
|
5101
5093
|
|
|
5102
5094
|
if ($.colorMode) {
|
|
5103
|
-
let
|
|
5095
|
+
let colorMode = $.colorMode;
|
|
5104
5096
|
$.colorMode = function () {
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5097
|
+
colorMode(...arguments);
|
|
5098
|
+
_colorMode = $._colorMode;
|
|
5099
|
+
usingRGB = _colorMode == 'rgb';
|
|
5100
|
+
_colorFormat = $._colorFormat;
|
|
5108
5101
|
};
|
|
5109
5102
|
}
|
|
5110
5103
|
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5104
|
+
const addColor = (r, g, b, a) => {
|
|
5105
|
+
let isColor = r._q5Color;
|
|
5106
|
+
|
|
5107
|
+
if (usingRGB === false || (g === undefined && !isColor && typeof r !== 'number')) {
|
|
5108
|
+
if (usingRGB === false || typeof r == 'string' || !Array.isArray(r)) {
|
|
5109
|
+
r = $.color(r, g, b, a);
|
|
5110
|
+
} else {
|
|
5111
|
+
[r, g, b, a] = r;
|
|
5112
|
+
}
|
|
5114
5113
|
} else if (b === undefined) {
|
|
5115
5114
|
// grayscale mode `fill(1, 0.5)`
|
|
5116
|
-
a = g ??
|
|
5115
|
+
a = g ?? _colorFormat;
|
|
5117
5116
|
g = b = r;
|
|
5118
5117
|
}
|
|
5119
|
-
a ??=
|
|
5120
|
-
|
|
5118
|
+
a ??= _colorFormat;
|
|
5119
|
+
|
|
5120
|
+
if (isColor === true) {
|
|
5121
5121
|
let c = r;
|
|
5122
|
-
if (
|
|
5122
|
+
if (usingRGB) ({ r, g, b, a } = c);
|
|
5123
5123
|
else {
|
|
5124
5124
|
a = c.a;
|
|
5125
5125
|
if (c.c != undefined) c = Q5.OKLCHtoRGB(c.l, c.c, c.h);
|
|
@@ -5129,7 +5129,7 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5129
5129
|
}
|
|
5130
5130
|
}
|
|
5131
5131
|
|
|
5132
|
-
if (
|
|
5132
|
+
if (_colorFormat === 255) {
|
|
5133
5133
|
r /= 255;
|
|
5134
5134
|
g /= 255;
|
|
5135
5135
|
b /= 255;
|
|
@@ -5147,38 +5147,42 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5147
5147
|
colorIndex++;
|
|
5148
5148
|
};
|
|
5149
5149
|
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5150
|
+
let doFill = true,
|
|
5151
|
+
doStroke = true,
|
|
5152
|
+
fillSet = false,
|
|
5153
|
+
strokeSet = false,
|
|
5154
|
+
strokeIdx = 0,
|
|
5155
|
+
fillIdx = 1,
|
|
5156
|
+
tintIdx = 1,
|
|
5157
|
+
globalAlpha = 1,
|
|
5158
|
+
sw = 1, // stroke weight
|
|
5159
|
+
hsw = 0.5, // half the stroke weight
|
|
5160
|
+
scaledSW = 1;
|
|
5153
5161
|
|
|
5154
5162
|
$.fill = (r, g, b, a) => {
|
|
5155
5163
|
addColor(r, g, b, a);
|
|
5156
|
-
|
|
5157
|
-
|
|
5164
|
+
doFill = fillSet = true;
|
|
5165
|
+
fillIdx = colorIndex;
|
|
5158
5166
|
};
|
|
5159
5167
|
$.stroke = (r, g, b, a) => {
|
|
5160
5168
|
addColor(r, g, b, a);
|
|
5161
|
-
|
|
5162
|
-
|
|
5169
|
+
doStroke = strokeSet = true;
|
|
5170
|
+
strokeIdx = colorIndex;
|
|
5163
5171
|
};
|
|
5164
5172
|
$.tint = (r, g, b, a) => {
|
|
5165
5173
|
addColor(r, g, b, a);
|
|
5166
|
-
|
|
5174
|
+
tintIdx = colorIndex;
|
|
5167
5175
|
};
|
|
5168
|
-
$.opacity = (a) => (
|
|
5169
|
-
$.noFill = () => (
|
|
5170
|
-
$.noStroke = () => (
|
|
5171
|
-
$.noTint = () => (
|
|
5172
|
-
|
|
5173
|
-
$._strokeWeight = 1;
|
|
5174
|
-
$._hsw = 0.5;
|
|
5175
|
-
$._scaledSW = 1;
|
|
5176
|
+
$.opacity = (a) => (globalAlpha = a);
|
|
5177
|
+
$.noFill = () => (doFill = false);
|
|
5178
|
+
$.noStroke = () => (doStroke = false);
|
|
5179
|
+
$.noTint = () => (tintIdx = 1);
|
|
5176
5180
|
|
|
5177
5181
|
$.strokeWeight = (v) => {
|
|
5178
5182
|
v = Math.abs(v);
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5183
|
+
sw = v;
|
|
5184
|
+
scaledSW = v * _scale;
|
|
5185
|
+
hsw = v / 2;
|
|
5182
5186
|
};
|
|
5183
5187
|
|
|
5184
5188
|
const MAX_TRANSFORMS = $._graphics ? 1000 : 1e7,
|
|
@@ -5187,10 +5191,9 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5187
5191
|
|
|
5188
5192
|
let matrix,
|
|
5189
5193
|
matrices = [],
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
$._matrixDirty = false;
|
|
5194
|
+
matricesIdxStack = [],
|
|
5195
|
+
matrixIdx = 0,
|
|
5196
|
+
matrixDirty = false; // tracks if the matrix has been modified
|
|
5194
5197
|
|
|
5195
5198
|
// initialize with a 4x4 identity matrix
|
|
5196
5199
|
// prettier-ignore
|
|
@@ -5205,7 +5208,7 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5205
5208
|
|
|
5206
5209
|
$.resetMatrix = () => {
|
|
5207
5210
|
matrix = matrices[0].slice();
|
|
5208
|
-
|
|
5211
|
+
matrixIdx = 0;
|
|
5209
5212
|
};
|
|
5210
5213
|
$.resetMatrix();
|
|
5211
5214
|
|
|
@@ -5216,7 +5219,7 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5216
5219
|
m[12] += x * m[0];
|
|
5217
5220
|
m[13] -= y * m[5];
|
|
5218
5221
|
m[14] += z * m[10];
|
|
5219
|
-
|
|
5222
|
+
matrixDirty = true;
|
|
5220
5223
|
};
|
|
5221
5224
|
|
|
5222
5225
|
$.rotate = $.rotateZ = (a) => {
|
|
@@ -5245,16 +5248,16 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5245
5248
|
m[5] = m5 * cosR - m4 * sinR;
|
|
5246
5249
|
}
|
|
5247
5250
|
|
|
5248
|
-
|
|
5251
|
+
matrixDirty = true;
|
|
5249
5252
|
};
|
|
5250
5253
|
|
|
5251
|
-
|
|
5254
|
+
let _scale = 1;
|
|
5252
5255
|
|
|
5253
5256
|
$.scale = (x = 1, y, z = 1) => {
|
|
5254
5257
|
y ??= x;
|
|
5255
5258
|
|
|
5256
|
-
|
|
5257
|
-
|
|
5259
|
+
_scale = Math.max(Math.abs(x), Math.abs(y));
|
|
5260
|
+
scaledSW = sw * _scale;
|
|
5258
5261
|
|
|
5259
5262
|
let m = matrix;
|
|
5260
5263
|
|
|
@@ -5271,7 +5274,7 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5271
5274
|
m[10] *= z;
|
|
5272
5275
|
m[11] *= z;
|
|
5273
5276
|
|
|
5274
|
-
|
|
5277
|
+
matrixDirty = true;
|
|
5275
5278
|
};
|
|
5276
5279
|
|
|
5277
5280
|
$.shearX = (ang) => {
|
|
@@ -5288,7 +5291,7 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5288
5291
|
m[0] = m0 + m4 * tanAng;
|
|
5289
5292
|
m[1] = m1 + m5 * tanAng;
|
|
5290
5293
|
|
|
5291
|
-
|
|
5294
|
+
matrixDirty = true;
|
|
5292
5295
|
};
|
|
5293
5296
|
|
|
5294
5297
|
$.shearY = (ang) => {
|
|
@@ -5305,7 +5308,7 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5305
5308
|
m[4] = m4 + m0 * tanAng;
|
|
5306
5309
|
m[5] = m5 + m1 * tanAng;
|
|
5307
5310
|
|
|
5308
|
-
|
|
5311
|
+
matrixDirty = true;
|
|
5309
5312
|
};
|
|
5310
5313
|
|
|
5311
5314
|
$.applyMatrix = (...args) => {
|
|
@@ -5322,38 +5325,93 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5322
5325
|
|
|
5323
5326
|
// overwrite the current transformation matrix
|
|
5324
5327
|
matrix = m.slice();
|
|
5325
|
-
|
|
5328
|
+
matrixDirty = true;
|
|
5326
5329
|
};
|
|
5327
5330
|
|
|
5328
5331
|
// saves the current matrix state
|
|
5329
|
-
|
|
5332
|
+
const saveMatrix = () => {
|
|
5330
5333
|
transforms.set(matrix, matrices.length * MATRIX_SIZE);
|
|
5331
|
-
|
|
5334
|
+
matrixIdx = matrices.length;
|
|
5332
5335
|
matrices.push(matrix.slice());
|
|
5333
|
-
|
|
5336
|
+
matrixDirty = false;
|
|
5334
5337
|
};
|
|
5335
5338
|
|
|
5336
5339
|
// push the current matrix index onto the stack
|
|
5337
5340
|
$.pushMatrix = () => {
|
|
5338
|
-
if (
|
|
5339
|
-
|
|
5341
|
+
if (matrixDirty) saveMatrix();
|
|
5342
|
+
matricesIdxStack.push(matrixIdx);
|
|
5340
5343
|
};
|
|
5341
5344
|
|
|
5342
5345
|
$.popMatrix = () => {
|
|
5343
|
-
if (!
|
|
5346
|
+
if (!matricesIdxStack.length) {
|
|
5344
5347
|
return console.warn('Matrix index stack is empty!');
|
|
5345
5348
|
}
|
|
5346
5349
|
// pop the last matrix index and set it as the current matrix index
|
|
5347
|
-
let idx =
|
|
5350
|
+
let idx = matricesIdxStack.pop();
|
|
5348
5351
|
matrix = matrices[idx].slice();
|
|
5349
|
-
|
|
5350
|
-
|
|
5352
|
+
matrixIdx = idx;
|
|
5353
|
+
matrixDirty = false;
|
|
5351
5354
|
};
|
|
5352
5355
|
|
|
5353
|
-
let
|
|
5356
|
+
let styles = [];
|
|
5357
|
+
|
|
5354
5358
|
$.pushStyles = () => {
|
|
5355
|
-
|
|
5356
|
-
|
|
5359
|
+
styles.push([
|
|
5360
|
+
fillIdx,
|
|
5361
|
+
strokeIdx,
|
|
5362
|
+
sw,
|
|
5363
|
+
hsw,
|
|
5364
|
+
scaledSW,
|
|
5365
|
+
doFill,
|
|
5366
|
+
doStroke,
|
|
5367
|
+
fillSet,
|
|
5368
|
+
strokeSet,
|
|
5369
|
+
tintIdx,
|
|
5370
|
+
_textSize,
|
|
5371
|
+
_textAlign,
|
|
5372
|
+
_textBaseline,
|
|
5373
|
+
_imageMode,
|
|
5374
|
+
_rectMode,
|
|
5375
|
+
_ellipseMode,
|
|
5376
|
+
usingRGB,
|
|
5377
|
+
_colorMode,
|
|
5378
|
+
_colorFormat,
|
|
5379
|
+
Color
|
|
5380
|
+
]);
|
|
5381
|
+
};
|
|
5382
|
+
|
|
5383
|
+
$.popStyles = () => {
|
|
5384
|
+
let s = styles.pop();
|
|
5385
|
+
|
|
5386
|
+
// array destructuring to local variables is way better
|
|
5387
|
+
// for performance than copying from one object to another
|
|
5388
|
+
[
|
|
5389
|
+
fillIdx,
|
|
5390
|
+
strokeIdx,
|
|
5391
|
+
sw,
|
|
5392
|
+
hsw,
|
|
5393
|
+
scaledSW,
|
|
5394
|
+
doFill,
|
|
5395
|
+
doStroke,
|
|
5396
|
+
fillSet,
|
|
5397
|
+
strokeSet,
|
|
5398
|
+
tintIdx,
|
|
5399
|
+
_textSize,
|
|
5400
|
+
_textAlign,
|
|
5401
|
+
_textBaseline,
|
|
5402
|
+
_imageMode,
|
|
5403
|
+
_rectMode,
|
|
5404
|
+
_ellipseMode,
|
|
5405
|
+
usingRGB,
|
|
5406
|
+
_colorMode,
|
|
5407
|
+
_colorFormat
|
|
5408
|
+
] = s;
|
|
5409
|
+
|
|
5410
|
+
// since these values are used outside of q5-webgpu
|
|
5411
|
+
// they need to be stored on the instance
|
|
5412
|
+
$._colorFormat = _colorFormat;
|
|
5413
|
+
$._colorMode = _colorMode;
|
|
5414
|
+
$.Color = s.at(-1);
|
|
5357
5415
|
};
|
|
5358
5416
|
|
|
5359
5417
|
$.push = () => {
|
|
@@ -5366,7 +5424,7 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5366
5424
|
$.popStyles();
|
|
5367
5425
|
};
|
|
5368
5426
|
|
|
5369
|
-
|
|
5427
|
+
const calcBox = (x, y, w, h, mode) => {
|
|
5370
5428
|
// left, right, top, bottom
|
|
5371
5429
|
let l, r, t, b;
|
|
5372
5430
|
if (!mode || mode == 'corner') {
|
|
@@ -5426,7 +5484,7 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5426
5484
|
replace: [1, 0, 0, 1, 0, 0]
|
|
5427
5485
|
};
|
|
5428
5486
|
|
|
5429
|
-
|
|
5487
|
+
let blendModeNames = Object.keys(blendModes);
|
|
5430
5488
|
|
|
5431
5489
|
$.blendConfigs = {};
|
|
5432
5490
|
|
|
@@ -5445,12 +5503,12 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5445
5503
|
};
|
|
5446
5504
|
}
|
|
5447
5505
|
|
|
5448
|
-
|
|
5506
|
+
let _blendMode = 'source-over';
|
|
5449
5507
|
|
|
5450
5508
|
$.blendMode = (mode) => {
|
|
5451
|
-
if (mode ==
|
|
5452
|
-
|
|
5453
|
-
let i =
|
|
5509
|
+
if (mode == _blendMode) return;
|
|
5510
|
+
_blendMode = mode;
|
|
5511
|
+
let i = blendModeNames.indexOf(mode);
|
|
5454
5512
|
if (i == -1) {
|
|
5455
5513
|
console.error(`Blend mode "${mode}" not supported in q5.js WebGPU.`);
|
|
5456
5514
|
return;
|
|
@@ -5465,19 +5523,17 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5465
5523
|
};
|
|
5466
5524
|
|
|
5467
5525
|
$.background = (r, g, b, a) => {
|
|
5468
|
-
$.push();
|
|
5469
|
-
$.resetMatrix();
|
|
5470
5526
|
if (r.canvas) {
|
|
5527
|
+
$.push();
|
|
5528
|
+
$.resetMatrix();
|
|
5471
5529
|
let img = r;
|
|
5472
|
-
|
|
5530
|
+
_imageMode = 'corner';
|
|
5473
5531
|
$.image(img, -c.hw, -c.hh, c.w, c.h);
|
|
5532
|
+
$.pop();
|
|
5474
5533
|
} else {
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
$._doStroke = false;
|
|
5478
|
-
$.rect(-c.hw, -c.hh, c.w, c.h);
|
|
5534
|
+
addColor(r, g, b, a);
|
|
5535
|
+
addRect(-c.hw, c.hh, c.hw, c.hh, c.hw, -c.hh, -c.hw, -c.hh, colorIndex, 0);
|
|
5479
5536
|
}
|
|
5480
|
-
$.pop();
|
|
5481
5537
|
};
|
|
5482
5538
|
|
|
5483
5539
|
$._beginRender = () => {
|
|
@@ -5511,7 +5567,7 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5511
5567
|
});
|
|
5512
5568
|
|
|
5513
5569
|
if (!shouldClear) {
|
|
5514
|
-
pass.setPipeline($._pipelines[
|
|
5570
|
+
pass.setPipeline($._pipelines[prevFramePL]);
|
|
5515
5571
|
pass.setBindGroup(0, frameBindGroup);
|
|
5516
5572
|
pass.draw(4);
|
|
5517
5573
|
}
|
|
@@ -5583,7 +5639,7 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5583
5639
|
if (drawStack[i] != curPipelineIndex) {
|
|
5584
5640
|
if (drawStack[i] == 0) {
|
|
5585
5641
|
// change blend mode
|
|
5586
|
-
let mode =
|
|
5642
|
+
let mode = blendModeNames[v];
|
|
5587
5643
|
for (let i = 1; i < $._pipelines.length; i++) {
|
|
5588
5644
|
$._pipelineConfigs[i].fragment.targets[0].blend = $.blendConfigs[mode];
|
|
5589
5645
|
$._pipelines[i] = Q5.device.createRenderPipeline($._pipelineConfigs[i]);
|
|
@@ -5644,7 +5700,7 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5644
5700
|
]
|
|
5645
5701
|
});
|
|
5646
5702
|
|
|
5647
|
-
pass.setPipeline($._pipelines[
|
|
5703
|
+
pass.setPipeline($._pipelines[framePL]);
|
|
5648
5704
|
pass.setBindGroup(0, frameBindGroup);
|
|
5649
5705
|
pass.draw(4);
|
|
5650
5706
|
pass.end();
|
|
@@ -5657,7 +5713,7 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5657
5713
|
colorIndex = 1;
|
|
5658
5714
|
colorStackIndex = 8;
|
|
5659
5715
|
matrices = [matrices[0]];
|
|
5660
|
-
|
|
5716
|
+
matricesIdxStack = [];
|
|
5661
5717
|
|
|
5662
5718
|
$._texture = frameA;
|
|
5663
5719
|
|
|
@@ -5669,40 +5725,10 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5669
5725
|
$._buffers = [];
|
|
5670
5726
|
});
|
|
5671
5727
|
};
|
|
5672
|
-
};
|
|
5673
5728
|
|
|
5674
|
-
|
|
5675
|
-
if (!navigator.gpu) {
|
|
5676
|
-
console.warn('q5 WebGPU not supported on this browser! Use Google Chrome or Edge.');
|
|
5677
|
-
return false;
|
|
5678
|
-
}
|
|
5679
|
-
if (!Q5.requestedGPU) {
|
|
5680
|
-
let adapter = await navigator.gpu.requestAdapter();
|
|
5681
|
-
if (!adapter) {
|
|
5682
|
-
console.warn('q5 WebGPU could not start! No appropriate GPUAdapter found, vulkan may need to be enabled.');
|
|
5683
|
-
return false;
|
|
5684
|
-
}
|
|
5685
|
-
Q5.device = await adapter.requestDevice();
|
|
5729
|
+
/* SHAPES */
|
|
5686
5730
|
|
|
5687
|
-
|
|
5688
|
-
console.error('WebGPU crashed!');
|
|
5689
|
-
console.error(e);
|
|
5690
|
-
});
|
|
5691
|
-
}
|
|
5692
|
-
return true;
|
|
5693
|
-
};
|
|
5694
|
-
|
|
5695
|
-
Q5.WebGPU = async function (scope, parent) {
|
|
5696
|
-
if (!scope || scope == 'global') Q5._hasGlobal = true;
|
|
5697
|
-
if (!(await Q5.initWebGPU())) {
|
|
5698
|
-
return new Q5(scope, parent, 'webgpu-fallback');
|
|
5699
|
-
}
|
|
5700
|
-
return new Q5(scope, parent, 'webgpu');
|
|
5701
|
-
};
|
|
5702
|
-
|
|
5703
|
-
Q5.webgpu = Q5.WebGPU;
|
|
5704
|
-
Q5.renderers.webgpu.shapes = ($) => {
|
|
5705
|
-
$._shapesPL = 1;
|
|
5731
|
+
let shapesPL = 1;
|
|
5706
5732
|
|
|
5707
5733
|
$._shapesShaderCode =
|
|
5708
5734
|
$._baseShaderCode +
|
|
@@ -5751,14 +5777,12 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
5751
5777
|
code: $._shapesShaderCode
|
|
5752
5778
|
});
|
|
5753
5779
|
|
|
5754
|
-
let
|
|
5755
|
-
|
|
5756
|
-
vertexStack = new Float32Array($._graphics ? 1000 : 1e7),
|
|
5757
|
-
vertIndex = 0;
|
|
5780
|
+
let shapesVertStack = new Float32Array($._graphics ? 1000 : 1e7),
|
|
5781
|
+
shapesVertIdx = 0;
|
|
5758
5782
|
const TAU = Math.PI * 2;
|
|
5759
5783
|
const HALF_PI = Math.PI / 2;
|
|
5760
5784
|
|
|
5761
|
-
let
|
|
5785
|
+
let shapesVertBuffLayout = {
|
|
5762
5786
|
arrayStride: 16, // 4 floats * 4 bytes
|
|
5763
5787
|
attributes: [
|
|
5764
5788
|
{ format: 'float32x2', offset: 0, shaderLocation: 0 }, // position
|
|
@@ -5778,7 +5802,7 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
5778
5802
|
vertex: {
|
|
5779
5803
|
module: shapesShader,
|
|
5780
5804
|
entryPoint: 'vertexMain',
|
|
5781
|
-
buffers: [
|
|
5805
|
+
buffers: [shapesVertBuffLayout]
|
|
5782
5806
|
},
|
|
5783
5807
|
fragment: {
|
|
5784
5808
|
module: shapesShader,
|
|
@@ -5792,18 +5816,18 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
5792
5816
|
$._pipelines[1] = Q5.device.createRenderPipeline($._pipelineConfigs[1]);
|
|
5793
5817
|
|
|
5794
5818
|
const addVert = (x, y, ci, ti) => {
|
|
5795
|
-
let v =
|
|
5796
|
-
i =
|
|
5819
|
+
let v = shapesVertStack,
|
|
5820
|
+
i = shapesVertIdx;
|
|
5797
5821
|
v[i++] = x;
|
|
5798
5822
|
v[i++] = y;
|
|
5799
5823
|
v[i++] = ci;
|
|
5800
5824
|
v[i++] = ti;
|
|
5801
|
-
|
|
5825
|
+
shapesVertIdx = i;
|
|
5802
5826
|
};
|
|
5803
5827
|
|
|
5804
5828
|
const addRect = (x1, y1, x2, y2, x3, y3, x4, y4, ci, ti) => {
|
|
5805
|
-
let v =
|
|
5806
|
-
i =
|
|
5829
|
+
let v = shapesVertStack,
|
|
5830
|
+
i = shapesVertIdx;
|
|
5807
5831
|
|
|
5808
5832
|
v[i++] = x1;
|
|
5809
5833
|
v[i++] = y1;
|
|
@@ -5825,8 +5849,8 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
5825
5849
|
v[i++] = ci;
|
|
5826
5850
|
v[i++] = ti;
|
|
5827
5851
|
|
|
5828
|
-
|
|
5829
|
-
drawStack.push(
|
|
5852
|
+
shapesVertIdx = i;
|
|
5853
|
+
drawStack.push(shapesPL, 4);
|
|
5830
5854
|
};
|
|
5831
5855
|
|
|
5832
5856
|
const addArc = (x, y, a, b, startAngle, endAngle, n, ci, ti) => {
|
|
@@ -5834,8 +5858,8 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
5834
5858
|
let angleIncrement = angleRange / n;
|
|
5835
5859
|
let t = startAngle;
|
|
5836
5860
|
|
|
5837
|
-
let v =
|
|
5838
|
-
i =
|
|
5861
|
+
let v = shapesVertStack,
|
|
5862
|
+
i = shapesVertIdx;
|
|
5839
5863
|
|
|
5840
5864
|
for (let j = 0; j <= n; j++) {
|
|
5841
5865
|
// add center vertex
|
|
@@ -5857,8 +5881,8 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
5857
5881
|
t += angleIncrement;
|
|
5858
5882
|
}
|
|
5859
5883
|
|
|
5860
|
-
|
|
5861
|
-
drawStack.push(
|
|
5884
|
+
shapesVertIdx = i;
|
|
5885
|
+
drawStack.push(shapesPL, (n + 1) * 2);
|
|
5862
5886
|
};
|
|
5863
5887
|
|
|
5864
5888
|
const addArcStroke = (x, y, outerA, outerB, innerA, innerB, startAngle, endAngle, n, ci, ti) => {
|
|
@@ -5866,8 +5890,8 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
5866
5890
|
let angleIncrement = angleRange / n;
|
|
5867
5891
|
let t = startAngle;
|
|
5868
5892
|
|
|
5869
|
-
let v =
|
|
5870
|
-
i =
|
|
5893
|
+
let v = shapesVertStack,
|
|
5894
|
+
i = shapesVertIdx;
|
|
5871
5895
|
|
|
5872
5896
|
for (let j = 0; j <= n; j++) {
|
|
5873
5897
|
// Outer vertex
|
|
@@ -5892,45 +5916,46 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
5892
5916
|
t += angleIncrement;
|
|
5893
5917
|
}
|
|
5894
5918
|
|
|
5895
|
-
|
|
5896
|
-
drawStack.push(
|
|
5919
|
+
shapesVertIdx = i;
|
|
5920
|
+
drawStack.push(shapesPL, (n + 1) * 2);
|
|
5897
5921
|
};
|
|
5898
5922
|
|
|
5899
|
-
|
|
5923
|
+
let _rectMode = 'corner';
|
|
5924
|
+
|
|
5925
|
+
$.rectMode = (x) => (_rectMode = x);
|
|
5900
5926
|
|
|
5901
5927
|
$.rect = (x, y, w, h, rr = 0) => {
|
|
5902
5928
|
h ??= w;
|
|
5903
|
-
let [l, r, t, b] =
|
|
5929
|
+
let [l, r, t, b] = calcBox(x, y, w, h, _rectMode);
|
|
5904
5930
|
let ci, ti;
|
|
5905
|
-
if (
|
|
5906
|
-
ti =
|
|
5931
|
+
if (matrixDirty) saveMatrix();
|
|
5932
|
+
ti = matrixIdx;
|
|
5907
5933
|
|
|
5908
5934
|
if (!rr) {
|
|
5909
|
-
if (
|
|
5910
|
-
ci =
|
|
5935
|
+
if (doFill) {
|
|
5936
|
+
ci = fillIdx;
|
|
5911
5937
|
addRect(l, t, r, t, r, b, l, b, ci, ti);
|
|
5912
5938
|
}
|
|
5913
5939
|
|
|
5914
|
-
if (
|
|
5915
|
-
ci =
|
|
5916
|
-
let sw = $._strokeWeight / 2;
|
|
5940
|
+
if (doStroke) {
|
|
5941
|
+
ci = strokeIdx;
|
|
5917
5942
|
|
|
5918
5943
|
// Calculate stroke positions
|
|
5919
|
-
let lsw = l -
|
|
5920
|
-
rsw = r +
|
|
5921
|
-
tsw = t +
|
|
5922
|
-
bsw = b -
|
|
5923
|
-
lpsw = l +
|
|
5924
|
-
rpsw = r -
|
|
5925
|
-
tpsw = t -
|
|
5926
|
-
bpsw = b +
|
|
5944
|
+
let lsw = l - hsw,
|
|
5945
|
+
rsw = r + hsw,
|
|
5946
|
+
tsw = t + hsw,
|
|
5947
|
+
bsw = b - hsw,
|
|
5948
|
+
lpsw = l + hsw,
|
|
5949
|
+
rpsw = r - hsw,
|
|
5950
|
+
tpsw = t - hsw,
|
|
5951
|
+
bpsw = b + hsw;
|
|
5927
5952
|
|
|
5928
5953
|
addRect(lsw, tpsw, rsw, tpsw, rsw, tsw, lsw, tsw, ci, ti); // Top
|
|
5929
5954
|
addRect(lsw, bsw, rsw, bsw, rsw, bpsw, lsw, bpsw, ci, ti); // Bottom
|
|
5930
5955
|
|
|
5931
5956
|
// Adjust side strokes to avoid overlapping corners
|
|
5932
|
-
tsw = t -
|
|
5933
|
-
bsw = b +
|
|
5957
|
+
tsw = t - hsw;
|
|
5958
|
+
bsw = b + hsw;
|
|
5934
5959
|
|
|
5935
5960
|
addRect(lsw, tsw, lpsw, tsw, lpsw, bsw, lsw, bsw, ci, ti); // Left
|
|
5936
5961
|
addRect(rpsw, tsw, rsw, tsw, rsw, bsw, rpsw, bsw, ci, ti); // Right
|
|
@@ -5946,15 +5971,15 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
5946
5971
|
// Clamp radius
|
|
5947
5972
|
rr = Math.min(rr, Math.min(w, h) / 2);
|
|
5948
5973
|
|
|
5949
|
-
let n = getArcSegments(rr *
|
|
5974
|
+
let n = getArcSegments(rr * _scale);
|
|
5950
5975
|
|
|
5951
5976
|
let trr = t + rr,
|
|
5952
5977
|
brr = b - rr,
|
|
5953
5978
|
lrr = l - rr,
|
|
5954
5979
|
rrr = r + rr;
|
|
5955
5980
|
|
|
5956
|
-
if (
|
|
5957
|
-
ci =
|
|
5981
|
+
if (doFill) {
|
|
5982
|
+
ci = fillIdx;
|
|
5958
5983
|
// Corner arcs
|
|
5959
5984
|
addArc(r, b, rr, rr, 0, HALF_PI, n, ci, ti);
|
|
5960
5985
|
addArc(l, b, rr, rr, Math.PI, HALF_PI, n, ci, ti);
|
|
@@ -5966,9 +5991,8 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
5966
5991
|
addRect(rrr, t, r, t, r, b, rrr, b, ci, ti); // Right
|
|
5967
5992
|
}
|
|
5968
5993
|
|
|
5969
|
-
if (
|
|
5970
|
-
ci =
|
|
5971
|
-
let hsw = $._hsw;
|
|
5994
|
+
if (doStroke) {
|
|
5995
|
+
ci = strokeIdx;
|
|
5972
5996
|
|
|
5973
5997
|
let outerA = rr + hsw,
|
|
5974
5998
|
outerB = rr + hsw,
|
|
@@ -6001,9 +6025,9 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6001
6025
|
|
|
6002
6026
|
$.plane = (x, y, w, h) => {
|
|
6003
6027
|
h ??= w;
|
|
6004
|
-
let [l, r, t, b] =
|
|
6005
|
-
if (
|
|
6006
|
-
addRect(l, t, r, t, r, b, l, b,
|
|
6028
|
+
let [l, r, t, b] = calcBox(x, y, w, h, 'center');
|
|
6029
|
+
if (matrixDirty) saveMatrix();
|
|
6030
|
+
addRect(l, t, r, t, r, b, l, b, fillIdx, matrixIdx);
|
|
6007
6031
|
};
|
|
6008
6032
|
|
|
6009
6033
|
// prettier-ignore
|
|
@@ -6037,24 +6061,24 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6037
6061
|
d < 2400 ? 90 :
|
|
6038
6062
|
100;
|
|
6039
6063
|
|
|
6040
|
-
|
|
6041
|
-
|
|
6064
|
+
let _ellipseMode = 'center';
|
|
6065
|
+
|
|
6066
|
+
$.ellipseMode = (x) => (_ellipseMode = x);
|
|
6042
6067
|
|
|
6043
6068
|
$.ellipse = (x, y, w, h) => {
|
|
6044
|
-
let n = getArcSegments(Math.max(Math.abs(w), Math.abs(h)) *
|
|
6069
|
+
let n = getArcSegments(Math.max(Math.abs(w), Math.abs(h)) * _scale);
|
|
6045
6070
|
let a = w / 2;
|
|
6046
6071
|
let b = w == h ? a : h / 2;
|
|
6047
6072
|
|
|
6048
|
-
if (
|
|
6049
|
-
let ti =
|
|
6073
|
+
if (matrixDirty) saveMatrix();
|
|
6074
|
+
let ti = matrixIdx;
|
|
6050
6075
|
|
|
6051
|
-
if (
|
|
6052
|
-
addArc(x, -y, a, b, 0, TAU, n,
|
|
6076
|
+
if (doFill) {
|
|
6077
|
+
addArc(x, -y, a, b, 0, TAU, n, fillIdx, ti);
|
|
6053
6078
|
}
|
|
6054
|
-
if (
|
|
6055
|
-
let sw = $._strokeWeight / 2;
|
|
6079
|
+
if (doStroke) {
|
|
6056
6080
|
// Draw the stroke as a ring using triangle strips
|
|
6057
|
-
addArcStroke(x, -y, a +
|
|
6081
|
+
addArcStroke(x, -y, a + hsw, b + hsw, a - hsw, b - hsw, 0, TAU, n, strokeIdx, ti);
|
|
6058
6082
|
}
|
|
6059
6083
|
};
|
|
6060
6084
|
|
|
@@ -6079,74 +6103,72 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6079
6103
|
|
|
6080
6104
|
// Calculate position based on ellipseMode
|
|
6081
6105
|
let a, b;
|
|
6082
|
-
if (
|
|
6106
|
+
if (_ellipseMode == $.CENTER) {
|
|
6083
6107
|
a = w / 2;
|
|
6084
6108
|
b = h / 2;
|
|
6085
|
-
} else if (
|
|
6109
|
+
} else if (_ellipseMode == $.RADIUS) {
|
|
6086
6110
|
a = w;
|
|
6087
6111
|
b = h;
|
|
6088
|
-
} else if (
|
|
6112
|
+
} else if (_ellipseMode == $.CORNER) {
|
|
6089
6113
|
x += w / 2;
|
|
6090
6114
|
y += h / 2;
|
|
6091
6115
|
a = w / 2;
|
|
6092
6116
|
b = h / 2;
|
|
6093
|
-
} else if (
|
|
6117
|
+
} else if (_ellipseMode == $.CORNERS) {
|
|
6094
6118
|
x = (x + w) / 2;
|
|
6095
6119
|
y = (y + h) / 2;
|
|
6096
6120
|
a = (w - x) / 2;
|
|
6097
6121
|
b = (h - y) / 2;
|
|
6098
6122
|
}
|
|
6099
6123
|
|
|
6100
|
-
if (
|
|
6101
|
-
let ti =
|
|
6102
|
-
let n = getArcSegments(Math.max(Math.abs(w), Math.abs(h)) *
|
|
6124
|
+
if (matrixDirty) saveMatrix();
|
|
6125
|
+
let ti = matrixIdx;
|
|
6126
|
+
let n = getArcSegments(Math.max(Math.abs(w), Math.abs(h)) * _scale);
|
|
6103
6127
|
|
|
6104
6128
|
// Draw fill
|
|
6105
|
-
if (
|
|
6106
|
-
addArc(x, -y, a, b, start, stop, n,
|
|
6129
|
+
if (doFill) {
|
|
6130
|
+
addArc(x, -y, a, b, start, stop, n, fillIdx, ti);
|
|
6107
6131
|
}
|
|
6108
6132
|
|
|
6109
6133
|
// Draw stroke
|
|
6110
|
-
if (
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
addArc(x + a * Math.cos(
|
|
6115
|
-
addArc(x + a * Math.cos(stop), -y - b * Math.sin(stop), hsw, hsw, 0, TAU, n, $._stroke, ti);
|
|
6134
|
+
if (doStroke) {
|
|
6135
|
+
addArcStroke(x, -y, a + hsw, b + hsw, a - hsw, b - hsw, start, stop, n, strokeIdx, ti);
|
|
6136
|
+
if (_strokeCap == 'round') {
|
|
6137
|
+
addArc(x + a * Math.cos(start), -y - b * Math.sin(start), hsw, hsw, 0, TAU, n, strokeIdx, ti);
|
|
6138
|
+
addArc(x + a * Math.cos(stop), -y - b * Math.sin(stop), hsw, hsw, 0, TAU, n, strokeIdx, ti);
|
|
6116
6139
|
}
|
|
6117
6140
|
}
|
|
6118
6141
|
};
|
|
6119
6142
|
|
|
6120
6143
|
$.point = (x, y) => {
|
|
6121
|
-
if (
|
|
6122
|
-
let ti =
|
|
6123
|
-
ci =
|
|
6124
|
-
sw = $._strokeWeight;
|
|
6144
|
+
if (matrixDirty) saveMatrix();
|
|
6145
|
+
let ti = matrixIdx,
|
|
6146
|
+
ci = strokeIdx;
|
|
6125
6147
|
|
|
6126
|
-
if (
|
|
6127
|
-
let [l, r, t, b] =
|
|
6148
|
+
if (scaledSW < 2) {
|
|
6149
|
+
let [l, r, t, b] = calcBox(x, y, sw, sw, 'corner');
|
|
6128
6150
|
addRect(l, t, r, t, r, b, l, b, ci, ti);
|
|
6129
6151
|
} else {
|
|
6130
|
-
let n = getArcSegments(
|
|
6152
|
+
let n = getArcSegments(scaledSW);
|
|
6131
6153
|
sw /= 2;
|
|
6132
6154
|
addArc(x, -y, sw, sw, 0, TAU, n, ci, ti);
|
|
6133
6155
|
}
|
|
6134
6156
|
};
|
|
6135
6157
|
|
|
6136
|
-
|
|
6137
|
-
|
|
6138
|
-
|
|
6158
|
+
let _strokeCap = 'round',
|
|
6159
|
+
_strokeJoin = 'round';
|
|
6160
|
+
|
|
6161
|
+
$.strokeCap = (x) => (_strokeCap = x);
|
|
6162
|
+
$.strokeJoin = (x) => (_strokeJoin = x);
|
|
6139
6163
|
$.lineMode = () => {
|
|
6140
|
-
|
|
6141
|
-
|
|
6164
|
+
_strokeCap = 'square';
|
|
6165
|
+
_strokeJoin = 'none';
|
|
6142
6166
|
};
|
|
6143
6167
|
|
|
6144
6168
|
$.line = (x1, y1, x2, y2) => {
|
|
6145
|
-
if (
|
|
6146
|
-
let ti =
|
|
6147
|
-
ci =
|
|
6148
|
-
sw = $._strokeWeight,
|
|
6149
|
-
hsw = $._hsw;
|
|
6169
|
+
if (matrixDirty) saveMatrix();
|
|
6170
|
+
let ti = matrixIdx,
|
|
6171
|
+
ci = strokeIdx;
|
|
6150
6172
|
|
|
6151
6173
|
// calculate the direction vector and length
|
|
6152
6174
|
let dx = x2 - x1,
|
|
@@ -6159,8 +6181,8 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6159
6181
|
|
|
6160
6182
|
addRect(x1 + px, -y1 - py, x1 - px, -y1 + py, x2 - px, -y2 + py, x2 + px, -y2 - py, ci, ti);
|
|
6161
6183
|
|
|
6162
|
-
if (
|
|
6163
|
-
let n = getArcSegments(
|
|
6184
|
+
if (scaledSW > 2 && _strokeCap != 'square') {
|
|
6185
|
+
let n = getArcSegments(scaledSW);
|
|
6164
6186
|
addArc(x1, -y1, hsw, hsw, 0, TAU, n, ci, ti);
|
|
6165
6187
|
addArc(x2, -y2, hsw, hsw, 0, TAU, n, ci, ti);
|
|
6166
6188
|
}
|
|
@@ -6183,19 +6205,19 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6183
6205
|
};
|
|
6184
6206
|
|
|
6185
6207
|
$.vertex = (x, y) => {
|
|
6186
|
-
if (
|
|
6187
|
-
sv.push(x, -y,
|
|
6208
|
+
if (matrixDirty) saveMatrix();
|
|
6209
|
+
sv.push(x, -y, fillIdx, matrixIdx);
|
|
6188
6210
|
shapeVertCount++;
|
|
6189
6211
|
};
|
|
6190
6212
|
|
|
6191
6213
|
$.curveVertex = (x, y) => {
|
|
6192
|
-
if (
|
|
6214
|
+
if (matrixDirty) saveMatrix();
|
|
6193
6215
|
curveVertices.push({ x: x, y: -y });
|
|
6194
6216
|
};
|
|
6195
6217
|
|
|
6196
6218
|
$.bezierVertex = function (cx1, cy1, cx2, cy2, x, y) {
|
|
6197
6219
|
if (shapeVertCount === 0) throw new Error('Shape needs a vertex()');
|
|
6198
|
-
if (
|
|
6220
|
+
if (matrixDirty) saveMatrix();
|
|
6199
6221
|
|
|
6200
6222
|
// Get the last vertex as the starting point (P₀)
|
|
6201
6223
|
let prevIndex = (shapeVertCount - 1) * 4;
|
|
@@ -6231,7 +6253,7 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6231
6253
|
vy = mt3 * startY + 3 * mt2 * t * -cy1 + 3 * mt * t2 * -cy2 + t3 * -y;
|
|
6232
6254
|
}
|
|
6233
6255
|
|
|
6234
|
-
sv.push(vx, vy,
|
|
6256
|
+
sv.push(vx, vy, fillIdx, matrixIdx);
|
|
6235
6257
|
shapeVertCount++;
|
|
6236
6258
|
}
|
|
6237
6259
|
};
|
|
@@ -6278,7 +6300,7 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6278
6300
|
(2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * t2 +
|
|
6279
6301
|
(-p0.y + 3 * p1.y - 3 * p2.y + p3.y) * t3);
|
|
6280
6302
|
|
|
6281
|
-
sv.push(x, y,
|
|
6303
|
+
sv.push(x, y, fillIdx, matrixIdx);
|
|
6282
6304
|
shapeVertCount++;
|
|
6283
6305
|
}
|
|
6284
6306
|
}
|
|
@@ -6304,14 +6326,14 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6304
6326
|
}
|
|
6305
6327
|
}
|
|
6306
6328
|
|
|
6307
|
-
if (
|
|
6329
|
+
if (doFill) {
|
|
6308
6330
|
if (shapeVertCount == 5) {
|
|
6309
6331
|
// for quads, draw two triangles
|
|
6310
6332
|
addVert(sv[0], sv[1], sv[2], sv[3]); // v0
|
|
6311
6333
|
addVert(sv[4], sv[5], sv[6], sv[7]); // v1
|
|
6312
6334
|
addVert(sv[12], sv[13], sv[14], sv[15]); // v3
|
|
6313
6335
|
addVert(sv[8], sv[9], sv[10], sv[11]); // v2
|
|
6314
|
-
drawStack.push(
|
|
6336
|
+
drawStack.push(shapesPL, 4);
|
|
6315
6337
|
} else {
|
|
6316
6338
|
// triangulate the shape
|
|
6317
6339
|
for (let i = 1; i < shapeVertCount - 1; i++) {
|
|
@@ -6323,29 +6345,28 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6323
6345
|
addVert(sv[v1], sv[v1 + 1], sv[v1 + 2], sv[v1 + 3]);
|
|
6324
6346
|
addVert(sv[v2], sv[v2 + 1], sv[v2 + 2], sv[v2 + 3]);
|
|
6325
6347
|
}
|
|
6326
|
-
drawStack.push(
|
|
6348
|
+
drawStack.push(shapesPL, (shapeVertCount - 2) * 3);
|
|
6327
6349
|
}
|
|
6328
6350
|
}
|
|
6329
6351
|
|
|
6330
|
-
if (
|
|
6331
|
-
let
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
$._strokeCap = 'square';
|
|
6352
|
+
if (doStroke) {
|
|
6353
|
+
let n = getArcSegments(scaledSW),
|
|
6354
|
+
ti = matrixIdx,
|
|
6355
|
+
ogStrokeCap = _strokeCap;
|
|
6356
|
+
_strokeCap = 'square';
|
|
6336
6357
|
// draw lines between vertices
|
|
6337
6358
|
for (let i = 0; i < shapeVertCount - 1; i++) {
|
|
6338
6359
|
let v1 = i * 4;
|
|
6339
6360
|
let v2 = (i + 1) * 4;
|
|
6340
6361
|
$.line(sv[v1], -sv[v1 + 1], sv[v2], -sv[v2 + 1]);
|
|
6341
6362
|
|
|
6342
|
-
addArc(sv[v1], sv[v1 + 1], hsw, hsw, 0, TAU, n,
|
|
6363
|
+
addArc(sv[v1], sv[v1 + 1], hsw, hsw, 0, TAU, n, strokeIdx, ti);
|
|
6343
6364
|
}
|
|
6344
6365
|
let v1 = (shapeVertCount - 1) * 4;
|
|
6345
6366
|
let v2 = 0;
|
|
6346
6367
|
if (close) $.line(sv[v1], -sv[v1 + 1], sv[v2], -sv[v2 + 1]);
|
|
6347
|
-
addArc(sv[v1], sv[v1 + 1], hsw, hsw, 0, TAU, n,
|
|
6348
|
-
|
|
6368
|
+
addArc(sv[v1], sv[v1 + 1], hsw, hsw, 0, TAU, n, strokeIdx, ti);
|
|
6369
|
+
_strokeCap = ogStrokeCap;
|
|
6349
6370
|
}
|
|
6350
6371
|
|
|
6351
6372
|
// reset for the next shape
|
|
@@ -6390,87 +6411,88 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6390
6411
|
$._hooks.prerender.push(() => {
|
|
6391
6412
|
$._pass.setPipeline($._pipelines[1]);
|
|
6392
6413
|
|
|
6393
|
-
let
|
|
6394
|
-
size:
|
|
6414
|
+
let shapesVertBuff = Q5.device.createBuffer({
|
|
6415
|
+
size: shapesVertIdx * 4,
|
|
6395
6416
|
usage: GPUBufferUsage.VERTEX,
|
|
6396
6417
|
mappedAtCreation: true
|
|
6397
6418
|
});
|
|
6398
6419
|
|
|
6399
|
-
new Float32Array(
|
|
6400
|
-
|
|
6420
|
+
new Float32Array(shapesVertBuff.getMappedRange()).set(shapesVertStack.slice(0, shapesVertIdx));
|
|
6421
|
+
shapesVertBuff.unmap();
|
|
6401
6422
|
|
|
6402
|
-
$._pass.setVertexBuffer(0,
|
|
6423
|
+
$._pass.setVertexBuffer(0, shapesVertBuff);
|
|
6403
6424
|
|
|
6404
|
-
$._buffers.push(
|
|
6425
|
+
$._buffers.push(shapesVertBuff);
|
|
6405
6426
|
});
|
|
6406
6427
|
|
|
6407
6428
|
$._hooks.postrender.push(() => {
|
|
6408
|
-
|
|
6429
|
+
shapesVertIdx = 0;
|
|
6409
6430
|
});
|
|
6410
|
-
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
|
|
6431
|
+
|
|
6432
|
+
/* IMAGE */
|
|
6433
|
+
|
|
6434
|
+
let imagePL = 2,
|
|
6435
|
+
videoPL = 3;
|
|
6414
6436
|
|
|
6415
6437
|
$._imageShaderCode =
|
|
6416
6438
|
$._baseShaderCode +
|
|
6417
6439
|
/* wgsl */ `
|
|
6418
|
-
struct VertexParams {
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
}
|
|
6426
|
-
struct FragParams {
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
}
|
|
6432
|
-
|
|
6433
|
-
@group(0) @binding(0) var<uniform> q: Q5;
|
|
6434
|
-
@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;
|
|
6435
|
-
@group(0) @binding(2) var<storage> colors : array<vec4f>;
|
|
6436
|
-
|
|
6437
|
-
@group(1) @binding(0) var samp: sampler;
|
|
6438
|
-
@group(1) @binding(1) var tex: texture_2d<f32>;
|
|
6439
|
-
|
|
6440
|
-
fn transformVertex(pos: vec2f, matrixIndex: f32) -> vec4f {
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
}
|
|
6447
|
-
|
|
6448
|
-
fn applyTint(texColor: vec4f, tintColor: vec4f) -> vec4f {
|
|
6449
|
-
|
|
6450
|
-
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
}
|
|
6454
|
-
|
|
6455
|
-
@vertex
|
|
6456
|
-
fn vertexMain(v: VertexParams) -> FragParams {
|
|
6457
|
-
|
|
6458
|
-
|
|
6459
|
-
|
|
6460
|
-
|
|
6461
|
-
|
|
6462
|
-
|
|
6463
|
-
|
|
6464
|
-
|
|
6465
|
-
}
|
|
6466
|
-
|
|
6467
|
-
@fragment
|
|
6468
|
-
fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
6469
|
-
|
|
6470
|
-
|
|
6471
|
-
|
|
6472
|
-
}
|
|
6473
|
-
`;
|
|
6440
|
+
struct VertexParams {
|
|
6441
|
+
@builtin(vertex_index) vertexIndex : u32,
|
|
6442
|
+
@location(0) pos: vec2f,
|
|
6443
|
+
@location(1) texCoord: vec2f,
|
|
6444
|
+
@location(2) tintIndex: f32,
|
|
6445
|
+
@location(3) matrixIndex: f32,
|
|
6446
|
+
@location(4) imageAlpha: f32
|
|
6447
|
+
}
|
|
6448
|
+
struct FragParams {
|
|
6449
|
+
@builtin(position) position: vec4f,
|
|
6450
|
+
@location(0) texCoord: vec2f,
|
|
6451
|
+
@location(1) tintColor: vec4f,
|
|
6452
|
+
@location(2) imageAlpha: f32
|
|
6453
|
+
}
|
|
6454
|
+
|
|
6455
|
+
@group(0) @binding(0) var<uniform> q: Q5;
|
|
6456
|
+
@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;
|
|
6457
|
+
@group(0) @binding(2) var<storage> colors : array<vec4f>;
|
|
6458
|
+
|
|
6459
|
+
@group(1) @binding(0) var samp: sampler;
|
|
6460
|
+
@group(1) @binding(1) var tex: texture_2d<f32>;
|
|
6461
|
+
|
|
6462
|
+
fn transformVertex(pos: vec2f, matrixIndex: f32) -> vec4f {
|
|
6463
|
+
var vert = vec4f(pos, 0f, 1f);
|
|
6464
|
+
vert = transforms[i32(matrixIndex)] * vert;
|
|
6465
|
+
vert.x /= q.halfWidth;
|
|
6466
|
+
vert.y /= q.halfHeight;
|
|
6467
|
+
return vert;
|
|
6468
|
+
}
|
|
6469
|
+
|
|
6470
|
+
fn applyTint(texColor: vec4f, tintColor: vec4f) -> vec4f {
|
|
6471
|
+
// apply the tint color to the sampled texture color at full strength
|
|
6472
|
+
let tinted = vec4f(texColor.rgb * tintColor.rgb, texColor.a);
|
|
6473
|
+
// mix in the tint using the tint alpha as the blend strength
|
|
6474
|
+
return mix(texColor, tinted, tintColor.a);
|
|
6475
|
+
}
|
|
6476
|
+
|
|
6477
|
+
@vertex
|
|
6478
|
+
fn vertexMain(v: VertexParams) -> FragParams {
|
|
6479
|
+
var vert = transformVertex(v.pos, v.matrixIndex);
|
|
6480
|
+
|
|
6481
|
+
var f: FragParams;
|
|
6482
|
+
f.position = vert;
|
|
6483
|
+
f.texCoord = v.texCoord;
|
|
6484
|
+
f.tintColor = colors[i32(v.tintIndex)];
|
|
6485
|
+
f.imageAlpha = v.imageAlpha;
|
|
6486
|
+
return f;
|
|
6487
|
+
}
|
|
6488
|
+
|
|
6489
|
+
@fragment
|
|
6490
|
+
fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
6491
|
+
var texColor = textureSample(tex, samp, f.texCoord);
|
|
6492
|
+
texColor.a *= f.imageAlpha;
|
|
6493
|
+
return applyTint(texColor, f.tintColor);
|
|
6494
|
+
}
|
|
6495
|
+
`;
|
|
6474
6496
|
|
|
6475
6497
|
let imageShader = Q5.device.createShaderModule({
|
|
6476
6498
|
label: 'imageShader',
|
|
@@ -6486,10 +6508,10 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6486
6508
|
code: $._videoShaderCode
|
|
6487
6509
|
});
|
|
6488
6510
|
|
|
6489
|
-
let
|
|
6490
|
-
|
|
6511
|
+
let imgVertStack = new Float32Array($._graphics ? 1000 : 1e7),
|
|
6512
|
+
imgVertIdx = 0;
|
|
6491
6513
|
|
|
6492
|
-
let
|
|
6514
|
+
let imgVertBuffLayout = {
|
|
6493
6515
|
arrayStride: 28,
|
|
6494
6516
|
attributes: [
|
|
6495
6517
|
{ shaderLocation: 0, offset: 0, format: 'float32x2' },
|
|
@@ -6548,7 +6570,7 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6548
6570
|
vertex: {
|
|
6549
6571
|
module: imageShader,
|
|
6550
6572
|
entryPoint: 'vertexMain',
|
|
6551
|
-
buffers: [{ arrayStride: 0, attributes: [] },
|
|
6573
|
+
buffers: [{ arrayStride: 0, attributes: [] }, imgVertBuffLayout]
|
|
6552
6574
|
},
|
|
6553
6575
|
fragment: {
|
|
6554
6576
|
module: imageShader,
|
|
@@ -6567,7 +6589,7 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6567
6589
|
vertex: {
|
|
6568
6590
|
module: videoShader,
|
|
6569
6591
|
entryPoint: 'vertexMain',
|
|
6570
|
-
buffers: [{ arrayStride: 0, attributes: [] },
|
|
6592
|
+
buffers: [{ arrayStride: 0, attributes: [] }, imgVertBuffLayout]
|
|
6571
6593
|
},
|
|
6572
6594
|
fragment: {
|
|
6573
6595
|
module: videoShader,
|
|
@@ -6747,11 +6769,13 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6747
6769
|
return g;
|
|
6748
6770
|
};
|
|
6749
6771
|
|
|
6750
|
-
|
|
6772
|
+
let _imageMode = 'corner';
|
|
6773
|
+
|
|
6774
|
+
$.imageMode = (x) => (_imageMode = x);
|
|
6751
6775
|
|
|
6752
|
-
const
|
|
6753
|
-
let s =
|
|
6754
|
-
i =
|
|
6776
|
+
const addImgVert = (x, y, u, v, ci, ti, ia) => {
|
|
6777
|
+
let s = imgVertStack,
|
|
6778
|
+
i = imgVertIdx;
|
|
6755
6779
|
s[i++] = x;
|
|
6756
6780
|
s[i++] = y;
|
|
6757
6781
|
s[i++] = u;
|
|
@@ -6759,7 +6783,7 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6759
6783
|
s[i++] = ci;
|
|
6760
6784
|
s[i++] = ti;
|
|
6761
6785
|
s[i++] = ia;
|
|
6762
|
-
|
|
6786
|
+
imgVertIdx = i;
|
|
6763
6787
|
};
|
|
6764
6788
|
|
|
6765
6789
|
$.image = (img, dx = 0, dy = 0, dw, dh, sx = 0, sy = 0, sw, sh) => {
|
|
@@ -6770,7 +6794,7 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6770
6794
|
if (img.flipped) $.scale(-1, 1);
|
|
6771
6795
|
}
|
|
6772
6796
|
|
|
6773
|
-
if (
|
|
6797
|
+
if (matrixDirty) saveMatrix();
|
|
6774
6798
|
|
|
6775
6799
|
let cnv = img.canvas || img,
|
|
6776
6800
|
w = cnv.width,
|
|
@@ -6800,23 +6824,23 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6800
6824
|
sx *= pd;
|
|
6801
6825
|
sy *= pd;
|
|
6802
6826
|
|
|
6803
|
-
let [l, r, t, b] =
|
|
6827
|
+
let [l, r, t, b] = calcBox(dx, dy, dw, dh, _imageMode);
|
|
6804
6828
|
|
|
6805
6829
|
let u0 = sx / w,
|
|
6806
6830
|
v0 = sy / h,
|
|
6807
6831
|
u1 = (sx + sw) / w,
|
|
6808
6832
|
v1 = (sy + sh) / h,
|
|
6809
|
-
ti =
|
|
6810
|
-
ci =
|
|
6811
|
-
ia =
|
|
6833
|
+
ti = matrixIdx,
|
|
6834
|
+
ci = tintIdx,
|
|
6835
|
+
ia = globalAlpha;
|
|
6812
6836
|
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
|
|
6837
|
+
addImgVert(l, t, u0, v0, ci, ti, ia);
|
|
6838
|
+
addImgVert(r, t, u1, v0, ci, ti, ia);
|
|
6839
|
+
addImgVert(l, b, u0, v1, ci, ti, ia);
|
|
6840
|
+
addImgVert(r, b, u1, v1, ci, ti, ia);
|
|
6817
6841
|
|
|
6818
6842
|
if (!isVideo) {
|
|
6819
|
-
|
|
6843
|
+
drawStack.push(imagePL, img._texture.index);
|
|
6820
6844
|
|
|
6821
6845
|
if (makeFrame) {
|
|
6822
6846
|
img.resetMatrix();
|
|
@@ -6839,55 +6863,47 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
6839
6863
|
})
|
|
6840
6864
|
);
|
|
6841
6865
|
|
|
6842
|
-
|
|
6866
|
+
drawStack.push(videoPL, $._textureBindGroups.length - 1);
|
|
6843
6867
|
|
|
6844
6868
|
if (img.flipped) $.scale(-1, 1);
|
|
6845
6869
|
}
|
|
6846
6870
|
};
|
|
6847
6871
|
|
|
6848
6872
|
$._hooks.prerender.push(() => {
|
|
6849
|
-
if (!
|
|
6873
|
+
if (!imgVertIdx) return;
|
|
6850
6874
|
|
|
6851
6875
|
// Switch to image pipeline
|
|
6852
6876
|
$._pass.setPipeline($._pipelines[2]);
|
|
6853
6877
|
|
|
6854
|
-
let
|
|
6855
|
-
size:
|
|
6878
|
+
let imgVertBuff = Q5.device.createBuffer({
|
|
6879
|
+
size: imgVertIdx * 5,
|
|
6856
6880
|
usage: GPUBufferUsage.VERTEX,
|
|
6857
6881
|
mappedAtCreation: true
|
|
6858
6882
|
});
|
|
6859
6883
|
|
|
6860
|
-
new Float32Array(
|
|
6861
|
-
|
|
6884
|
+
new Float32Array(imgVertBuff.getMappedRange()).set(imgVertStack.slice(0, imgVertIdx));
|
|
6885
|
+
imgVertBuff.unmap();
|
|
6862
6886
|
|
|
6863
|
-
$._pass.setVertexBuffer(1,
|
|
6887
|
+
$._pass.setVertexBuffer(1, imgVertBuff);
|
|
6864
6888
|
|
|
6865
|
-
$._buffers.push(
|
|
6889
|
+
$._buffers.push(imgVertBuff);
|
|
6866
6890
|
|
|
6867
6891
|
if (vidFrames) {
|
|
6868
6892
|
// Switch to video pipeline
|
|
6869
6893
|
$._pass.setPipeline($._pipelines[3]);
|
|
6870
|
-
$._pass.setVertexBuffer(1,
|
|
6894
|
+
$._pass.setVertexBuffer(1, imgVertBuff);
|
|
6871
6895
|
}
|
|
6872
6896
|
});
|
|
6873
6897
|
|
|
6874
6898
|
$._hooks.postrender.push(() => {
|
|
6875
|
-
|
|
6899
|
+
imgVertIdx = 0;
|
|
6876
6900
|
$._textureBindGroups.splice(tIdx, vidFrames);
|
|
6877
6901
|
vidFrames = 0;
|
|
6878
6902
|
});
|
|
6879
|
-
};
|
|
6880
6903
|
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
Q5.INVERT = 4;
|
|
6885
|
-
Q5.POSTERIZE = 5;
|
|
6886
|
-
Q5.DILATE = 6;
|
|
6887
|
-
Q5.ERODE = 7;
|
|
6888
|
-
Q5.BLUR = 8;
|
|
6889
|
-
Q5.renderers.webgpu.text = ($, q) => {
|
|
6890
|
-
$._textPL = 4;
|
|
6904
|
+
/* TEXT */
|
|
6905
|
+
|
|
6906
|
+
let textPL = 4;
|
|
6891
6907
|
|
|
6892
6908
|
$._textShaderCode =
|
|
6893
6909
|
$._baseShaderCode +
|
|
@@ -7223,10 +7239,10 @@ fn fragMain(f : FragParams) -> @location(0) vec4f {
|
|
|
7223
7239
|
return $.loadFont(url, cb);
|
|
7224
7240
|
};
|
|
7225
7241
|
|
|
7226
|
-
|
|
7227
|
-
|
|
7228
|
-
|
|
7229
|
-
|
|
7242
|
+
let _textSize = 18,
|
|
7243
|
+
_textAlign = 'left',
|
|
7244
|
+
_textBaseline = 'alphabetic',
|
|
7245
|
+
leadingSet = false,
|
|
7230
7246
|
leading = 22.5,
|
|
7231
7247
|
leadDiff = 4.5,
|
|
7232
7248
|
leadPercent = 1.25;
|
|
@@ -7240,8 +7256,8 @@ fn fragMain(f : FragParams) -> @location(0) vec4f {
|
|
|
7240
7256
|
};
|
|
7241
7257
|
|
|
7242
7258
|
$.textSize = (size) => {
|
|
7243
|
-
if (size == undefined) return
|
|
7244
|
-
|
|
7259
|
+
if (size == undefined) return _textSize;
|
|
7260
|
+
_textSize = size;
|
|
7245
7261
|
if (!leadingSet) {
|
|
7246
7262
|
leading = size * leadPercent;
|
|
7247
7263
|
leadDiff = leading - size;
|
|
@@ -7264,7 +7280,7 @@ fn fragMain(f : FragParams) -> @location(0) vec4f {
|
|
|
7264
7280
|
};
|
|
7265
7281
|
|
|
7266
7282
|
// ranges from 0.35 (black) to 0.65 (thin)
|
|
7267
|
-
|
|
7283
|
+
let textEdge = 0.5;
|
|
7268
7284
|
|
|
7269
7285
|
$.textWeight = (weight) => {
|
|
7270
7286
|
if (!weight) return $._textWeight;
|
|
@@ -7272,19 +7288,19 @@ fn fragMain(f : FragParams) -> @location(0) vec4f {
|
|
|
7272
7288
|
weight = weights[weight.toLowerCase().replace(/[ _-]/g, '')];
|
|
7273
7289
|
if (!weight) throw new Error(`Invalid font weight: ${weight}`);
|
|
7274
7290
|
}
|
|
7275
|
-
|
|
7291
|
+
textEdge = 0.6875 - weight * 0.000375;
|
|
7276
7292
|
};
|
|
7277
7293
|
|
|
7278
7294
|
$.textLeading = (lineHeight) => {
|
|
7279
7295
|
$._font.lineHeight = leading = lineHeight;
|
|
7280
|
-
leadDiff = leading -
|
|
7281
|
-
leadPercent = leading /
|
|
7296
|
+
leadDiff = leading - _textSize;
|
|
7297
|
+
leadPercent = leading / _textSize;
|
|
7282
7298
|
leadingSet = true;
|
|
7283
7299
|
};
|
|
7284
7300
|
|
|
7285
7301
|
$.textAlign = (horiz, vert) => {
|
|
7286
|
-
|
|
7287
|
-
if (vert)
|
|
7302
|
+
_textAlign = horiz;
|
|
7303
|
+
if (vert) _textBaseline = vert;
|
|
7288
7304
|
};
|
|
7289
7305
|
|
|
7290
7306
|
let charStack = [],
|
|
@@ -7383,8 +7399,8 @@ fn fragMain(f : FragParams) -> @location(0) vec4f {
|
|
|
7383
7399
|
|
|
7384
7400
|
let charsData = [];
|
|
7385
7401
|
|
|
7386
|
-
let ta =
|
|
7387
|
-
tb =
|
|
7402
|
+
let ta = _textAlign,
|
|
7403
|
+
tb = _textBaseline,
|
|
7388
7404
|
textIndex = textStack.length,
|
|
7389
7405
|
o = 0, // offset
|
|
7390
7406
|
measurements;
|
|
@@ -7398,8 +7414,8 @@ fn fragMain(f : FragParams) -> @location(0) vec4f {
|
|
|
7398
7414
|
o += 4;
|
|
7399
7415
|
});
|
|
7400
7416
|
|
|
7401
|
-
if (tb == 'alphabetic') y -=
|
|
7402
|
-
else if (tb == 'center') y -=
|
|
7417
|
+
if (tb == 'alphabetic') y -= _textSize;
|
|
7418
|
+
else if (tb == 'center') y -= _textSize * 0.5;
|
|
7403
7419
|
else if (tb == 'bottom') y -= leading;
|
|
7404
7420
|
} else {
|
|
7405
7421
|
// measure the text to get the line widths before setting
|
|
@@ -7407,7 +7423,7 @@ fn fragMain(f : FragParams) -> @location(0) vec4f {
|
|
|
7407
7423
|
measurements = measureText($._font, str);
|
|
7408
7424
|
|
|
7409
7425
|
let offsetY = 0;
|
|
7410
|
-
if (tb == 'alphabetic') y -=
|
|
7426
|
+
if (tb == 'alphabetic') y -= _textSize;
|
|
7411
7427
|
else if (tb == 'center') offsetY = measurements.height * 0.5;
|
|
7412
7428
|
else if (tb == 'bottom') offsetY = measurements.height;
|
|
7413
7429
|
|
|
@@ -7429,19 +7445,19 @@ fn fragMain(f : FragParams) -> @location(0) vec4f {
|
|
|
7429
7445
|
|
|
7430
7446
|
let txt = [];
|
|
7431
7447
|
|
|
7432
|
-
if (
|
|
7448
|
+
if (matrixDirty) saveMatrix();
|
|
7433
7449
|
|
|
7434
7450
|
txt[0] = x;
|
|
7435
7451
|
txt[1] = -y;
|
|
7436
|
-
txt[2] =
|
|
7437
|
-
txt[3] =
|
|
7438
|
-
txt[4] =
|
|
7439
|
-
txt[5] =
|
|
7440
|
-
txt[6] =
|
|
7441
|
-
txt[7] =
|
|
7452
|
+
txt[2] = _textSize / 42;
|
|
7453
|
+
txt[3] = matrixIdx;
|
|
7454
|
+
txt[4] = doFill && fillSet ? fillIdx : 0;
|
|
7455
|
+
txt[5] = strokeIdx;
|
|
7456
|
+
txt[6] = doStroke && strokeSet ? sw : 0;
|
|
7457
|
+
txt[7] = textEdge;
|
|
7442
7458
|
|
|
7443
7459
|
textStack.push(txt);
|
|
7444
|
-
|
|
7460
|
+
drawStack.push(textPL, measurements.printedCharCount, $._font.index);
|
|
7445
7461
|
};
|
|
7446
7462
|
|
|
7447
7463
|
$.textWidth = (str) => {
|
|
@@ -7450,15 +7466,15 @@ fn fragMain(f : FragParams) -> @location(0) vec4f {
|
|
|
7450
7466
|
};
|
|
7451
7467
|
|
|
7452
7468
|
$.createTextImage = (str, w, h) => {
|
|
7453
|
-
$._g.textSize(
|
|
7469
|
+
$._g.textSize(_textSize);
|
|
7454
7470
|
|
|
7455
|
-
if (
|
|
7456
|
-
let fi =
|
|
7457
|
-
$._g.fill(
|
|
7471
|
+
if (doFill && fillSet) {
|
|
7472
|
+
let fi = fillIdx * 4;
|
|
7473
|
+
$._g.fill(colorStack.slice(fi, fi + 4));
|
|
7458
7474
|
}
|
|
7459
|
-
if (
|
|
7460
|
-
let si =
|
|
7461
|
-
$._g.stroke(
|
|
7475
|
+
if (doStroke && strokeSet) {
|
|
7476
|
+
let si = strokeIdx * 4;
|
|
7477
|
+
$._g.stroke(colorStack.slice(si, si + 4));
|
|
7462
7478
|
}
|
|
7463
7479
|
|
|
7464
7480
|
let g = $._g.createTextImage(str, w, h);
|
|
@@ -7469,21 +7485,21 @@ fn fragMain(f : FragParams) -> @location(0) vec4f {
|
|
|
7469
7485
|
$.textImage = (img, x, y) => {
|
|
7470
7486
|
if (typeof img == 'string') img = $.createTextImage(img);
|
|
7471
7487
|
|
|
7472
|
-
let og =
|
|
7473
|
-
|
|
7488
|
+
let og = _imageMode;
|
|
7489
|
+
_imageMode = 'corner';
|
|
7474
7490
|
|
|
7475
|
-
let ta =
|
|
7491
|
+
let ta = _textAlign;
|
|
7476
7492
|
if (ta == 'center') x -= img.canvas.hw;
|
|
7477
7493
|
else if (ta == 'right') x -= img.width;
|
|
7478
7494
|
|
|
7479
|
-
let bl =
|
|
7495
|
+
let bl = _textBaseline;
|
|
7480
7496
|
if (bl == 'alphabetic') y -= img._leading;
|
|
7481
7497
|
else if (bl == 'center') y -= img._middle;
|
|
7482
7498
|
else if (bl == 'bottom') y -= img._bottom;
|
|
7483
7499
|
else if (bl == 'top') y -= img._top;
|
|
7484
7500
|
|
|
7485
7501
|
$.image(img, x, y);
|
|
7486
|
-
|
|
7502
|
+
_imageMode = og;
|
|
7487
7503
|
};
|
|
7488
7504
|
|
|
7489
7505
|
$._hooks.prerender.push(() => {
|
|
@@ -7538,8 +7554,9 @@ fn fragMain(f : FragParams) -> @location(0) vec4f {
|
|
|
7538
7554
|
charStack = [];
|
|
7539
7555
|
textStack = [];
|
|
7540
7556
|
});
|
|
7541
|
-
|
|
7542
|
-
|
|
7557
|
+
|
|
7558
|
+
/* SHADERS */
|
|
7559
|
+
|
|
7543
7560
|
let pipelineTypes = ['frame', 'shapes', 'image', 'video', 'text'];
|
|
7544
7561
|
|
|
7545
7562
|
let plCounters = {
|
|
@@ -7597,20 +7614,69 @@ Q5.renderers.webgpu.shaders = ($) => {
|
|
|
7597
7614
|
$.createTextShader = (code) => $._createShader(code, 'text');
|
|
7598
7615
|
|
|
7599
7616
|
$.shader = (shader) => {
|
|
7600
|
-
|
|
7601
|
-
|
|
7602
|
-
};
|
|
7617
|
+
let type = shader.type;
|
|
7618
|
+
let idx = shader.pipelineIndex;
|
|
7603
7619
|
|
|
7604
|
-
|
|
7605
|
-
|
|
7606
|
-
|
|
7620
|
+
if (type == 'frame') {
|
|
7621
|
+
if (shader.applyBeforeDraw) prevFramePL = idx;
|
|
7622
|
+
else framePL = idx;
|
|
7623
|
+
} else if (type == 'shapes') shapesPL = idx;
|
|
7624
|
+
else if (type == 'image') imagePL = idx;
|
|
7625
|
+
else if (type == 'video') videoPL = idx;
|
|
7626
|
+
else if (type == 'text') textPL = idx;
|
|
7607
7627
|
};
|
|
7608
7628
|
|
|
7629
|
+
$.resetShader = $.resetShapesShader = () => (shapesPL = 1);
|
|
7630
|
+
$.resetFrameShader = () => (prevFramePL = framePL = 0);
|
|
7631
|
+
$.resetImageShader = () => (imagePL = 2);
|
|
7632
|
+
$.resetVideoShader = () => (videoPL = 3);
|
|
7633
|
+
$.resetTextShader = () => (textPL = 4);
|
|
7634
|
+
|
|
7609
7635
|
$.resetShaders = () => {
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
|
|
7613
|
-
|
|
7614
|
-
|
|
7636
|
+
prevFramePL = framePL = 0;
|
|
7637
|
+
shapesPL = 1;
|
|
7638
|
+
imagePL = 2;
|
|
7639
|
+
videoPL = 3;
|
|
7640
|
+
textPL = 4;
|
|
7615
7641
|
};
|
|
7616
7642
|
};
|
|
7643
|
+
|
|
7644
|
+
Q5.THRESHOLD = 1;
|
|
7645
|
+
Q5.GRAY = 2;
|
|
7646
|
+
Q5.OPAQUE = 3;
|
|
7647
|
+
Q5.INVERT = 4;
|
|
7648
|
+
Q5.POSTERIZE = 5;
|
|
7649
|
+
Q5.DILATE = 6;
|
|
7650
|
+
Q5.ERODE = 7;
|
|
7651
|
+
Q5.BLUR = 8;
|
|
7652
|
+
|
|
7653
|
+
Q5.initWebGPU = async () => {
|
|
7654
|
+
if (!navigator.gpu) {
|
|
7655
|
+
console.warn('q5 WebGPU not supported on this browser! Use Google Chrome or Edge.');
|
|
7656
|
+
return false;
|
|
7657
|
+
}
|
|
7658
|
+
if (!Q5.requestedGPU) {
|
|
7659
|
+
let adapter = await navigator.gpu.requestAdapter();
|
|
7660
|
+
if (!adapter) {
|
|
7661
|
+
console.warn('q5 WebGPU could not start! No appropriate GPUAdapter found, vulkan may need to be enabled.');
|
|
7662
|
+
return false;
|
|
7663
|
+
}
|
|
7664
|
+
Q5.device = await adapter.requestDevice();
|
|
7665
|
+
|
|
7666
|
+
Q5.device.lost.then((e) => {
|
|
7667
|
+
console.error('WebGPU crashed!');
|
|
7668
|
+
console.error(e);
|
|
7669
|
+
});
|
|
7670
|
+
}
|
|
7671
|
+
return true;
|
|
7672
|
+
};
|
|
7673
|
+
|
|
7674
|
+
Q5.WebGPU = async function (scope, parent) {
|
|
7675
|
+
if (!scope || scope == 'global') Q5._hasGlobal = true;
|
|
7676
|
+
if (!(await Q5.initWebGPU())) {
|
|
7677
|
+
return new Q5(scope, parent, 'webgpu-fallback');
|
|
7678
|
+
}
|
|
7679
|
+
return new Q5(scope, parent, 'webgpu');
|
|
7680
|
+
};
|
|
7681
|
+
|
|
7682
|
+
Q5.webgpu = Q5.WebGPU;
|