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