q5 2.12.12 → 2.13.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/package.json +1 -1
- package/q5.js +162 -129
- package/q5.min.js +2 -2
- package/src/q5-core.js +1 -1
- package/src/q5-webgpu-canvas.js +69 -50
- package/src/q5-webgpu-drawing.js +9 -9
- package/src/q5-webgpu-image.js +74 -58
- package/src/q5-webgpu-text.js +9 -11
package/package.json
CHANGED
package/q5.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* q5.js
|
|
3
|
-
* @version 2.
|
|
3
|
+
* @version 2.13
|
|
4
4
|
* @author quinton-ashley, Tezumie, and LingDong-
|
|
5
5
|
* @license LGPL-3.0
|
|
6
6
|
* @class Q5
|
|
@@ -3594,6 +3594,9 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3594
3594
|
c.width = $.width = 500;
|
|
3595
3595
|
c.height = $.height = 500;
|
|
3596
3596
|
|
|
3597
|
+
// q2d graphics context
|
|
3598
|
+
$._g = $.createGraphics(1, 1);
|
|
3599
|
+
|
|
3597
3600
|
if ($.colorMode) $.colorMode('rgb', 1);
|
|
3598
3601
|
|
|
3599
3602
|
let pass,
|
|
@@ -3729,7 +3732,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3729
3732
|
};
|
|
3730
3733
|
|
|
3731
3734
|
$._stroke = 0;
|
|
3732
|
-
$._fill = 1;
|
|
3735
|
+
$._fill = $._tint = 1;
|
|
3733
3736
|
$._doFill = $._doStroke = true;
|
|
3734
3737
|
|
|
3735
3738
|
$.fill = (r, g, b, a) => {
|
|
@@ -3742,42 +3745,51 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3742
3745
|
$._doStroke = $._strokeSet = true;
|
|
3743
3746
|
$._stroke = colorIndex;
|
|
3744
3747
|
};
|
|
3748
|
+
$.tint = (r, g, b, a) => {
|
|
3749
|
+
addColor(r, g, b, a);
|
|
3750
|
+
$._tint = colorIndex;
|
|
3751
|
+
};
|
|
3745
3752
|
|
|
3746
3753
|
$.noFill = () => ($._doFill = false);
|
|
3747
3754
|
$.noStroke = () => ($._doStroke = false);
|
|
3755
|
+
$.noTint = () => ($._tint = 1);
|
|
3748
3756
|
|
|
3749
3757
|
$._strokeWeight = 1;
|
|
3750
3758
|
$.strokeWeight = (v) => ($._strokeWeight = Math.abs(v));
|
|
3751
3759
|
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
0, 1, 0, 0,
|
|
3759
|
-
0, 0, 1, 0,
|
|
3760
|
-
0, 0, 0, 1
|
|
3761
|
-
];
|
|
3762
|
-
$._transformIndex = 0;
|
|
3763
|
-
};
|
|
3764
|
-
$.resetMatrix();
|
|
3760
|
+
const MAX_TRANSFORMS = 1e7, // or whatever maximum you need
|
|
3761
|
+
MATRIX_SIZE = 16, // 4x4 matrix
|
|
3762
|
+
transforms = new Float32Array(MAX_TRANSFORMS * MATRIX_SIZE),
|
|
3763
|
+
matrices = [],
|
|
3764
|
+
matricesIndexStack = [];
|
|
3765
|
+
let matrix;
|
|
3765
3766
|
|
|
3766
3767
|
// tracks if the matrix has been modified
|
|
3767
3768
|
$._matrixDirty = false;
|
|
3768
3769
|
|
|
3769
|
-
//
|
|
3770
|
-
|
|
3770
|
+
// initialize with a 4x4 identity matrix
|
|
3771
|
+
// prettier-ignore
|
|
3772
|
+
matrices.push([
|
|
3773
|
+
1, 0, 0, 0,
|
|
3774
|
+
0, 1, 0, 0,
|
|
3775
|
+
0, 0, 1, 0,
|
|
3776
|
+
0, 0, 0, 1
|
|
3777
|
+
]);
|
|
3771
3778
|
|
|
3772
|
-
|
|
3773
|
-
|
|
3779
|
+
transforms.set(matrices[0]);
|
|
3780
|
+
|
|
3781
|
+
$.resetMatrix = () => {
|
|
3782
|
+
matrix = matrices[0].slice();
|
|
3783
|
+
$._matrixIndex = 0;
|
|
3784
|
+
};
|
|
3785
|
+
$.resetMatrix();
|
|
3774
3786
|
|
|
3775
3787
|
$.translate = (x, y, z) => {
|
|
3776
3788
|
if (!x && !y && !z) return;
|
|
3777
3789
|
// update the translation values
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3790
|
+
matrix[12] += x;
|
|
3791
|
+
matrix[13] -= y;
|
|
3792
|
+
matrix[14] += z || 0;
|
|
3781
3793
|
$._matrixDirty = true;
|
|
3782
3794
|
};
|
|
3783
3795
|
|
|
@@ -3788,7 +3800,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3788
3800
|
let cosR = Math.cos(a);
|
|
3789
3801
|
let sinR = Math.sin(a);
|
|
3790
3802
|
|
|
3791
|
-
let m =
|
|
3803
|
+
let m = matrix;
|
|
3792
3804
|
|
|
3793
3805
|
let m0 = m[0],
|
|
3794
3806
|
m1 = m[1],
|
|
@@ -3815,7 +3827,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3815
3827
|
$.scale = (x = 1, y, z = 1) => {
|
|
3816
3828
|
y ??= x;
|
|
3817
3829
|
|
|
3818
|
-
let m =
|
|
3830
|
+
let m = matrix;
|
|
3819
3831
|
|
|
3820
3832
|
m[0] *= x;
|
|
3821
3833
|
m[1] *= x;
|
|
@@ -3839,13 +3851,13 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3839
3851
|
|
|
3840
3852
|
let tanAng = Math.tan(ang);
|
|
3841
3853
|
|
|
3842
|
-
let m0 =
|
|
3843
|
-
m1 =
|
|
3844
|
-
m4 =
|
|
3845
|
-
m5 =
|
|
3854
|
+
let m0 = matrix[0],
|
|
3855
|
+
m1 = matrix[1],
|
|
3856
|
+
m4 = matrix[4],
|
|
3857
|
+
m5 = matrix[5];
|
|
3846
3858
|
|
|
3847
|
-
|
|
3848
|
-
|
|
3859
|
+
matrix[0] = m0 + m4 * tanAng;
|
|
3860
|
+
matrix[1] = m1 + m5 * tanAng;
|
|
3849
3861
|
|
|
3850
3862
|
$._matrixDirty = true;
|
|
3851
3863
|
};
|
|
@@ -3856,13 +3868,13 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3856
3868
|
|
|
3857
3869
|
let tanAng = Math.tan(ang);
|
|
3858
3870
|
|
|
3859
|
-
let m0 =
|
|
3860
|
-
m1 =
|
|
3861
|
-
m4 =
|
|
3862
|
-
m5 =
|
|
3871
|
+
let m0 = matrix[0],
|
|
3872
|
+
m1 = matrix[1],
|
|
3873
|
+
m4 = matrix[4],
|
|
3874
|
+
m5 = matrix[5];
|
|
3863
3875
|
|
|
3864
|
-
|
|
3865
|
-
|
|
3876
|
+
matrix[4] = m4 + m0 * tanAng;
|
|
3877
|
+
matrix[5] = m5 + m1 * tanAng;
|
|
3866
3878
|
|
|
3867
3879
|
$._matrixDirty = true;
|
|
3868
3880
|
};
|
|
@@ -3880,31 +3892,32 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3880
3892
|
}
|
|
3881
3893
|
|
|
3882
3894
|
// overwrite the current transformation matrix
|
|
3883
|
-
|
|
3895
|
+
matrix = m.slice();
|
|
3884
3896
|
$._matrixDirty = true;
|
|
3885
3897
|
};
|
|
3886
3898
|
|
|
3887
3899
|
// function to save the current matrix state if dirty
|
|
3888
3900
|
$._saveMatrix = () => {
|
|
3889
|
-
|
|
3890
|
-
$.
|
|
3901
|
+
transforms.set(matrix, matrices.length * MATRIX_SIZE);
|
|
3902
|
+
$._matrixIndex = matrices.length;
|
|
3903
|
+
matrices.push(matrix.slice());
|
|
3891
3904
|
$._matrixDirty = false;
|
|
3892
3905
|
};
|
|
3893
3906
|
|
|
3894
3907
|
// push the current matrix index onto the stack
|
|
3895
3908
|
$.pushMatrix = () => {
|
|
3896
3909
|
if ($._matrixDirty) $._saveMatrix();
|
|
3897
|
-
|
|
3910
|
+
matricesIndexStack.push($._matrixIndex);
|
|
3898
3911
|
};
|
|
3899
3912
|
|
|
3900
3913
|
$.popMatrix = () => {
|
|
3901
|
-
if (
|
|
3914
|
+
if (!matricesIndexStack.length) {
|
|
3902
3915
|
return console.warn('Matrix index stack is empty!');
|
|
3903
3916
|
}
|
|
3904
3917
|
// pop the last matrix index and set it as the current matrix index
|
|
3905
|
-
let idx =
|
|
3906
|
-
|
|
3907
|
-
$.
|
|
3918
|
+
let idx = matricesIndexStack.pop();
|
|
3919
|
+
matrix = matrices[idx].slice();
|
|
3920
|
+
$._matrixIndex = idx;
|
|
3908
3921
|
$._matrixDirty = false;
|
|
3909
3922
|
};
|
|
3910
3923
|
|
|
@@ -4029,14 +4042,14 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
4029
4042
|
};
|
|
4030
4043
|
|
|
4031
4044
|
$._render = () => {
|
|
4032
|
-
if (
|
|
4045
|
+
if (matrices.length > 1 || !$._transformBindGroup) {
|
|
4033
4046
|
let transformBuffer = Q5.device.createBuffer({
|
|
4034
|
-
size:
|
|
4047
|
+
size: matrices.length * MATRIX_SIZE * 4, // 4 bytes per float
|
|
4035
4048
|
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
|
|
4036
4049
|
mappedAtCreation: true
|
|
4037
4050
|
});
|
|
4038
4051
|
|
|
4039
|
-
new Float32Array(transformBuffer.getMappedRange()).set(
|
|
4052
|
+
new Float32Array(transformBuffer.getMappedRange()).set(transforms.slice(0, matrices.length * MATRIX_SIZE));
|
|
4040
4053
|
transformBuffer.unmap();
|
|
4041
4054
|
|
|
4042
4055
|
$._transformBindGroup = Q5.device.createBindGroup({
|
|
@@ -4064,7 +4077,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
4064
4077
|
entries: [{ binding: 0, resource: { buffer: colorsBuffer } }]
|
|
4065
4078
|
});
|
|
4066
4079
|
|
|
4067
|
-
|
|
4080
|
+
pass.setBindGroup(1, $._colorsBindGroup);
|
|
4068
4081
|
|
|
4069
4082
|
for (let m of $._hooks.preRender) m();
|
|
4070
4083
|
|
|
@@ -4088,6 +4101,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
4088
4101
|
pass.draw(v, 1, drawVertOffset);
|
|
4089
4102
|
drawVertOffset += v;
|
|
4090
4103
|
} else if (curPipelineIndex == 1) {
|
|
4104
|
+
// let vertCount = drawStack[i + 2];
|
|
4091
4105
|
// draw images
|
|
4092
4106
|
if (curTextureIndex != v) {
|
|
4093
4107
|
// v is the texture index
|
|
@@ -4095,6 +4109,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
4095
4109
|
}
|
|
4096
4110
|
pass.draw(4, 1, imageVertOffset);
|
|
4097
4111
|
imageVertOffset += 4;
|
|
4112
|
+
// i++;
|
|
4098
4113
|
} else if (curPipelineIndex == 2) {
|
|
4099
4114
|
// draw text
|
|
4100
4115
|
let o = drawStack[i + 2];
|
|
@@ -4123,8 +4138,9 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
4123
4138
|
colorIndex = 1;
|
|
4124
4139
|
colorStackIndex = 8;
|
|
4125
4140
|
rotation = 0;
|
|
4126
|
-
|
|
4127
|
-
|
|
4141
|
+
transforms.length = MATRIX_SIZE;
|
|
4142
|
+
matrices.length = 1;
|
|
4143
|
+
matricesIndexStack.length = 0;
|
|
4128
4144
|
};
|
|
4129
4145
|
};
|
|
4130
4146
|
|
|
@@ -4135,7 +4151,10 @@ Q5.initWebGPU = async () => {
|
|
|
4135
4151
|
}
|
|
4136
4152
|
if (!Q5.device) {
|
|
4137
4153
|
let adapter = await navigator.gpu.requestAdapter();
|
|
4138
|
-
if (!adapter)
|
|
4154
|
+
if (!adapter) {
|
|
4155
|
+
console.warn('q5 WebGPU could not start! No appropriate GPUAdapter found, vulkan may need to be enabled.');
|
|
4156
|
+
return false;
|
|
4157
|
+
}
|
|
4139
4158
|
Q5.device = await adapter.requestDevice();
|
|
4140
4159
|
}
|
|
4141
4160
|
return true;
|
|
@@ -4160,7 +4179,7 @@ Q5.renderers.webgpu.drawing = ($, q) => {
|
|
|
4160
4179
|
struct VertexInput {
|
|
4161
4180
|
@location(0) pos: vec2f,
|
|
4162
4181
|
@location(1) colorIndex: f32,
|
|
4163
|
-
@location(2)
|
|
4182
|
+
@location(2) matrixIndex: f32
|
|
4164
4183
|
}
|
|
4165
4184
|
struct VertexOutput {
|
|
4166
4185
|
@builtin(position) position: vec4f,
|
|
@@ -4179,7 +4198,7 @@ struct Uniforms {
|
|
|
4179
4198
|
@vertex
|
|
4180
4199
|
fn vertexMain(input: VertexInput) -> VertexOutput {
|
|
4181
4200
|
var vert = vec4f(input.pos, 0.0, 1.0);
|
|
4182
|
-
vert = transforms[i32(input.
|
|
4201
|
+
vert = transforms[i32(input.matrixIndex)] * vert;
|
|
4183
4202
|
vert.x /= uniforms.halfWidth;
|
|
4184
4203
|
vert.y /= uniforms.halfHeight;
|
|
4185
4204
|
|
|
@@ -4206,7 +4225,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
4206
4225
|
attributes: [
|
|
4207
4226
|
{ format: 'float32x2', offset: 0, shaderLocation: 0 }, // position
|
|
4208
4227
|
{ format: 'float32', offset: 8, shaderLocation: 1 }, // colorIndex
|
|
4209
|
-
{ format: 'float32', offset: 12, shaderLocation: 2 } //
|
|
4228
|
+
{ format: 'float32', offset: 12, shaderLocation: 2 } // matrixIndex
|
|
4210
4229
|
]
|
|
4211
4230
|
};
|
|
4212
4231
|
|
|
@@ -4360,7 +4379,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
4360
4379
|
let [l, r, t, b] = $._calcBox(x, y, w, h, $._rectMode);
|
|
4361
4380
|
let ci, ti;
|
|
4362
4381
|
if ($._matrixDirty) $._saveMatrix();
|
|
4363
|
-
ti = $.
|
|
4382
|
+
ti = $._matrixIndex;
|
|
4364
4383
|
|
|
4365
4384
|
if ($._doFill) {
|
|
4366
4385
|
ci = $._fill;
|
|
@@ -4434,7 +4453,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
4434
4453
|
let b = w == h ? a : Math.max(h, 1) / 2;
|
|
4435
4454
|
|
|
4436
4455
|
if ($._matrixDirty) $._saveMatrix();
|
|
4437
|
-
let ti = $.
|
|
4456
|
+
let ti = $._matrixIndex;
|
|
4438
4457
|
|
|
4439
4458
|
if ($._doFill) {
|
|
4440
4459
|
addEllipse(x, y, a, b, n, $._fill, ti);
|
|
@@ -4450,7 +4469,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
4450
4469
|
|
|
4451
4470
|
$.point = (x, y) => {
|
|
4452
4471
|
if ($._matrixDirty) $._saveMatrix();
|
|
4453
|
-
let ti = $.
|
|
4472
|
+
let ti = $._matrixIndex,
|
|
4454
4473
|
ci = $._stroke,
|
|
4455
4474
|
sw = $._strokeWeight;
|
|
4456
4475
|
|
|
@@ -4470,7 +4489,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
4470
4489
|
|
|
4471
4490
|
$.line = (x1, y1, x2, y2) => {
|
|
4472
4491
|
if ($._matrixDirty) $._saveMatrix();
|
|
4473
|
-
let ti = $.
|
|
4492
|
+
let ti = $._matrixIndex,
|
|
4474
4493
|
ci = $._stroke,
|
|
4475
4494
|
sw = $._strokeWeight,
|
|
4476
4495
|
hsw = sw / 2;
|
|
@@ -4505,7 +4524,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
4505
4524
|
|
|
4506
4525
|
$.vertex = (x, y) => {
|
|
4507
4526
|
if ($._matrixDirty) $._saveMatrix();
|
|
4508
|
-
sv.push(x, -y, $._fill, $.
|
|
4527
|
+
sv.push(x, -y, $._fill, $._matrixIndex);
|
|
4509
4528
|
shapeVertCount++;
|
|
4510
4529
|
};
|
|
4511
4530
|
|
|
@@ -4550,7 +4569,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
4550
4569
|
(2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * t2 +
|
|
4551
4570
|
(-p0.y + 3 * p1.y - 3 * p2.y + p3.y) * t3);
|
|
4552
4571
|
|
|
4553
|
-
sv.push(x, y, $._fill, $.
|
|
4572
|
+
sv.push(x, y, $._fill, $._matrixIndex);
|
|
4554
4573
|
shapeVertCount++;
|
|
4555
4574
|
}
|
|
4556
4575
|
}
|
|
@@ -4668,14 +4687,22 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
4668
4687
|
};
|
|
4669
4688
|
Q5.renderers.webgpu.image = ($, q) => {
|
|
4670
4689
|
$._textureBindGroups = [];
|
|
4671
|
-
let vertexStack =
|
|
4690
|
+
let vertexStack = new Float32Array(1e7),
|
|
4691
|
+
vertIndex = 0;
|
|
4672
4692
|
|
|
4673
|
-
let
|
|
4674
|
-
label: '
|
|
4693
|
+
let imageShader = Q5.device.createShaderModule({
|
|
4694
|
+
label: 'imageShader',
|
|
4675
4695
|
code: `
|
|
4696
|
+
struct VertexInput {
|
|
4697
|
+
@location(0) pos: vec2f,
|
|
4698
|
+
@location(1) texCoord: vec2f,
|
|
4699
|
+
@location(2) tintIndex: f32,
|
|
4700
|
+
@location(3) matrixIndex: f32
|
|
4701
|
+
}
|
|
4676
4702
|
struct VertexOutput {
|
|
4677
4703
|
@builtin(position) position: vec4f,
|
|
4678
|
-
@location(0) texCoord: vec2f
|
|
4704
|
+
@location(0) texCoord: vec2f,
|
|
4705
|
+
@location(1) tintIndex: f32
|
|
4679
4706
|
}
|
|
4680
4707
|
struct Uniforms {
|
|
4681
4708
|
halfWidth: f32,
|
|
@@ -4685,31 +4712,33 @@ struct Uniforms {
|
|
|
4685
4712
|
@group(0) @binding(0) var<uniform> uniforms: Uniforms;
|
|
4686
4713
|
@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;
|
|
4687
4714
|
|
|
4715
|
+
@group(1) @binding(0) var<storage> colors : array<vec4f>;
|
|
4716
|
+
|
|
4717
|
+
@group(2) @binding(0) var samp: sampler;
|
|
4718
|
+
@group(2) @binding(1) var texture: texture_2d<f32>;
|
|
4719
|
+
|
|
4688
4720
|
@vertex
|
|
4689
|
-
fn vertexMain(
|
|
4690
|
-
var vert = vec4f(pos, 0.0, 1.0);
|
|
4691
|
-
vert = transforms[i32(
|
|
4721
|
+
fn vertexMain(input: VertexInput) -> VertexOutput {
|
|
4722
|
+
var vert = vec4f(input.pos, 0.0, 1.0);
|
|
4723
|
+
vert = transforms[i32(input.matrixIndex)] * vert;
|
|
4692
4724
|
vert.x /= uniforms.halfWidth;
|
|
4693
4725
|
vert.y /= uniforms.halfHeight;
|
|
4694
4726
|
|
|
4695
4727
|
var output: VertexOutput;
|
|
4696
4728
|
output.position = vert;
|
|
4697
|
-
output.texCoord = texCoord;
|
|
4729
|
+
output.texCoord = input.texCoord;
|
|
4730
|
+
output.tintIndex = input.tintIndex;
|
|
4698
4731
|
return output;
|
|
4699
4732
|
}
|
|
4700
|
-
`
|
|
4701
|
-
});
|
|
4702
|
-
|
|
4703
|
-
let fragmentShader = Q5.device.createShaderModule({
|
|
4704
|
-
label: 'imageFragmentShader',
|
|
4705
|
-
code: `
|
|
4706
|
-
@group(2) @binding(0) var samp: sampler;
|
|
4707
|
-
@group(2) @binding(1) var texture: texture_2d<f32>;
|
|
4708
4733
|
|
|
4709
4734
|
@fragment
|
|
4710
|
-
fn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f {
|
|
4711
|
-
|
|
4712
|
-
|
|
4735
|
+
fn fragmentMain(@location(0) texCoord: vec2f, @location(1) tintIndex: f32) -> @location(0) vec4f {
|
|
4736
|
+
let texColor = textureSample(texture, samp, texCoord);
|
|
4737
|
+
let tintColor = colors[i32(tintIndex)];
|
|
4738
|
+
|
|
4739
|
+
// Mix original and tinted colors using tint alpha as blend factor
|
|
4740
|
+
let tinted = vec4f(texColor.rgb * tintColor.rgb, texColor.a);
|
|
4741
|
+
return mix(texColor, tinted, tintColor.a);
|
|
4713
4742
|
}
|
|
4714
4743
|
`
|
|
4715
4744
|
});
|
|
@@ -4731,11 +4760,12 @@ fn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f {
|
|
|
4731
4760
|
});
|
|
4732
4761
|
|
|
4733
4762
|
const vertexBufferLayout = {
|
|
4734
|
-
arrayStride:
|
|
4763
|
+
arrayStride: 24,
|
|
4735
4764
|
attributes: [
|
|
4736
4765
|
{ shaderLocation: 0, offset: 0, format: 'float32x2' },
|
|
4737
4766
|
{ shaderLocation: 1, offset: 8, format: 'float32x2' },
|
|
4738
|
-
{ shaderLocation: 2, offset: 16, format: 'float32' } //
|
|
4767
|
+
{ shaderLocation: 2, offset: 16, format: 'float32' }, // tintIndex
|
|
4768
|
+
{ shaderLocation: 3, offset: 20, format: 'float32' } // matrixIndex
|
|
4739
4769
|
]
|
|
4740
4770
|
};
|
|
4741
4771
|
|
|
@@ -4748,12 +4778,12 @@ fn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f {
|
|
|
4748
4778
|
label: 'imagePipeline',
|
|
4749
4779
|
layout: pipelineLayout,
|
|
4750
4780
|
vertex: {
|
|
4751
|
-
module:
|
|
4781
|
+
module: imageShader,
|
|
4752
4782
|
entryPoint: 'vertexMain',
|
|
4753
4783
|
buffers: [{ arrayStride: 0, attributes: [] }, vertexBufferLayout]
|
|
4754
4784
|
},
|
|
4755
4785
|
fragment: {
|
|
4756
|
-
module:
|
|
4786
|
+
module: imageShader,
|
|
4757
4787
|
entryPoint: 'fragmentMain',
|
|
4758
4788
|
targets: [{ format: 'bgra8unorm', blend: $.blendConfigs.normal }]
|
|
4759
4789
|
},
|
|
@@ -4829,58 +4859,63 @@ fn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f {
|
|
|
4829
4859
|
|
|
4830
4860
|
$.loadImage = (src, cb) => {
|
|
4831
4861
|
q._preloadCount++;
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
// calculate the default width and height that the image
|
|
4836
|
-
// should be drawn at if the user doesn't specify a display size
|
|
4837
|
-
img.defaultWidth = img.width * $._defaultImageScale;
|
|
4838
|
-
img.defaultHeight = img.height * $._defaultImageScale;
|
|
4839
|
-
img.pixelDensity = 1;
|
|
4840
|
-
|
|
4862
|
+
let g = $._g.loadImage(src, (img) => {
|
|
4863
|
+
g.defaultWidth = img.width * $._defaultImageScale;
|
|
4864
|
+
g.defaultHeight = img.height * $._defaultImageScale;
|
|
4841
4865
|
$._createTexture(img);
|
|
4842
4866
|
q._preloadCount--;
|
|
4843
4867
|
if (cb) cb(img);
|
|
4844
|
-
};
|
|
4845
|
-
|
|
4846
|
-
return img;
|
|
4868
|
+
});
|
|
4869
|
+
return g;
|
|
4847
4870
|
};
|
|
4848
4871
|
|
|
4849
4872
|
$.imageMode = (x) => ($._imageMode = x);
|
|
4850
4873
|
|
|
4851
|
-
|
|
4874
|
+
const addVert = (x, y, u, v, ci, ti) => {
|
|
4875
|
+
let s = vertexStack,
|
|
4876
|
+
i = vertIndex;
|
|
4877
|
+
s[i++] = x;
|
|
4878
|
+
s[i++] = y;
|
|
4879
|
+
s[i++] = u;
|
|
4880
|
+
s[i++] = v;
|
|
4881
|
+
s[i++] = ci;
|
|
4882
|
+
s[i++] = ti;
|
|
4883
|
+
vertIndex = i;
|
|
4884
|
+
};
|
|
4885
|
+
|
|
4886
|
+
$.image = (img, dx = 0, dy = 0, dw, dh, sx = 0, sy = 0, sw, sh) => {
|
|
4887
|
+
let g = img;
|
|
4852
4888
|
if (img.canvas) img = img.canvas;
|
|
4853
4889
|
if (img.textureIndex == undefined) return;
|
|
4854
4890
|
|
|
4855
4891
|
if ($._matrixDirty) $._saveMatrix();
|
|
4856
|
-
let ti = $._transformIndex;
|
|
4857
4892
|
|
|
4858
|
-
let
|
|
4859
|
-
|
|
4893
|
+
let ti = $._matrixIndex,
|
|
4894
|
+
w = img.width,
|
|
4895
|
+
h = img.height;
|
|
4860
4896
|
|
|
4861
|
-
dw ??=
|
|
4862
|
-
dh ??=
|
|
4897
|
+
dw ??= g.defaultWidth;
|
|
4898
|
+
dh ??= g.defaultHeight;
|
|
4863
4899
|
sw ??= w;
|
|
4864
4900
|
sh ??= h;
|
|
4865
4901
|
|
|
4866
|
-
let pd =
|
|
4902
|
+
let pd = g._pixelDensity || 1;
|
|
4867
4903
|
dw *= pd;
|
|
4868
4904
|
dh *= pd;
|
|
4869
4905
|
|
|
4870
4906
|
let [l, r, t, b] = $._calcBox(dx, dy, dw, dh, $._imageMode);
|
|
4871
4907
|
|
|
4872
|
-
let u0 = sx / w
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
);
|
|
4908
|
+
let u0 = sx / w,
|
|
4909
|
+
v0 = sy / h,
|
|
4910
|
+
u1 = (sx + sw) / w,
|
|
4911
|
+
v1 = (sy + sh) / h;
|
|
4912
|
+
|
|
4913
|
+
let ci = $._tint;
|
|
4914
|
+
|
|
4915
|
+
addVert(l, t, u0, v0, ci, ti);
|
|
4916
|
+
addVert(r, t, u1, v0, ci, ti);
|
|
4917
|
+
addVert(l, b, u0, v1, ci, ti);
|
|
4918
|
+
addVert(r, b, u1, v1, ci, ti);
|
|
4884
4919
|
|
|
4885
4920
|
$.drawStack.push(1, img.textureIndex);
|
|
4886
4921
|
};
|
|
@@ -4891,20 +4926,20 @@ fn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f {
|
|
|
4891
4926
|
// Switch to image pipeline
|
|
4892
4927
|
$.pass.setPipeline($._pipelines[1]);
|
|
4893
4928
|
|
|
4894
|
-
|
|
4895
|
-
size:
|
|
4929
|
+
let vertexBuffer = Q5.device.createBuffer({
|
|
4930
|
+
size: vertIndex * 4,
|
|
4896
4931
|
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
|
|
4897
4932
|
mappedAtCreation: true
|
|
4898
4933
|
});
|
|
4899
4934
|
|
|
4900
|
-
new Float32Array(vertexBuffer.getMappedRange()).set(vertexStack);
|
|
4935
|
+
new Float32Array(vertexBuffer.getMappedRange()).set(vertexStack.slice(0, vertIndex));
|
|
4901
4936
|
vertexBuffer.unmap();
|
|
4902
4937
|
|
|
4903
4938
|
$.pass.setVertexBuffer(1, vertexBuffer);
|
|
4904
4939
|
});
|
|
4905
4940
|
|
|
4906
4941
|
$._hooks.postRender.push(() => {
|
|
4907
|
-
|
|
4942
|
+
vertIndex = 0;
|
|
4908
4943
|
});
|
|
4909
4944
|
};
|
|
4910
4945
|
|
|
@@ -4941,7 +4976,7 @@ struct Char {
|
|
|
4941
4976
|
struct Text {
|
|
4942
4977
|
pos: vec2f,
|
|
4943
4978
|
scale: f32,
|
|
4944
|
-
|
|
4979
|
+
matrixIndex: f32,
|
|
4945
4980
|
fillIndex: f32,
|
|
4946
4981
|
strokeIndex: f32
|
|
4947
4982
|
}
|
|
@@ -4973,7 +5008,7 @@ fn vertexMain(input : VertexInput) -> VertexOutput {
|
|
|
4973
5008
|
let charPos = ((pos[input.vertex] * fontChar.size + char.xy + fontChar.offset) * text.scale) + text.pos;
|
|
4974
5009
|
|
|
4975
5010
|
var vert = vec4f(charPos, 0.0, 1.0);
|
|
4976
|
-
vert = transforms[i32(text.
|
|
5011
|
+
vert = transforms[i32(text.matrixIndex)] * vert;
|
|
4977
5012
|
vert.x /= uniforms.halfWidth;
|
|
4978
5013
|
vert.y /= uniforms.halfHeight;
|
|
4979
5014
|
|
|
@@ -5197,13 +5232,11 @@ fn fragmentMain(input : VertexOutput) -> @location(0) vec4f {
|
|
|
5197
5232
|
if (cb) cb(fontName);
|
|
5198
5233
|
};
|
|
5199
5234
|
|
|
5200
|
-
|
|
5201
|
-
let g = $.createGraphics(1, 1);
|
|
5202
|
-
g.colorMode($.RGB, 1);
|
|
5235
|
+
$._g.colorMode($.RGB, 1);
|
|
5203
5236
|
|
|
5204
5237
|
$.loadFont = (url, cb) => {
|
|
5205
5238
|
let ext = url.slice(url.lastIndexOf('.') + 1);
|
|
5206
|
-
if (ext != 'json') return
|
|
5239
|
+
if (ext != 'json') return $._g.loadFont(url, cb);
|
|
5207
5240
|
let fontName = url.slice(url.lastIndexOf('/') + 1, url.lastIndexOf('-'));
|
|
5208
5241
|
createFont(url, fontName, cb);
|
|
5209
5242
|
return fontName;
|
|
@@ -5388,7 +5421,7 @@ fn fragmentMain(input : VertexOutput) -> @location(0) vec4f {
|
|
|
5388
5421
|
text[0] = x;
|
|
5389
5422
|
text[1] = -y;
|
|
5390
5423
|
text[2] = $._textSize / 44;
|
|
5391
|
-
text[3] = $.
|
|
5424
|
+
text[3] = $._matrixIndex;
|
|
5392
5425
|
text[4] = $._fillSet ? $._fill : 0;
|
|
5393
5426
|
text[5] = $._stroke;
|
|
5394
5427
|
|
|
@@ -5402,18 +5435,18 @@ fn fragmentMain(input : VertexOutput) -> @location(0) vec4f {
|
|
|
5402
5435
|
};
|
|
5403
5436
|
|
|
5404
5437
|
$.createTextImage = (str, w, h) => {
|
|
5405
|
-
|
|
5438
|
+
$._g.textSize($._textSize);
|
|
5406
5439
|
|
|
5407
5440
|
if ($._doFill) {
|
|
5408
5441
|
let fi = $._fill * 4;
|
|
5409
|
-
|
|
5442
|
+
$._g.fill(colorStack.slice(fi, fi + 4));
|
|
5410
5443
|
}
|
|
5411
5444
|
if ($._doStroke) {
|
|
5412
5445
|
let si = $._stroke * 4;
|
|
5413
|
-
|
|
5446
|
+
$._g.stroke(colorStack.slice(si, si + 4));
|
|
5414
5447
|
}
|
|
5415
5448
|
|
|
5416
|
-
let img =
|
|
5449
|
+
let img = $._g.createTextImage(str, w, h);
|
|
5417
5450
|
|
|
5418
5451
|
if (img.canvas.textureIndex == undefined) {
|
|
5419
5452
|
$._createTexture(img);
|