q5 2.13.1 → 2.13.2
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 +141 -171
- package/q5.min.js +1 -1
- package/src/q5-2d-canvas.js +1 -0
- package/src/q5-webgpu-canvas.js +50 -76
- package/src/q5-webgpu-drawing.js +19 -27
- package/src/q5-webgpu-image.js +45 -40
- package/src/q5-webgpu-text.js +26 -28
package/package.json
CHANGED
package/q5.js
CHANGED
|
@@ -843,6 +843,7 @@ Q5.renderers.q2d.canvas = ($, q) => {
|
|
|
843
843
|
if ($.ctx) {
|
|
844
844
|
$.ctx.resetTransform();
|
|
845
845
|
$.scale($._pixelDensity);
|
|
846
|
+
if ($._webgpuFallback) $.translate($.canvas.hw, $.canvas.hh);
|
|
846
847
|
}
|
|
847
848
|
};
|
|
848
849
|
|
|
@@ -3601,7 +3602,6 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3601
3602
|
|
|
3602
3603
|
let pass,
|
|
3603
3604
|
mainView,
|
|
3604
|
-
colorsLayout,
|
|
3605
3605
|
colorIndex = 1,
|
|
3606
3606
|
colorStackIndex = 8;
|
|
3607
3607
|
|
|
@@ -3613,7 +3613,6 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3613
3613
|
let drawStack = ($.drawStack = []);
|
|
3614
3614
|
|
|
3615
3615
|
// colors used for each draw call
|
|
3616
|
-
|
|
3617
3616
|
let colorStack = ($.colorStack = new Float32Array(1e6));
|
|
3618
3617
|
|
|
3619
3618
|
// prettier-ignore
|
|
@@ -3622,43 +3621,28 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3622
3621
|
1, 1, 1, 1 // white
|
|
3623
3622
|
]);
|
|
3624
3623
|
|
|
3625
|
-
|
|
3626
|
-
label: '
|
|
3624
|
+
let mainLayout = Q5.device.createBindGroupLayout({
|
|
3625
|
+
label: 'mainLayout',
|
|
3627
3626
|
entries: [
|
|
3628
3627
|
{
|
|
3629
3628
|
binding: 0,
|
|
3630
3629
|
visibility: GPUShaderStage.VERTEX,
|
|
3631
|
-
buffer: {
|
|
3632
|
-
type: 'uniform',
|
|
3633
|
-
hasDynamicOffset: false
|
|
3634
|
-
}
|
|
3630
|
+
buffer: { type: 'uniform' }
|
|
3635
3631
|
},
|
|
3636
3632
|
{
|
|
3637
3633
|
binding: 1,
|
|
3638
3634
|
visibility: GPUShaderStage.VERTEX,
|
|
3639
|
-
buffer: {
|
|
3640
|
-
|
|
3641
|
-
hasDynamicOffset: false
|
|
3642
|
-
}
|
|
3643
|
-
}
|
|
3644
|
-
]
|
|
3645
|
-
});
|
|
3646
|
-
|
|
3647
|
-
colorsLayout = Q5.device.createBindGroupLayout({
|
|
3648
|
-
label: 'colorsLayout',
|
|
3649
|
-
entries: [
|
|
3635
|
+
buffer: { type: 'read-only-storage' }
|
|
3636
|
+
},
|
|
3650
3637
|
{
|
|
3651
|
-
binding:
|
|
3638
|
+
binding: 2,
|
|
3652
3639
|
visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
|
|
3653
|
-
buffer: {
|
|
3654
|
-
type: 'read-only-storage',
|
|
3655
|
-
hasDynamicOffset: false
|
|
3656
|
-
}
|
|
3640
|
+
buffer: { type: 'read-only-storage' }
|
|
3657
3641
|
}
|
|
3658
3642
|
]
|
|
3659
3643
|
});
|
|
3660
3644
|
|
|
3661
|
-
$.bindGroupLayouts = [
|
|
3645
|
+
$.bindGroupLayouts = [mainLayout];
|
|
3662
3646
|
|
|
3663
3647
|
let uniformBuffer = Q5.device.createBuffer({
|
|
3664
3648
|
size: 8, // Size of two floats
|
|
@@ -3688,7 +3672,6 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3688
3672
|
Q5.device.queue.writeBuffer(uniformBuffer, 0, new Float32Array([$.canvas.hw, $.canvas.hh]));
|
|
3689
3673
|
|
|
3690
3674
|
createMainView();
|
|
3691
|
-
|
|
3692
3675
|
return c;
|
|
3693
3676
|
};
|
|
3694
3677
|
|
|
@@ -3732,7 +3715,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3732
3715
|
};
|
|
3733
3716
|
|
|
3734
3717
|
$._stroke = 0;
|
|
3735
|
-
$._fill = $._tint = 1;
|
|
3718
|
+
$._fill = $._tint = $._globalAlpha = 1;
|
|
3736
3719
|
$._doFill = $._doStroke = true;
|
|
3737
3720
|
|
|
3738
3721
|
$.fill = (r, g, b, a) => {
|
|
@@ -3749,6 +3732,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3749
3732
|
addColor(r, g, b, a);
|
|
3750
3733
|
$._tint = colorIndex;
|
|
3751
3734
|
};
|
|
3735
|
+
$.opacity = (a) => ($._globalAlpha = a);
|
|
3752
3736
|
|
|
3753
3737
|
$.noFill = () => ($._doFill = false);
|
|
3754
3738
|
$.noStroke = () => ($._doStroke = false);
|
|
@@ -3762,6 +3746,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3762
3746
|
transforms = new Float32Array(MAX_TRANSFORMS * MATRIX_SIZE),
|
|
3763
3747
|
matrices = [],
|
|
3764
3748
|
matricesIndexStack = [];
|
|
3749
|
+
|
|
3765
3750
|
let matrix;
|
|
3766
3751
|
|
|
3767
3752
|
// tracks if the matrix has been modified
|
|
@@ -3797,12 +3782,10 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3797
3782
|
if (!a) return;
|
|
3798
3783
|
if ($._angleMode) a *= $._DEGTORAD;
|
|
3799
3784
|
|
|
3800
|
-
let cosR = Math.cos(a)
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
let m0 = m[0],
|
|
3785
|
+
let cosR = Math.cos(a),
|
|
3786
|
+
sinR = Math.sin(a),
|
|
3787
|
+
m = matrix,
|
|
3788
|
+
m0 = m[0],
|
|
3806
3789
|
m1 = m[1],
|
|
3807
3790
|
m4 = m[4],
|
|
3808
3791
|
m5 = m[5];
|
|
@@ -3849,15 +3832,15 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3849
3832
|
if (!ang) return;
|
|
3850
3833
|
if ($._angleMode) ang *= $._DEGTORAD;
|
|
3851
3834
|
|
|
3852
|
-
let tanAng = Math.tan(ang)
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
m1 =
|
|
3856
|
-
m4 =
|
|
3857
|
-
m5 =
|
|
3835
|
+
let tanAng = Math.tan(ang),
|
|
3836
|
+
m = matrix,
|
|
3837
|
+
m0 = m[0],
|
|
3838
|
+
m1 = m[1],
|
|
3839
|
+
m4 = m[4],
|
|
3840
|
+
m5 = m[5];
|
|
3858
3841
|
|
|
3859
|
-
|
|
3860
|
-
|
|
3842
|
+
m[0] = m0 + m4 * tanAng;
|
|
3843
|
+
m[1] = m1 + m5 * tanAng;
|
|
3861
3844
|
|
|
3862
3845
|
$._matrixDirty = true;
|
|
3863
3846
|
};
|
|
@@ -3866,15 +3849,15 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3866
3849
|
if (!ang) return;
|
|
3867
3850
|
if ($._angleMode) ang *= $._DEGTORAD;
|
|
3868
3851
|
|
|
3869
|
-
let tanAng = Math.tan(ang)
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
m1 =
|
|
3873
|
-
m4 =
|
|
3874
|
-
m5 =
|
|
3852
|
+
let tanAng = Math.tan(ang),
|
|
3853
|
+
m = matrix,
|
|
3854
|
+
m0 = m[0],
|
|
3855
|
+
m1 = m[1],
|
|
3856
|
+
m4 = m[4],
|
|
3857
|
+
m5 = m[5];
|
|
3875
3858
|
|
|
3876
|
-
|
|
3877
|
-
|
|
3859
|
+
m[4] = m4 + m0 * tanAng;
|
|
3860
|
+
m[5] = m5 + m1 * tanAng;
|
|
3878
3861
|
|
|
3879
3862
|
$._matrixDirty = true;
|
|
3880
3863
|
};
|
|
@@ -4042,26 +4025,14 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
4042
4025
|
};
|
|
4043
4026
|
|
|
4044
4027
|
$._render = () => {
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
});
|
|
4051
|
-
|
|
4052
|
-
new Float32Array(transformBuffer.getMappedRange()).set(transforms.slice(0, matrices.length * MATRIX_SIZE));
|
|
4053
|
-
transformBuffer.unmap();
|
|
4054
|
-
|
|
4055
|
-
$._transformBindGroup = Q5.device.createBindGroup({
|
|
4056
|
-
layout: $._transformLayout,
|
|
4057
|
-
entries: [
|
|
4058
|
-
{ binding: 0, resource: { buffer: uniformBuffer } },
|
|
4059
|
-
{ binding: 1, resource: { buffer: transformBuffer } }
|
|
4060
|
-
]
|
|
4061
|
-
});
|
|
4062
|
-
}
|
|
4028
|
+
let transformBuffer = Q5.device.createBuffer({
|
|
4029
|
+
size: matrices.length * MATRIX_SIZE * 4, // 4 bytes per float
|
|
4030
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
|
|
4031
|
+
mappedAtCreation: true
|
|
4032
|
+
});
|
|
4063
4033
|
|
|
4064
|
-
|
|
4034
|
+
new Float32Array(transformBuffer.getMappedRange()).set(transforms.slice(0, matrices.length * MATRIX_SIZE));
|
|
4035
|
+
transformBuffer.unmap();
|
|
4065
4036
|
|
|
4066
4037
|
let colorsBuffer = Q5.device.createBuffer({
|
|
4067
4038
|
size: colorStackIndex * 4,
|
|
@@ -4072,12 +4043,16 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
4072
4043
|
new Float32Array(colorsBuffer.getMappedRange()).set(colorStack.slice(0, colorStackIndex));
|
|
4073
4044
|
colorsBuffer.unmap();
|
|
4074
4045
|
|
|
4075
|
-
|
|
4076
|
-
layout:
|
|
4077
|
-
entries: [
|
|
4046
|
+
mainBindGroup = Q5.device.createBindGroup({
|
|
4047
|
+
layout: mainLayout,
|
|
4048
|
+
entries: [
|
|
4049
|
+
{ binding: 0, resource: { buffer: uniformBuffer } },
|
|
4050
|
+
{ binding: 1, resource: { buffer: transformBuffer } },
|
|
4051
|
+
{ binding: 2, resource: { buffer: colorsBuffer } }
|
|
4052
|
+
]
|
|
4078
4053
|
});
|
|
4079
4054
|
|
|
4080
|
-
pass.setBindGroup(
|
|
4055
|
+
pass.setBindGroup(0, mainBindGroup);
|
|
4081
4056
|
|
|
4082
4057
|
for (let m of $._hooks.preRender) m();
|
|
4083
4058
|
|
|
@@ -4101,11 +4076,11 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
4101
4076
|
pass.draw(v, 1, drawVertOffset);
|
|
4102
4077
|
drawVertOffset += v;
|
|
4103
4078
|
} else if (curPipelineIndex == 1) {
|
|
4104
|
-
// let
|
|
4079
|
+
// let instanceCount = drawStack[i + 2];
|
|
4105
4080
|
// draw images
|
|
4106
4081
|
if (curTextureIndex != v) {
|
|
4107
4082
|
// v is the texture index
|
|
4108
|
-
pass.setBindGroup(
|
|
4083
|
+
pass.setBindGroup(1, $._textureBindGroups[v]);
|
|
4109
4084
|
}
|
|
4110
4085
|
pass.draw(4, 1, imageVertOffset);
|
|
4111
4086
|
imageVertOffset += 4;
|
|
@@ -4113,8 +4088,8 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
4113
4088
|
} else if (curPipelineIndex == 2) {
|
|
4114
4089
|
// draw text
|
|
4115
4090
|
let o = drawStack[i + 2];
|
|
4116
|
-
pass.setBindGroup(
|
|
4117
|
-
pass.setBindGroup(
|
|
4091
|
+
pass.setBindGroup(1, $._fonts[o].bindGroup);
|
|
4092
|
+
pass.setBindGroup(2, $._textBindGroup);
|
|
4118
4093
|
|
|
4119
4094
|
// v is the number of characters in the text
|
|
4120
4095
|
pass.draw(4, v, 0, textCharOffset);
|
|
@@ -4173,46 +4148,40 @@ Q5.renderers.webgpu.drawing = ($, q) => {
|
|
|
4173
4148
|
vertexStack = new Float32Array(1e7),
|
|
4174
4149
|
vertIndex = 0;
|
|
4175
4150
|
|
|
4176
|
-
let
|
|
4177
|
-
label: '
|
|
4151
|
+
let drawingShader = Q5.device.createShaderModule({
|
|
4152
|
+
label: 'drawingShader',
|
|
4178
4153
|
code: `
|
|
4179
|
-
struct
|
|
4154
|
+
struct Uniforms {
|
|
4155
|
+
halfWidth: f32,
|
|
4156
|
+
halfHeight: f32
|
|
4157
|
+
}
|
|
4158
|
+
struct VertexParams {
|
|
4180
4159
|
@location(0) pos: vec2f,
|
|
4181
4160
|
@location(1) colorIndex: f32,
|
|
4182
4161
|
@location(2) matrixIndex: f32
|
|
4183
4162
|
}
|
|
4184
|
-
struct
|
|
4163
|
+
struct FragmentParams {
|
|
4185
4164
|
@builtin(position) position: vec4f,
|
|
4186
4165
|
@location(0) color: vec4f
|
|
4187
4166
|
}
|
|
4188
|
-
struct Uniforms {
|
|
4189
|
-
halfWidth: f32,
|
|
4190
|
-
halfHeight: f32
|
|
4191
|
-
}
|
|
4192
4167
|
|
|
4193
4168
|
@group(0) @binding(0) var<uniform> uniforms: Uniforms;
|
|
4194
4169
|
@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;
|
|
4195
|
-
|
|
4196
|
-
@group(1) @binding(0) var<storage> colors : array<vec4f>;
|
|
4170
|
+
@group(0) @binding(2) var<storage> colors : array<vec4f>;
|
|
4197
4171
|
|
|
4198
4172
|
@vertex
|
|
4199
|
-
fn vertexMain(
|
|
4200
|
-
var vert = vec4f(
|
|
4201
|
-
vert = transforms[i32(
|
|
4173
|
+
fn vertexMain(v: VertexParams) -> FragmentParams {
|
|
4174
|
+
var vert = vec4f(v.pos, 0.0, 1.0);
|
|
4175
|
+
vert = transforms[i32(v.matrixIndex)] * vert;
|
|
4202
4176
|
vert.x /= uniforms.halfWidth;
|
|
4203
4177
|
vert.y /= uniforms.halfHeight;
|
|
4204
4178
|
|
|
4205
|
-
var
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
return
|
|
4179
|
+
var f: FragmentParams;
|
|
4180
|
+
f.position = vert;
|
|
4181
|
+
f.color = colors[i32(v.colorIndex)];
|
|
4182
|
+
return f;
|
|
4209
4183
|
}
|
|
4210
|
-
`
|
|
4211
|
-
});
|
|
4212
4184
|
|
|
4213
|
-
let fragmentShader = Q5.device.createShaderModule({
|
|
4214
|
-
label: 'drawingFragmentShader',
|
|
4215
|
-
code: `
|
|
4216
4185
|
@fragment
|
|
4217
4186
|
fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
4218
4187
|
return color;
|
|
@@ -4238,19 +4207,17 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
4238
4207
|
label: 'drawingPipeline',
|
|
4239
4208
|
layout: pipelineLayout,
|
|
4240
4209
|
vertex: {
|
|
4241
|
-
module:
|
|
4210
|
+
module: drawingShader,
|
|
4242
4211
|
entryPoint: 'vertexMain',
|
|
4243
4212
|
buffers: [vertexBufferLayout]
|
|
4244
4213
|
},
|
|
4245
4214
|
fragment: {
|
|
4246
|
-
module:
|
|
4215
|
+
module: drawingShader,
|
|
4247
4216
|
entryPoint: 'fragmentMain',
|
|
4248
4217
|
targets: [{ format: 'bgra8unorm', blend: $.blendConfigs.normal }]
|
|
4249
4218
|
},
|
|
4250
4219
|
primitive: { topology: 'triangle-strip', stripIndexFormat: 'uint32' },
|
|
4251
|
-
multisample: {
|
|
4252
|
-
count: 4
|
|
4253
|
-
}
|
|
4220
|
+
multisample: { count: 4 }
|
|
4254
4221
|
};
|
|
4255
4222
|
|
|
4256
4223
|
$._pipelines[0] = Q5.device.createRenderPipeline($._pipelineConfigs[0]);
|
|
@@ -4686,63 +4653,66 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
4686
4653
|
});
|
|
4687
4654
|
};
|
|
4688
4655
|
Q5.renderers.webgpu.image = ($, q) => {
|
|
4689
|
-
$._textureBindGroups = [];
|
|
4690
4656
|
let vertexStack = new Float32Array(1e7),
|
|
4691
4657
|
vertIndex = 0;
|
|
4692
4658
|
|
|
4693
4659
|
let imageShader = Q5.device.createShaderModule({
|
|
4694
4660
|
label: 'imageShader',
|
|
4695
4661
|
code: `
|
|
4696
|
-
struct
|
|
4662
|
+
struct Uniforms {
|
|
4663
|
+
halfWidth: f32,
|
|
4664
|
+
halfHeight: f32
|
|
4665
|
+
}
|
|
4666
|
+
struct VertexParams {
|
|
4697
4667
|
@location(0) pos: vec2f,
|
|
4698
4668
|
@location(1) texCoord: vec2f,
|
|
4699
4669
|
@location(2) tintIndex: f32,
|
|
4700
|
-
@location(3) matrixIndex: f32
|
|
4670
|
+
@location(3) matrixIndex: f32,
|
|
4671
|
+
@location(4) globalAlpha: f32
|
|
4701
4672
|
}
|
|
4702
|
-
struct
|
|
4673
|
+
struct FragmentParams {
|
|
4703
4674
|
@builtin(position) position: vec4f,
|
|
4704
4675
|
@location(0) texCoord: vec2f,
|
|
4705
|
-
@location(1) tintIndex: f32
|
|
4706
|
-
|
|
4707
|
-
struct Uniforms {
|
|
4708
|
-
halfWidth: f32,
|
|
4709
|
-
halfHeight: f32
|
|
4676
|
+
@location(1) tintIndex: f32,
|
|
4677
|
+
@location(2) globalAlpha: f32
|
|
4710
4678
|
}
|
|
4711
4679
|
|
|
4712
4680
|
@group(0) @binding(0) var<uniform> uniforms: Uniforms;
|
|
4713
4681
|
@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;
|
|
4682
|
+
@group(0) @binding(2) var<storage> colors : array<vec4f>;
|
|
4714
4683
|
|
|
4715
|
-
@group(1) @binding(0) var
|
|
4716
|
-
|
|
4717
|
-
@group(2) @binding(0) var samp: sampler;
|
|
4718
|
-
@group(2) @binding(1) var texture: texture_2d<f32>;
|
|
4684
|
+
@group(1) @binding(0) var samp: sampler;
|
|
4685
|
+
@group(1) @binding(1) var texture: texture_2d<f32>;
|
|
4719
4686
|
|
|
4720
4687
|
@vertex
|
|
4721
|
-
fn vertexMain(
|
|
4722
|
-
var vert = vec4f(
|
|
4723
|
-
vert = transforms[i32(
|
|
4688
|
+
fn vertexMain(v: VertexParams) -> FragmentParams {
|
|
4689
|
+
var vert = vec4f(v.pos, 0.0, 1.0);
|
|
4690
|
+
vert = transforms[i32(v.matrixIndex)] * vert;
|
|
4724
4691
|
vert.x /= uniforms.halfWidth;
|
|
4725
4692
|
vert.y /= uniforms.halfHeight;
|
|
4726
4693
|
|
|
4727
|
-
var
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4694
|
+
var f: FragmentParams;
|
|
4695
|
+
f.position = vert;
|
|
4696
|
+
f.texCoord = v.texCoord;
|
|
4697
|
+
f.tintIndex = v.tintIndex;
|
|
4698
|
+
f.globalAlpha = v.globalAlpha;
|
|
4699
|
+
return f;
|
|
4732
4700
|
}
|
|
4733
4701
|
|
|
4734
4702
|
@fragment
|
|
4735
|
-
fn fragmentMain(
|
|
4736
|
-
let texColor = textureSample(texture, samp, texCoord);
|
|
4737
|
-
let tintColor = colors[i32(tintIndex)];
|
|
4703
|
+
fn fragmentMain(f: FragmentParams) -> @location(0) vec4f {
|
|
4704
|
+
let texColor = textureSample(texture, samp, f.texCoord);
|
|
4705
|
+
let tintColor = colors[i32(f.tintIndex)];
|
|
4738
4706
|
|
|
4739
4707
|
// Mix original and tinted colors using tint alpha as blend factor
|
|
4740
|
-
let tinted = vec4f(texColor.rgb * tintColor.rgb, texColor.a);
|
|
4708
|
+
let tinted = vec4f(texColor.rgb * tintColor.rgb, texColor.a * f.globalAlpha);
|
|
4741
4709
|
return mix(texColor, tinted, tintColor.a);
|
|
4742
4710
|
}
|
|
4743
4711
|
`
|
|
4744
4712
|
});
|
|
4745
4713
|
|
|
4714
|
+
$._textureBindGroups = [];
|
|
4715
|
+
|
|
4746
4716
|
let textureLayout = Q5.device.createBindGroupLayout({
|
|
4747
4717
|
label: 'textureLayout',
|
|
4748
4718
|
entries: [
|
|
@@ -4760,12 +4730,13 @@ fn fragmentMain(@location(0) texCoord: vec2f, @location(1) tintIndex: f32) -> @l
|
|
|
4760
4730
|
});
|
|
4761
4731
|
|
|
4762
4732
|
const vertexBufferLayout = {
|
|
4763
|
-
arrayStride:
|
|
4733
|
+
arrayStride: 28,
|
|
4764
4734
|
attributes: [
|
|
4765
4735
|
{ shaderLocation: 0, offset: 0, format: 'float32x2' },
|
|
4766
4736
|
{ shaderLocation: 1, offset: 8, format: 'float32x2' },
|
|
4767
4737
|
{ shaderLocation: 2, offset: 16, format: 'float32' }, // tintIndex
|
|
4768
|
-
{ shaderLocation: 3, offset: 20, format: 'float32' } // matrixIndex
|
|
4738
|
+
{ shaderLocation: 3, offset: 20, format: 'float32' }, // matrixIndex
|
|
4739
|
+
{ shaderLocation: 4, offset: 24, format: 'float32' } // globalAlpha
|
|
4769
4740
|
]
|
|
4770
4741
|
};
|
|
4771
4742
|
|
|
@@ -4871,7 +4842,7 @@ fn fragmentMain(@location(0) texCoord: vec2f, @location(1) tintIndex: f32) -> @l
|
|
|
4871
4842
|
|
|
4872
4843
|
$.imageMode = (x) => ($._imageMode = x);
|
|
4873
4844
|
|
|
4874
|
-
const addVert = (x, y, u, v, ci, ti) => {
|
|
4845
|
+
const addVert = (x, y, u, v, ci, ti, ga) => {
|
|
4875
4846
|
let s = vertexStack,
|
|
4876
4847
|
i = vertIndex;
|
|
4877
4848
|
s[i++] = x;
|
|
@@ -4880,6 +4851,7 @@ fn fragmentMain(@location(0) texCoord: vec2f, @location(1) tintIndex: f32) -> @l
|
|
|
4880
4851
|
s[i++] = v;
|
|
4881
4852
|
s[i++] = ci;
|
|
4882
4853
|
s[i++] = ti;
|
|
4854
|
+
s[i++] = ga;
|
|
4883
4855
|
vertIndex = i;
|
|
4884
4856
|
};
|
|
4885
4857
|
|
|
@@ -4890,16 +4862,15 @@ fn fragmentMain(@location(0) texCoord: vec2f, @location(1) tintIndex: f32) -> @l
|
|
|
4890
4862
|
|
|
4891
4863
|
if ($._matrixDirty) $._saveMatrix();
|
|
4892
4864
|
|
|
4893
|
-
let
|
|
4894
|
-
|
|
4895
|
-
|
|
4865
|
+
let w = img.width,
|
|
4866
|
+
h = img.height,
|
|
4867
|
+
pd = g._pixelDensity || 1;
|
|
4896
4868
|
|
|
4897
4869
|
dw ??= g.defaultWidth;
|
|
4898
4870
|
dh ??= g.defaultHeight;
|
|
4899
4871
|
sw ??= w;
|
|
4900
4872
|
sh ??= h;
|
|
4901
4873
|
|
|
4902
|
-
let pd = g._pixelDensity || 1;
|
|
4903
4874
|
dw *= pd;
|
|
4904
4875
|
dh *= pd;
|
|
4905
4876
|
|
|
@@ -4908,14 +4879,15 @@ fn fragmentMain(@location(0) texCoord: vec2f, @location(1) tintIndex: f32) -> @l
|
|
|
4908
4879
|
let u0 = sx / w,
|
|
4909
4880
|
v0 = sy / h,
|
|
4910
4881
|
u1 = (sx + sw) / w,
|
|
4911
|
-
v1 = (sy + sh) / h
|
|
4882
|
+
v1 = (sy + sh) / h,
|
|
4883
|
+
ti = $._matrixIndex,
|
|
4884
|
+
ci = $._tint,
|
|
4885
|
+
ga = $._globalAlpha;
|
|
4912
4886
|
|
|
4913
|
-
|
|
4914
|
-
|
|
4915
|
-
addVert(l,
|
|
4916
|
-
addVert(r,
|
|
4917
|
-
addVert(l, b, u0, v1, ci, ti);
|
|
4918
|
-
addVert(r, b, u1, v1, ci, ti);
|
|
4887
|
+
addVert(l, t, u0, v0, ci, ti, ga);
|
|
4888
|
+
addVert(r, t, u1, v0, ci, ti, ga);
|
|
4889
|
+
addVert(l, b, u0, v1, ci, ti, ga);
|
|
4890
|
+
addVert(r, b, u1, v1, ci, ti, ga);
|
|
4919
4891
|
|
|
4920
4892
|
$.drawStack.push(1, img.textureIndex);
|
|
4921
4893
|
};
|
|
@@ -4927,7 +4899,7 @@ fn fragmentMain(@location(0) texCoord: vec2f, @location(1) tintIndex: f32) -> @l
|
|
|
4927
4899
|
$.pass.setPipeline($._pipelines[1]);
|
|
4928
4900
|
|
|
4929
4901
|
let vertexBuffer = Q5.device.createBuffer({
|
|
4930
|
-
size: vertIndex *
|
|
4902
|
+
size: vertIndex * 5,
|
|
4931
4903
|
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
|
|
4932
4904
|
mappedAtCreation: true
|
|
4933
4905
|
});
|
|
@@ -4955,14 +4927,15 @@ Q5.renderers.webgpu.text = ($, q) => {
|
|
|
4955
4927
|
let textShader = Q5.device.createShaderModule({
|
|
4956
4928
|
label: 'MSDF text shader',
|
|
4957
4929
|
code: `
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4930
|
+
struct Uniforms {
|
|
4931
|
+
halfWidth: f32,
|
|
4932
|
+
halfHeight: f32
|
|
4933
|
+
}
|
|
4934
|
+
struct VertexParams {
|
|
4962
4935
|
@builtin(vertex_index) vertex : u32,
|
|
4963
4936
|
@builtin(instance_index) instance : u32
|
|
4964
4937
|
}
|
|
4965
|
-
struct
|
|
4938
|
+
struct FragmentParams {
|
|
4966
4939
|
@builtin(position) position : vec4f,
|
|
4967
4940
|
@location(0) texCoord : vec2f,
|
|
4968
4941
|
@location(1) fillColor : vec4f
|
|
@@ -4980,43 +4953,40 @@ struct Text {
|
|
|
4980
4953
|
fillIndex: f32,
|
|
4981
4954
|
strokeIndex: f32
|
|
4982
4955
|
}
|
|
4983
|
-
struct Uniforms {
|
|
4984
|
-
halfWidth: f32,
|
|
4985
|
-
halfHeight: f32
|
|
4986
|
-
}
|
|
4987
4956
|
|
|
4988
4957
|
@group(0) @binding(0) var<uniform> uniforms: Uniforms;
|
|
4989
4958
|
@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;
|
|
4959
|
+
@group(0) @binding(2) var<storage> colors : array<vec4f>;
|
|
4990
4960
|
|
|
4991
|
-
@group(1) @binding(0) var
|
|
4961
|
+
@group(1) @binding(0) var fontTexture: texture_2d<f32>;
|
|
4962
|
+
@group(1) @binding(1) var fontSampler: sampler;
|
|
4963
|
+
@group(1) @binding(2) var<storage> fontChars: array<Char>;
|
|
4992
4964
|
|
|
4993
|
-
@group(2) @binding(0) var
|
|
4994
|
-
@group(2) @binding(1) var
|
|
4995
|
-
@group(2) @binding(2) var<storage> fontChars: array<Char>;
|
|
4965
|
+
@group(2) @binding(0) var<storage> textChars: array<vec4f>;
|
|
4966
|
+
@group(2) @binding(1) var<storage> textMetadata: array<Text>;
|
|
4996
4967
|
|
|
4997
|
-
|
|
4998
|
-
@group(3) @binding(1) var<storage> textMetadata: array<Text>;
|
|
4968
|
+
const quad = array(vec2f(0, -1), vec2f(1, -1), vec2f(0, 0), vec2f(1, 0));
|
|
4999
4969
|
|
|
5000
4970
|
@vertex
|
|
5001
|
-
fn vertexMain(
|
|
5002
|
-
let char = textChars[
|
|
4971
|
+
fn vertexMain(v : VertexParams) -> FragmentParams {
|
|
4972
|
+
let char = textChars[v.instance];
|
|
5003
4973
|
|
|
5004
4974
|
let text = textMetadata[i32(char.w)];
|
|
5005
4975
|
|
|
5006
4976
|
let fontChar = fontChars[i32(char.z)];
|
|
5007
4977
|
|
|
5008
|
-
let charPos = ((
|
|
4978
|
+
let charPos = ((quad[v.vertex] * fontChar.size + char.xy + fontChar.offset) * text.scale) + text.pos;
|
|
5009
4979
|
|
|
5010
4980
|
var vert = vec4f(charPos, 0.0, 1.0);
|
|
5011
4981
|
vert = transforms[i32(text.matrixIndex)] * vert;
|
|
5012
4982
|
vert.x /= uniforms.halfWidth;
|
|
5013
4983
|
vert.y /= uniforms.halfHeight;
|
|
5014
4984
|
|
|
5015
|
-
var
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
return
|
|
4985
|
+
var f : FragmentParams;
|
|
4986
|
+
f.position = vert;
|
|
4987
|
+
f.texCoord = (quad[v.vertex] * vec2f(1, -1)) * fontChar.texExtent + fontChar.texOffset;
|
|
4988
|
+
f.fillColor = colors[i32(text.fillIndex)];
|
|
4989
|
+
return f;
|
|
5020
4990
|
}
|
|
5021
4991
|
|
|
5022
4992
|
fn sampleMsdf(texCoord: vec2f) -> f32 {
|
|
@@ -5025,22 +4995,22 @@ fn sampleMsdf(texCoord: vec2f) -> f32 {
|
|
|
5025
4995
|
}
|
|
5026
4996
|
|
|
5027
4997
|
@fragment
|
|
5028
|
-
fn fragmentMain(
|
|
4998
|
+
fn fragmentMain(f : FragmentParams) -> @location(0) vec4f {
|
|
5029
4999
|
// pxRange (AKA distanceRange) comes from the msdfgen tool,
|
|
5030
5000
|
// uses the default which is 4.
|
|
5031
5001
|
let pxRange = 4.0;
|
|
5032
5002
|
let sz = vec2f(textureDimensions(fontTexture, 0));
|
|
5033
|
-
let dx = sz.x*length(vec2f(dpdxFine(
|
|
5034
|
-
let dy = sz.y*length(vec2f(dpdxFine(
|
|
5003
|
+
let dx = sz.x*length(vec2f(dpdxFine(f.texCoord.x), dpdyFine(f.texCoord.x)));
|
|
5004
|
+
let dy = sz.y*length(vec2f(dpdxFine(f.texCoord.y), dpdyFine(f.texCoord.y)));
|
|
5035
5005
|
let toPixels = pxRange * inverseSqrt(dx * dx + dy * dy);
|
|
5036
|
-
let sigDist = sampleMsdf(
|
|
5006
|
+
let sigDist = sampleMsdf(f.texCoord) - 0.5;
|
|
5037
5007
|
let pxDist = sigDist * toPixels;
|
|
5038
5008
|
let edgeWidth = 0.5;
|
|
5039
5009
|
let alpha = smoothstep(-edgeWidth, edgeWidth, pxDist);
|
|
5040
5010
|
if (alpha < 0.001) {
|
|
5041
5011
|
discard;
|
|
5042
5012
|
}
|
|
5043
|
-
return vec4f(
|
|
5013
|
+
return vec4f(f.fillColor.rgb, f.fillColor.a * alpha);
|
|
5044
5014
|
}
|
|
5045
5015
|
`
|
|
5046
5016
|
});
|