webgpu-computed 0.0.7 → 0.0.9
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/README.en.md +496 -0
- package/README.md +359 -250
- package/package.json +6 -4
- package/src/App.vue.d.ts +2 -0
- package/src/build.d.ts +3 -0
- package/src/index.js +321 -187
- package/src/main.d.ts +0 -0
- package/src/pages/GpuComputedExample.d.ts +1 -0
- package/src/pages/Index.vue.d.ts +2 -0
- package/src/router/index.d.ts +2 -0
- package/src/utils/GpuComputed.d.ts +108 -0
- package/src/utils/WGSL_Fun.d.ts +2 -0
- package/src/utils/include.d.ts +1 -0
- package/README.zh-CN.md +0 -385
- package/src/index.d.ts +0 -77
package/package.json
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webgpu-computed",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "对webgpu的封装,处理了繁琐的前置工作,只关注wgsl本身逻辑",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
8
|
},
|
|
9
|
-
"keywords": [
|
|
10
|
-
"webgpu", "computed", "web", "js"
|
|
11
|
-
],
|
|
9
|
+
"keywords": ["webgpu", "gpu", "compute", "wgsl", "typescript", "javascript"],
|
|
12
10
|
"dependencies": {
|
|
13
11
|
"webgpu": "^0.3.8"
|
|
14
12
|
},
|
|
@@ -16,6 +14,10 @@
|
|
|
16
14
|
"type": "git",
|
|
17
15
|
"url": "https://github.com/xiaguochuqiu/webgpu-computed.git"
|
|
18
16
|
},
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/xiaguochuqiu/webgpu-computed/issues"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/xiaguochuqiu/webgpu-computed#readme",
|
|
19
21
|
"author": "夏过初秋",
|
|
20
22
|
"license": "ISC"
|
|
21
23
|
}
|
package/src/App.vue.d.ts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare const _default: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, HTMLDivElement>;
|
|
2
|
+
export default _default;
|
package/src/build.d.ts
ADDED
package/src/index.js
CHANGED
|
@@ -1,237 +1,371 @@
|
|
|
1
|
-
async function
|
|
1
|
+
async function q(f, e = !0) {
|
|
2
2
|
if (typeof global < "u" && typeof require < "u")
|
|
3
|
-
return require(
|
|
3
|
+
return require(f);
|
|
4
4
|
{
|
|
5
|
-
let
|
|
5
|
+
let t = await import(
|
|
6
6
|
/* @vite-ignore */
|
|
7
|
-
|
|
7
|
+
f
|
|
8
8
|
);
|
|
9
|
-
return
|
|
9
|
+
return e && (t = t.default), t;
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
function S(f) {
|
|
13
|
+
return f && f[0].toUpperCase() + f.slice(1);
|
|
14
|
+
}
|
|
15
|
+
function x(f) {
|
|
16
|
+
return O.includes(f);
|
|
17
|
+
}
|
|
18
|
+
function w(f) {
|
|
19
|
+
return f && Array.isArray(f) && f.length ? f.every((e) => e && typeof e == "object" && "name" in e && "type" in e && x(e.type)) : !1;
|
|
20
|
+
}
|
|
21
|
+
function $(f) {
|
|
22
|
+
return f && "layout" in f && w(f.layout);
|
|
23
|
+
}
|
|
24
|
+
function _(f, e) {
|
|
25
|
+
const t = B[e];
|
|
26
|
+
return (t - f % t) % t;
|
|
27
|
+
}
|
|
28
|
+
function P(f, e) {
|
|
29
|
+
return f + (e - f % e) % e;
|
|
30
|
+
}
|
|
31
|
+
function T(f) {
|
|
32
|
+
const e = Object.keys(f), t = e.map((c) => {
|
|
33
|
+
const n = f[c];
|
|
34
|
+
if (Array.isArray(n)) {
|
|
35
|
+
for (const i of ["vec2", "vec3", "vec4", "mat3x3", "mat4x4"])
|
|
36
|
+
if (E[i] === n.length) return i;
|
|
37
|
+
throw new Error(`${c} 不支持的数组长度 ${n.length}`);
|
|
38
|
+
}
|
|
39
|
+
if (typeof n == "number") return "f32";
|
|
40
|
+
throw new Error(`${c} 不支持的类型`);
|
|
41
|
+
});
|
|
42
|
+
if (e.length !== t.length) throw new Error("keys 与 types 长度不一致");
|
|
43
|
+
let a = 0;
|
|
44
|
+
const s = e.map((c, n) => {
|
|
45
|
+
const i = t[n];
|
|
46
|
+
a += _(a, i);
|
|
47
|
+
const u = {
|
|
48
|
+
name: c,
|
|
49
|
+
type: i,
|
|
50
|
+
offset: a,
|
|
51
|
+
size: E[i]
|
|
52
|
+
};
|
|
53
|
+
return a += E[i], u;
|
|
54
|
+
}), r = Math.max(...t.map((c) => B[c]));
|
|
55
|
+
return {
|
|
56
|
+
stride: a + (r - a % r) % r,
|
|
57
|
+
layout: s
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const E = {
|
|
13
61
|
f32: 1,
|
|
14
62
|
vec2: 2,
|
|
15
63
|
vec3: 3,
|
|
16
64
|
vec4: 4,
|
|
17
65
|
mat3x3: 12,
|
|
18
66
|
mat4x4: 16
|
|
19
|
-
|
|
67
|
+
// array: Infinity
|
|
68
|
+
}, B = {
|
|
20
69
|
f32: 1,
|
|
21
70
|
vec2: 2,
|
|
22
71
|
vec3: 4,
|
|
23
72
|
vec4: 4,
|
|
24
73
|
mat3x3: 4,
|
|
25
74
|
mat4x4: 4
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
75
|
+
// array: 1
|
|
76
|
+
}, O = ["f32", "vec2", "vec3", "vec4", "mat3x3", "mat4x4"];
|
|
77
|
+
let g = null, b = null;
|
|
78
|
+
class z {
|
|
79
|
+
template;
|
|
80
|
+
option;
|
|
81
|
+
pipeline;
|
|
82
|
+
device;
|
|
83
|
+
groupLayout;
|
|
84
|
+
code;
|
|
85
|
+
constructor(e, t) {
|
|
86
|
+
this.template = e, this.option = t, this.improveTemplateOption(this.template);
|
|
34
87
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
88
|
+
/** 完善模版数据
|
|
89
|
+
* @param template
|
|
90
|
+
*/
|
|
91
|
+
improveTemplateOption(e) {
|
|
92
|
+
const t = (r) => {
|
|
93
|
+
let o = 0;
|
|
94
|
+
r.forEach((c) => {
|
|
95
|
+
o += _(o, c.type), c.offset = o, c.size = E[c.type], o += c.size;
|
|
96
|
+
});
|
|
97
|
+
}, a = (r) => {
|
|
98
|
+
t(r.layout);
|
|
99
|
+
const o = r.layout[r.layout.length - 1], c = o.offset + o.size;
|
|
100
|
+
let n = 1;
|
|
101
|
+
for (const i of r.layout) n = Math.max(n, B[i.type]);
|
|
102
|
+
r.stride = P(c, n);
|
|
103
|
+
};
|
|
104
|
+
Object.keys(e).forEach((r) => {
|
|
105
|
+
const o = e[r];
|
|
106
|
+
w(o) ? t(o) : $(o) && a(o);
|
|
107
|
+
});
|
|
48
108
|
}
|
|
109
|
+
/** 获取Gpu设备
|
|
110
|
+
* @returns
|
|
111
|
+
*/
|
|
49
112
|
async getDevice() {
|
|
50
|
-
if (!
|
|
51
|
-
return { adapter:
|
|
113
|
+
if (!g || !b) throw new Error("webgpu未初始化或不可用");
|
|
114
|
+
return { adapter: g, device: b };
|
|
52
115
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
buffer: {
|
|
69
|
-
type: "storage"
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
groupItem: {
|
|
73
|
-
binding: s,
|
|
74
|
-
resource: { buffer: t }
|
|
116
|
+
/**
|
|
117
|
+
* 初始化计算管线
|
|
118
|
+
*/
|
|
119
|
+
async initPipeline() {
|
|
120
|
+
if (!this.template) throw new Error("初始化计算管线错误,未找到可用数据模版");
|
|
121
|
+
await z.init();
|
|
122
|
+
const e = this.template, { device: t } = await this.getDevice(), a = [], s = [], r = [];
|
|
123
|
+
this.device = t, Object.keys(e).forEach((p, d) => {
|
|
124
|
+
if (r.push({
|
|
125
|
+
binding: d,
|
|
126
|
+
// 绑定到组里的0号位插槽
|
|
127
|
+
visibility: GPUShaderStage.COMPUTE,
|
|
128
|
+
// 数据在哪些阶段可以使用, 计算着色器、片元着色器、顶点着色器
|
|
129
|
+
buffer: {
|
|
130
|
+
type: "storage"
|
|
75
131
|
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
132
|
+
}), w(e[p])) {
|
|
133
|
+
const v = e[p], A = v.map((h) => `${h.name}:${h.type === "f32" ? "f32" : h.type + "<f32>"}`).join(","), m = `${S(p)}Struct`;
|
|
134
|
+
a.push(`struct ${S(p)}Struct {${A}};`), s.push(`@group(0) @binding(${d}) var<storage, read_write> ${p}: ${m};`);
|
|
135
|
+
} else if ($(e[p])) {
|
|
136
|
+
const v = e[p], A = v.layout.map((h) => `${h.name}:${h.type === "f32" ? "f32" : h.type + "<f32>"}`).join(","), m = `${S(p)}Struct`;
|
|
137
|
+
a.push(`struct ${m} {${A}};`), s.push(`@group(0) @binding(${d}) var<storage, read_write> ${p}: array<${m}>;`);
|
|
138
|
+
} else
|
|
139
|
+
s.push(`@group(0) @binding(${d}) var<storage, read_write> ${p}: array<f32>;`);
|
|
82
140
|
});
|
|
83
|
-
return { pipeline: o.createComputePipeline({
|
|
84
|
-
layout: o.createPipelineLayout({
|
|
85
|
-
bindGroupLayouts: [l]
|
|
86
|
-
}),
|
|
87
|
-
compute: {
|
|
88
|
-
module: o.createShaderModule({ code: r, label: "" }),
|
|
89
|
-
entryPoint: "main"
|
|
90
|
-
}
|
|
91
|
-
}), group: g, device: o, bufferInfoList: a };
|
|
92
|
-
}
|
|
93
|
-
buildCode(r, e, o) {
|
|
94
141
|
const {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}).filter((t) => !!t).join(`
|
|
102
|
-
`), s = Object.keys(r).map((t, p) => {
|
|
103
|
-
const c = r[t], n = "read_write";
|
|
104
|
-
return Array.isArray(c) ? `@group(0) @binding(${p}) var<storage, ${n}> ${t}: array<f32>;` : `@group(0) @binding(${p}) var<storage, ${n}> ${t}: array<${d(t)}Struct>;`;
|
|
105
|
-
}).join(`
|
|
106
|
-
`), i = l;
|
|
107
|
-
return (
|
|
142
|
+
beforeCodes: o = [],
|
|
143
|
+
workgroupSize: c = [32, 1, 1],
|
|
144
|
+
globalInvocationIdName: n = "grid",
|
|
145
|
+
workgroupIndexName: i = "index",
|
|
146
|
+
code: u = ""
|
|
147
|
+
} = this.option ?? {}, l = (
|
|
108
148
|
/*wgsl*/
|
|
109
149
|
`
|
|
110
|
-
${
|
|
111
|
-
${s}
|
|
112
|
-
|
|
113
|
-
${o?.beforeCodes?.join(" ") ?? ""}
|
|
150
|
+
${a.join("")}
|
|
151
|
+
${s.join("")}
|
|
152
|
+
${o.join(" ") ?? ""}
|
|
114
153
|
|
|
115
|
-
@compute @workgroup_size(${
|
|
116
|
-
fn main(@builtin(global_invocation_id) ${
|
|
117
|
-
var ${
|
|
118
|
-
${
|
|
154
|
+
@compute @workgroup_size(${c.join(",")})
|
|
155
|
+
fn main(@builtin(global_invocation_id) ${n}: vec3<u32>) {
|
|
156
|
+
var ${i} = ${n}.x;
|
|
157
|
+
${u}
|
|
119
158
|
}
|
|
120
159
|
`
|
|
121
160
|
);
|
|
161
|
+
this.code = l;
|
|
162
|
+
const y = t.createBindGroupLayout({
|
|
163
|
+
entries: r
|
|
164
|
+
});
|
|
165
|
+
this.groupLayout = y, this.pipeline = t.createComputePipeline({
|
|
166
|
+
layout: t.createPipelineLayout({
|
|
167
|
+
bindGroupLayouts: [y]
|
|
168
|
+
}),
|
|
169
|
+
compute: {
|
|
170
|
+
module: t.createShaderModule({ code: l, label: "" }),
|
|
171
|
+
entryPoint: "main"
|
|
172
|
+
}
|
|
173
|
+
});
|
|
122
174
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
175
|
+
/** 根据数据创建buffer组
|
|
176
|
+
* @param data
|
|
177
|
+
*/
|
|
178
|
+
createBindGroup(e) {
|
|
179
|
+
if (!this.template) throw new Error("创建buffer组错误,未找到可用数据模版");
|
|
180
|
+
if (!this.device) throw new Error("创建buffer组错误,未找到可用的gpu设备,请确保初始化完计算管线");
|
|
181
|
+
const t = this.device, a = this.template, s = [];
|
|
182
|
+
function r(n, i, u = 0, l) {
|
|
183
|
+
if (!l) {
|
|
184
|
+
const y = i[i.length - 1], p = y.offset + y.size;
|
|
185
|
+
let d = 1;
|
|
186
|
+
for (const v of i) d = Math.max(d, B[v.type]);
|
|
187
|
+
l = l ?? new Array(P(p, d)).fill(0);
|
|
132
188
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const
|
|
150
|
-
l
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
189
|
+
return i.forEach((y) => {
|
|
190
|
+
let p = n[y.name];
|
|
191
|
+
Array.isArray(p) || (p = [p]);
|
|
192
|
+
for (let d = 0; d < y.size; d++)
|
|
193
|
+
l[u + y.offset + d] = Number(p[d] ?? 0);
|
|
194
|
+
}), l;
|
|
195
|
+
}
|
|
196
|
+
function o(n, i) {
|
|
197
|
+
const u = new Array(i.stride * n.length).fill(0);
|
|
198
|
+
return n.forEach((l, y) => {
|
|
199
|
+
const p = y * i.stride;
|
|
200
|
+
r(l, i.layout, p, u);
|
|
201
|
+
}), u;
|
|
202
|
+
}
|
|
203
|
+
return Object.keys(a).forEach((n) => {
|
|
204
|
+
if (!(n in e)) throw new Error(`传入的数据中,不存在${n}字段`);
|
|
205
|
+
const i = a[n], u = e[n];
|
|
206
|
+
let l = [];
|
|
207
|
+
w(i) ? l = r(u, i) : $(i) ? l = o(u, i) : Array.isArray(u) && l.push(...u);
|
|
208
|
+
const y = new Float32Array(l), p = t.createBuffer({
|
|
209
|
+
size: y.byteLength,
|
|
210
|
+
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE
|
|
155
211
|
});
|
|
212
|
+
t.queue.writeBuffer(p, 0, y), s.push({ name: n, buffer: p });
|
|
156
213
|
}), {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
214
|
+
group: t.createBindGroup({
|
|
215
|
+
layout: this.groupLayout,
|
|
216
|
+
entries: s.map((n, i) => ({
|
|
217
|
+
binding: i,
|
|
218
|
+
resource: { buffer: n.buffer }
|
|
219
|
+
}))
|
|
220
|
+
}),
|
|
221
|
+
buffers: s
|
|
161
222
|
};
|
|
162
223
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
224
|
+
/** 数据映射回模版数据
|
|
225
|
+
* @param array
|
|
226
|
+
* @param key
|
|
227
|
+
*/
|
|
228
|
+
dataMap(e, t) {
|
|
229
|
+
if (!(t in this.template)) throw new Error("未找到数据字段:" + t);
|
|
230
|
+
if ($(this.template[t])) {
|
|
231
|
+
const a = this.template[t], s = e.length / a.stride, r = [];
|
|
232
|
+
for (let o = 0; o < s; o++) {
|
|
233
|
+
const c = o * a.stride, n = {};
|
|
234
|
+
a.layout.forEach((i) => {
|
|
235
|
+
const u = e.slice(c + i.offset, c + i.offset + i.size);
|
|
236
|
+
n[i.name] = u.length === 1 ? u[0] : u;
|
|
237
|
+
}), r.push(n);
|
|
171
238
|
}
|
|
172
|
-
return
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
239
|
+
return r;
|
|
240
|
+
}
|
|
241
|
+
if (w(this.template[t])) {
|
|
242
|
+
const a = this.template[t], s = {};
|
|
243
|
+
return a.forEach((r) => {
|
|
244
|
+
const o = e.slice(r.offset, r.offset + r.size);
|
|
245
|
+
s[r.name] = o.length === 1 ? o[0] : o;
|
|
246
|
+
}), s;
|
|
247
|
+
}
|
|
248
|
+
return e;
|
|
249
|
+
}
|
|
250
|
+
/** 开始计算
|
|
251
|
+
* @param group 数据组
|
|
252
|
+
* @param workgroupCount 工作组大小
|
|
253
|
+
* @param synchronize 需要同步的数据字段
|
|
254
|
+
* @returns
|
|
255
|
+
*/
|
|
256
|
+
async computed(e, t, a) {
|
|
257
|
+
if (!this.pipeline) throw new Error("未找到可用计算管线,请确保计算管线已经创建成功");
|
|
258
|
+
const s = this.device, r = this.pipeline, o = s.createCommandEncoder(), c = o.beginComputePass();
|
|
259
|
+
c.setPipeline(r), c.setBindGroup(0, e.group), c.dispatchWorkgroups(t[0], t[1], t[2]), c.end();
|
|
260
|
+
const n = e.buffers?.map((u) => {
|
|
261
|
+
if (a?.includes(u.name)) {
|
|
262
|
+
const l = s.createBuffer({
|
|
263
|
+
size: u.buffer.size,
|
|
181
264
|
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST
|
|
182
265
|
});
|
|
183
|
-
return
|
|
266
|
+
return o.copyBufferToBuffer(u.buffer, 0, l, 0, l.size), { buffer: l, name: u.name };
|
|
184
267
|
}
|
|
185
|
-
}).filter((
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
return [...new Float32Array(n)];
|
|
268
|
+
}).filter((u) => !!u);
|
|
269
|
+
return s.queue.submit([o.finish()]), await s.queue.onSubmittedWorkDone(), await Promise.all(
|
|
270
|
+
n.map(async (u) => {
|
|
271
|
+
await u.buffer.mapAsync(GPUMapMode.READ);
|
|
272
|
+
const l = u.buffer.getMappedRange();
|
|
273
|
+
return [...new Float32Array(l)];
|
|
192
274
|
})
|
|
193
275
|
);
|
|
194
|
-
return a?.onSuccess && a.onSuccess({ code: e, bufferInfoList: s, results: p }), p;
|
|
195
276
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
277
|
+
/** 初始化gpu设备
|
|
278
|
+
* @returns
|
|
279
|
+
*/
|
|
280
|
+
static async init() {
|
|
281
|
+
if (!(g && b)) {
|
|
282
|
+
if (typeof globalThis < "u" && typeof window > "u") {
|
|
283
|
+
const { create: e, globals: t } = await q("webgpu", !1);
|
|
284
|
+
Object.assign(globalThis, t), globalThis.navigator || (globalThis.navigator = {}), Object.assign(globalThis.navigator, { gpu: e([]) });
|
|
285
|
+
}
|
|
286
|
+
if (!navigator.gpu) throw new Error("该环境不支持webgpu");
|
|
287
|
+
if (g || (g = await navigator.gpu.requestAdapter({})), !g) throw new Error("获取适配器失败");
|
|
288
|
+
if (b = await g.requestDevice(), !g) throw new Error("获取设备失败");
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
/** 注销gpu设备
|
|
292
|
+
*/
|
|
293
|
+
static destroy() {
|
|
294
|
+
b && b.destroy(), b = null;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* @param data
|
|
298
|
+
*/
|
|
299
|
+
static buildBufferTypeByData(e) {
|
|
300
|
+
return Object.keys(e).reduce((a, s) => {
|
|
301
|
+
const r = e[s];
|
|
302
|
+
if (Array.isArray(r))
|
|
303
|
+
if (typeof r[0] == "number") a[s] = [];
|
|
304
|
+
else if (typeof r[0] == "object" || r.length) {
|
|
305
|
+
const o = T(r[0]);
|
|
306
|
+
a[s] = o;
|
|
307
|
+
} else console.log(`字段:${s}, 不支持该值对应数据类型或数组为空`);
|
|
308
|
+
else if (typeof r == "object") {
|
|
309
|
+
const o = T(r);
|
|
310
|
+
a[s] = o.layout;
|
|
311
|
+
} else console.log(`字段:${s}, 不支持的数据类型`);
|
|
312
|
+
return a;
|
|
313
|
+
}, {});
|
|
314
|
+
}
|
|
315
|
+
/** 通过数据创建
|
|
316
|
+
* @param opt
|
|
317
|
+
* @returns
|
|
318
|
+
*/
|
|
319
|
+
static async fromByData(e) {
|
|
320
|
+
let { data: t, ...a } = e;
|
|
321
|
+
const s = this.buildBufferTypeByData(t), r = new z(s, a);
|
|
322
|
+
return await r.initPipeline(), r;
|
|
323
|
+
}
|
|
324
|
+
/** 快捷计算方法
|
|
325
|
+
* @param opt
|
|
326
|
+
* @returns
|
|
327
|
+
*/
|
|
328
|
+
static async computed(e) {
|
|
329
|
+
let { data: t, map: a = !1, workgroupCount: s, synchronize: r, onSuccess: o, ...c } = e;
|
|
330
|
+
const n = await this.fromByData({ data: t, ...c }), i = n.createBindGroup(t), u = await n.computed(i, s, r);
|
|
331
|
+
return o && o({ gpuComputed: n, group: i, results: u }), a ? u.map((l, y) => n.dataMap(l, r[y])) : u;
|
|
199
332
|
}
|
|
200
333
|
}
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
// 世界空间 → OBB 局部空间
|
|
222
|
-
let local = point - center;
|
|
334
|
+
const j = (
|
|
335
|
+
/* wgsl */
|
|
336
|
+
`
|
|
337
|
+
fn quat_rotate(q: vec4<f32>, v: vec3<f32>) -> vec3<f32> {
|
|
338
|
+
// q.xyz = vector part, q.w = scalar part
|
|
339
|
+
let t = 2.0 * cross(q.xyz, v);
|
|
340
|
+
return v + q.w * t + cross(q.xyz, t);
|
|
341
|
+
}
|
|
342
|
+
`
|
|
343
|
+
), D = (
|
|
344
|
+
/* wgsl */
|
|
345
|
+
`
|
|
346
|
+
fn point_in_obb(
|
|
347
|
+
point: vec3<f32>,
|
|
348
|
+
center: vec3<f32>,
|
|
349
|
+
halfSize: vec3<f32>,
|
|
350
|
+
quat: vec4<f32>
|
|
351
|
+
) -> bool {
|
|
352
|
+
// 世界空间 → OBB 局部空间
|
|
353
|
+
let local = point - center;
|
|
223
354
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
355
|
+
// 逆旋转(共轭四元数)
|
|
356
|
+
let invQuat = vec4<f32>(-quat.xyz, quat.w);
|
|
357
|
+
let pLocal = quat_rotate(invQuat, local);
|
|
227
358
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
359
|
+
// AABB 判断
|
|
360
|
+
return all(abs(pLocal) <= halfSize);
|
|
361
|
+
}
|
|
362
|
+
`
|
|
363
|
+
), G = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
364
|
+
__proto__: null,
|
|
365
|
+
point_in_obb: D,
|
|
366
|
+
quat_rotate: j
|
|
367
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
234
368
|
export {
|
|
235
|
-
|
|
236
|
-
|
|
369
|
+
z as GpuComputed,
|
|
370
|
+
G as WGSL_Fun
|
|
237
371
|
};
|
package/src/main.d.ts
ADDED
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare const _default: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, HTMLDivElement>;
|
|
2
|
+
export default _default;
|