@multiplekex/shallot 0.1.12 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/package.json +3 -4
  2. package/src/core/builder.ts +71 -32
  3. package/src/core/component.ts +25 -11
  4. package/src/core/index.ts +14 -13
  5. package/src/core/math.ts +135 -0
  6. package/src/core/runtime.ts +0 -1
  7. package/src/core/state.ts +9 -68
  8. package/src/core/xml.ts +381 -265
  9. package/src/editor/format.ts +5 -0
  10. package/src/editor/index.ts +101 -0
  11. package/src/extras/arrows/index.ts +28 -69
  12. package/src/extras/gradient/index.ts +36 -52
  13. package/src/extras/lines/index.ts +51 -122
  14. package/src/extras/orbit/index.ts +40 -15
  15. package/src/extras/text/font.ts +546 -0
  16. package/src/extras/text/index.ts +158 -204
  17. package/src/extras/text/sdf.ts +429 -0
  18. package/src/standard/activity/index.ts +172 -0
  19. package/src/standard/compute/graph.ts +23 -23
  20. package/src/standard/compute/index.ts +76 -61
  21. package/src/standard/defaults.ts +8 -5
  22. package/src/standard/index.ts +1 -0
  23. package/src/standard/input/index.ts +30 -19
  24. package/src/standard/loading/index.ts +18 -13
  25. package/src/standard/render/bvh/blas.ts +752 -0
  26. package/src/standard/render/bvh/radix.ts +476 -0
  27. package/src/standard/render/bvh/structs.ts +167 -0
  28. package/src/standard/render/bvh/tlas.ts +886 -0
  29. package/src/standard/render/bvh/traverse.ts +467 -0
  30. package/src/standard/render/camera.ts +302 -27
  31. package/src/standard/render/data.ts +93 -0
  32. package/src/standard/render/depth.ts +117 -0
  33. package/src/standard/render/forward/index.ts +259 -0
  34. package/src/standard/render/forward/raster.ts +228 -0
  35. package/src/standard/render/index.ts +443 -70
  36. package/src/standard/render/indirect.ts +40 -0
  37. package/src/standard/render/instance.ts +214 -0
  38. package/src/standard/render/intersection.ts +72 -0
  39. package/src/standard/render/light.ts +16 -16
  40. package/src/standard/render/mesh/index.ts +67 -75
  41. package/src/standard/render/mesh/unified.ts +96 -0
  42. package/src/standard/render/{transparent.ts → overlay.ts} +14 -15
  43. package/src/standard/render/pass.ts +10 -4
  44. package/src/standard/render/postprocess.ts +142 -64
  45. package/src/standard/render/ray.ts +61 -0
  46. package/src/standard/render/scene.ts +38 -164
  47. package/src/standard/render/shaders.ts +484 -0
  48. package/src/standard/render/surface/compile.ts +3 -10
  49. package/src/standard/render/surface/index.ts +60 -30
  50. package/src/standard/render/surface/noise.ts +45 -0
  51. package/src/standard/render/surface/structs.ts +60 -19
  52. package/src/standard/render/surface/wgsl.ts +573 -0
  53. package/src/standard/render/triangle.ts +84 -0
  54. package/src/standard/transforms/index.ts +4 -6
  55. package/src/standard/tween/index.ts +10 -1
  56. package/src/standard/tween/sequence.ts +24 -16
  57. package/src/standard/tween/tween.ts +67 -16
  58. package/src/core/types.ts +0 -37
  59. package/src/standard/compute/inspect.ts +0 -201
  60. package/src/standard/compute/pass.ts +0 -23
  61. package/src/standard/compute/timing.ts +0 -139
  62. package/src/standard/render/forward.ts +0 -273
@@ -0,0 +1,467 @@
1
+ import {
2
+ BVH_NODE_STRUCT_WGSL,
3
+ LEAF_FLAG_WGSL,
4
+ BLAS_NODE_STRUCT_WGSL,
5
+ BLAS_TRIANGLE_STRUCT_WGSL,
6
+ } from "./structs";
7
+
8
+ export const OCT_DECODE_WGSL = /* wgsl */ `
9
+ fn octDecode(enc: u32) -> vec3<f32> {
10
+ let x = f32(enc & 0xFFFFu) / 65535.0 * 2.0 - 1.0;
11
+ let y = f32(enc >> 16u) / 65535.0 * 2.0 - 1.0;
12
+ let z = 1.0 - abs(x) - abs(y);
13
+ var n: vec3<f32>;
14
+ if (z < 0.0) {
15
+ let signX = select(-1.0, 1.0, x >= 0.0);
16
+ let signY = select(-1.0, 1.0, y >= 0.0);
17
+ n = vec3<f32>((1.0 - abs(y)) * signX, (1.0 - abs(x)) * signY, z);
18
+ } else {
19
+ n = vec3<f32>(x, y, z);
20
+ }
21
+ return normalize(n);
22
+ }`;
23
+
24
+ export const BVH_STRUCTS = /* wgsl */ `
25
+ ${BVH_NODE_STRUCT_WGSL}
26
+
27
+ ${LEAF_FLAG_WGSL}
28
+ const INVALID_NODE: u32 = 0xFFFFFFFFu;
29
+ const MAX_STACK_DEPTH: u32 = 24u;
30
+
31
+ ${OCT_DECODE_WGSL}
32
+ `;
33
+
34
+ export const TLAS_BLAS_STRUCTS = /* wgsl */ `
35
+ ${BLAS_NODE_STRUCT_WGSL}
36
+
37
+ ${BLAS_TRIANGLE_STRUCT_WGSL}
38
+ `;
39
+
40
+ export const TLAS_BLAS_BINDINGS = /* wgsl */ `
41
+ @group(1) @binding(0) var<storage, read> tlasNodes: array<BVHNode>;
42
+ @group(1) @binding(1) var<storage, read> tlasInstanceIds: array<u32>;
43
+ @group(1) @binding(2) var<storage, read> blasNodes: array<BLASNode>;
44
+ @group(1) @binding(3) var<storage, read> blasTriIds: array<u32>;
45
+ @group(1) @binding(4) var<storage, read> blasTriangles: array<BLASTriangle>;
46
+ @group(1) @binding(5) var<storage, read> blasMeta: array<u32>;
47
+ @group(1) @binding(6) var<storage, read> instanceInverses: array<mat4x4<f32>>;
48
+ `;
49
+
50
+ export const TLAS_BLAS_TRAVERSAL = /* wgsl */ `
51
+ fn isLeaf(child: u32) -> bool {
52
+ return (child & LEAF_FLAG) != 0u;
53
+ }
54
+
55
+ fn leafIndex(child: u32) -> u32 {
56
+ return child & ~LEAF_FLAG;
57
+ }
58
+
59
+ fn safeInverse(d: f32) -> f32 {
60
+ return select(1.0 / d, 1e30, abs(d) < 1e-10);
61
+ }
62
+
63
+ fn computeInvDir(dir: vec3<f32>) -> vec3<f32> {
64
+ return vec3(
65
+ safeInverse(dir.x),
66
+ safeInverse(dir.y),
67
+ safeInverse(dir.z)
68
+ );
69
+ }
70
+
71
+ fn intersectAABBDist(origin: vec3<f32>, invDir: vec3<f32>, nodeMin: vec3<f32>, nodeMax: vec3<f32>) -> f32 {
72
+ let t1 = (nodeMin - origin) * invDir;
73
+ let t2 = (nodeMax - origin) * invDir;
74
+
75
+ let tNear = min(t1, t2);
76
+ let tFar = max(t1, t2);
77
+
78
+ let tEnter = max(max(tNear.x, tNear.y), tNear.z);
79
+ let tExit = min(min(tFar.x, tFar.y), tFar.z);
80
+
81
+ if (tEnter <= tExit && tExit >= 0.0) {
82
+ return max(tEnter, 0.0);
83
+ }
84
+ return 1e30;
85
+ }
86
+
87
+ fn intersectBLASTriangle(ray: Ray, tri: BLASTriangle) -> HitResult {
88
+ var result: HitResult;
89
+ result.hit = false;
90
+ result.t = 0.0;
91
+ result.entityId = 0u;
92
+ result.u = 0.0;
93
+ result.v = 0.0;
94
+ result.normal = vec3(0.0, 1.0, 0.0);
95
+ result.worldPos = vec3(0.0);
96
+
97
+ let e1 = tri.e1;
98
+ let e2 = tri.e2;
99
+
100
+ let h = cross(ray.direction, e2);
101
+ let a = dot(e1, h);
102
+
103
+ if (a > -EPSILON && a < EPSILON) {
104
+ return result;
105
+ }
106
+
107
+ let f = 1.0 / a;
108
+ let s = ray.origin - tri.v0;
109
+ let u = f * dot(s, h);
110
+
111
+ if (u < 0.0 || u > 1.0) {
112
+ return result;
113
+ }
114
+
115
+ let q = cross(s, e1);
116
+ let v = f * dot(ray.direction, q);
117
+
118
+ if (v < 0.0 || u + v > 1.0) {
119
+ return result;
120
+ }
121
+
122
+ let t = f * dot(e2, q);
123
+
124
+ if (t > EPSILON) {
125
+ result.hit = true;
126
+ result.t = t;
127
+ result.u = u;
128
+ result.v = v;
129
+ let w = 1.0 - u - v;
130
+ let n0 = octDecode(tri.n0_enc);
131
+ let n1 = octDecode(tri.n1_enc);
132
+ let n2 = octDecode(tri.n2_enc);
133
+ result.normal = normalize(w * n0 + u * n1 + v * n2);
134
+ result.worldPos = ray.origin + t * ray.direction;
135
+ }
136
+
137
+ return result;
138
+ }
139
+
140
+ fn traceBLAS(
141
+ ray: Ray,
142
+ nodeOffset: u32,
143
+ triIdOffset: u32,
144
+ triOffset: u32,
145
+ triCount_: u32,
146
+ maxT: f32
147
+ ) -> HitResult {
148
+ var closest: HitResult;
149
+ closest.hit = false;
150
+ closest.t = maxT;
151
+ closest.entityId = 0u;
152
+ closest.u = 0.0;
153
+ closest.v = 0.0;
154
+ closest.normal = vec3(0.0, 1.0, 0.0);
155
+ closest.worldPos = vec3(0.0);
156
+
157
+ if (triCount_ == 0u) {
158
+ return closest;
159
+ }
160
+
161
+ if (triCount_ == 1u) {
162
+ let triIdx = blasTriIds[triIdOffset];
163
+ let tri = blasTriangles[triOffset + triIdx];
164
+ let hit = intersectBLASTriangle(ray, tri);
165
+ if (hit.hit && hit.t < maxT) {
166
+ return hit;
167
+ }
168
+ return closest;
169
+ }
170
+
171
+ let invDir = computeInvDir(ray.direction);
172
+
173
+ var stack: array<u32, MAX_STACK_DEPTH>;
174
+ var stackPtr = 0u;
175
+
176
+ stack[stackPtr] = 0u;
177
+ stackPtr++;
178
+
179
+ var iterations = 0u;
180
+ let maxIterations = min(triCount_ * 3u, 10000u);
181
+
182
+ while (stackPtr > 0u && iterations < maxIterations) {
183
+ iterations++;
184
+ stackPtr--;
185
+ let localIdx = stack[stackPtr];
186
+ let node = blasNodes[nodeOffset + localIdx];
187
+
188
+ let leftChild = node.leftChild;
189
+ let rightChild = node.rightChild;
190
+
191
+ if (leftChild != INVALID_NODE) {
192
+ if (isLeaf(leftChild)) {
193
+ let leafIdx = leafIndex(leftChild);
194
+ let triIdx = blasTriIds[triIdOffset + leafIdx];
195
+ let tri = blasTriangles[triOffset + triIdx];
196
+ let hit = intersectBLASTriangle(ray, tri);
197
+ if (hit.hit && hit.t < closest.t) {
198
+ closest = hit;
199
+ }
200
+ } else {
201
+ let leftNode = blasNodes[nodeOffset + leftChild];
202
+ let leftMin = vec3(leftNode.minX, leftNode.minY, leftNode.minZ);
203
+ let leftMax = vec3(leftNode.maxX, leftNode.maxY, leftNode.maxZ);
204
+ let leftDist = intersectAABBDist(ray.origin, invDir, leftMin, leftMax);
205
+
206
+ if (leftDist < closest.t && stackPtr < MAX_STACK_DEPTH) {
207
+ stack[stackPtr] = leftChild;
208
+ stackPtr++;
209
+ }
210
+ }
211
+ }
212
+
213
+ if (rightChild != INVALID_NODE) {
214
+ if (isLeaf(rightChild)) {
215
+ let leafIdx = leafIndex(rightChild);
216
+ let triIdx = blasTriIds[triIdOffset + leafIdx];
217
+ let tri = blasTriangles[triOffset + triIdx];
218
+ let hit = intersectBLASTriangle(ray, tri);
219
+ if (hit.hit && hit.t < closest.t) {
220
+ closest = hit;
221
+ }
222
+ } else {
223
+ let rightNode = blasNodes[nodeOffset + rightChild];
224
+ let rightMin = vec3(rightNode.minX, rightNode.minY, rightNode.minZ);
225
+ let rightMax = vec3(rightNode.maxX, rightNode.maxY, rightNode.maxZ);
226
+ let rightDist = intersectAABBDist(ray.origin, invDir, rightMin, rightMax);
227
+
228
+ if (rightDist < closest.t && stackPtr < MAX_STACK_DEPTH) {
229
+ stack[stackPtr] = rightChild;
230
+ stackPtr++;
231
+ }
232
+ }
233
+ }
234
+ }
235
+
236
+ return closest;
237
+ }
238
+
239
+ fn trace(ray: Ray) -> HitResult {
240
+ var closest: HitResult;
241
+ closest.hit = false;
242
+ closest.t = 1e30;
243
+ closest.entityId = 0u;
244
+ closest.u = 0.0;
245
+ closest.v = 0.0;
246
+ closest.normal = vec3(0.0, 1.0, 0.0);
247
+ closest.worldPos = vec3(0.0);
248
+
249
+ let count = getInstanceCount();
250
+ if (count == 0u) {
251
+ return closest;
252
+ }
253
+
254
+ let invDir = computeInvDir(ray.direction);
255
+
256
+ var stack: array<u32, MAX_STACK_DEPTH>;
257
+ var stackPtr = 0u;
258
+ stack[stackPtr] = 0u;
259
+ stackPtr++;
260
+
261
+ var iterations = 0u;
262
+ let maxIterations = min(count * 3u, 10000u);
263
+
264
+ while (stackPtr > 0u && iterations < maxIterations) {
265
+ iterations++;
266
+ stackPtr--;
267
+ let nodeIdx = stack[stackPtr];
268
+
269
+ let node = tlasNodes[nodeIdx];
270
+
271
+ var children: array<u32, 4>;
272
+ var dists: array<f32, 4>;
273
+
274
+ children[0] = node.child0;
275
+ children[1] = node.child1;
276
+ children[2] = node.child2;
277
+ children[3] = node.child3;
278
+
279
+ dists[0] = select(
280
+ intersectAABBDist(ray.origin, invDir,
281
+ vec3(node.c0_minX, node.c0_minY, node.c0_minZ),
282
+ vec3(node.c0_maxX, node.c0_maxY, node.c0_maxZ)),
283
+ 1e30,
284
+ children[0] == INVALID_NODE
285
+ );
286
+ dists[1] = select(
287
+ intersectAABBDist(ray.origin, invDir,
288
+ vec3(node.c1_minX, node.c1_minY, node.c1_minZ),
289
+ vec3(node.c1_maxX, node.c1_maxY, node.c1_maxZ)),
290
+ 1e30,
291
+ children[1] == INVALID_NODE
292
+ );
293
+ dists[2] = select(
294
+ intersectAABBDist(ray.origin, invDir,
295
+ vec3(node.c2_minX, node.c2_minY, node.c2_minZ),
296
+ vec3(node.c2_maxX, node.c2_maxY, node.c2_maxZ)),
297
+ 1e30,
298
+ children[2] == INVALID_NODE
299
+ );
300
+ dists[3] = select(
301
+ intersectAABBDist(ray.origin, invDir,
302
+ vec3(node.c3_minX, node.c3_minY, node.c3_minZ),
303
+ vec3(node.c3_maxX, node.c3_maxY, node.c3_maxZ)),
304
+ 1e30,
305
+ children[3] == INVALID_NODE
306
+ );
307
+
308
+ for (var i = 1u; i < 4u; i++) {
309
+ let keyDist = dists[i];
310
+ let keyChild = children[i];
311
+ var j = i;
312
+ while (j > 0u && dists[j - 1u] > keyDist) {
313
+ dists[j] = dists[j - 1u];
314
+ children[j] = children[j - 1u];
315
+ j--;
316
+ }
317
+ dists[j] = keyDist;
318
+ children[j] = keyChild;
319
+ }
320
+
321
+ for (var i = 3i; i >= 0i; i--) {
322
+ let child = children[i];
323
+ let dist = dists[i];
324
+
325
+ if (child == INVALID_NODE || dist >= closest.t) {
326
+ continue;
327
+ }
328
+
329
+ if (isLeaf(child)) {
330
+ let instanceIdx = leafIndex(child);
331
+ let eid = tlasInstanceIds[instanceIdx];
332
+ let shapeId = getShapeId(eid);
333
+
334
+ let nodeOffset = blasMeta[shapeId * 4u];
335
+ let triIdOffset = blasMeta[shapeId * 4u + 1u];
336
+ let triOffset = blasMeta[shapeId * 4u + 2u];
337
+ let triCount_ = blasMeta[shapeId * 4u + 3u];
338
+
339
+ if (triCount_ == 0u) {
340
+ continue;
341
+ }
342
+
343
+ let invMatrix = instanceInverses[eid];
344
+ var objRay: Ray;
345
+ objRay.origin = (invMatrix * vec4(ray.origin, 1.0)).xyz;
346
+ objRay.direction = (invMatrix * vec4(ray.direction, 0.0)).xyz;
347
+
348
+ let blasHit = traceBLAS(objRay, nodeOffset, triIdOffset, triOffset, triCount_, closest.t);
349
+
350
+ if (blasHit.hit && blasHit.t < closest.t) {
351
+ closest = blasHit;
352
+ closest.entityId = eid;
353
+ let normalMat = mat3x3(invMatrix[0].xyz, invMatrix[1].xyz, invMatrix[2].xyz);
354
+ closest.normal = normalize(transpose(normalMat) * blasHit.normal);
355
+ closest.worldPos = ray.origin + blasHit.t * ray.direction;
356
+ }
357
+ } else if (stackPtr < MAX_STACK_DEPTH) {
358
+ stack[stackPtr] = child;
359
+ stackPtr++;
360
+ }
361
+ }
362
+ }
363
+
364
+ return closest;
365
+ }
366
+ `;
367
+
368
+ export const TLAS_BLAS_ANY_HIT = /* wgsl */ `
369
+ fn traceAnyHit(ray: Ray, tMax: f32) -> bool {
370
+ let count = getInstanceCount();
371
+ if (count == 0u) { return false; }
372
+
373
+ let invDir = computeInvDir(ray.direction);
374
+
375
+ var stack: array<u32, MAX_STACK_DEPTH>;
376
+ var stackPtr = 0u;
377
+ stack[stackPtr] = 0u;
378
+ stackPtr++;
379
+
380
+ var iterations = 0u;
381
+ let maxIterations = min(count * 3u, 10000u);
382
+
383
+ while (stackPtr > 0u && iterations < maxIterations) {
384
+ iterations++;
385
+ stackPtr--;
386
+ let nodeIdx = stack[stackPtr];
387
+
388
+ let node = tlasNodes[nodeIdx];
389
+
390
+ var children: array<u32, 4>;
391
+ var dists: array<f32, 4>;
392
+
393
+ children[0] = node.child0;
394
+ children[1] = node.child1;
395
+ children[2] = node.child2;
396
+ children[3] = node.child3;
397
+
398
+ dists[0] = select(
399
+ intersectAABBDist(ray.origin, invDir,
400
+ vec3(node.c0_minX, node.c0_minY, node.c0_minZ),
401
+ vec3(node.c0_maxX, node.c0_maxY, node.c0_maxZ)),
402
+ 1e30,
403
+ children[0] == INVALID_NODE
404
+ );
405
+ dists[1] = select(
406
+ intersectAABBDist(ray.origin, invDir,
407
+ vec3(node.c1_minX, node.c1_minY, node.c1_minZ),
408
+ vec3(node.c1_maxX, node.c1_maxY, node.c1_maxZ)),
409
+ 1e30,
410
+ children[1] == INVALID_NODE
411
+ );
412
+ dists[2] = select(
413
+ intersectAABBDist(ray.origin, invDir,
414
+ vec3(node.c2_minX, node.c2_minY, node.c2_minZ),
415
+ vec3(node.c2_maxX, node.c2_maxY, node.c2_maxZ)),
416
+ 1e30,
417
+ children[2] == INVALID_NODE
418
+ );
419
+ dists[3] = select(
420
+ intersectAABBDist(ray.origin, invDir,
421
+ vec3(node.c3_minX, node.c3_minY, node.c3_minZ),
422
+ vec3(node.c3_maxX, node.c3_maxY, node.c3_maxZ)),
423
+ 1e30,
424
+ children[3] == INVALID_NODE
425
+ );
426
+
427
+ for (var i = 0u; i < 4u; i++) {
428
+ let child = children[i];
429
+ let dist = dists[i];
430
+
431
+ if (child == INVALID_NODE || dist >= tMax) {
432
+ continue;
433
+ }
434
+
435
+ if (isLeaf(child)) {
436
+ let instanceIdx = leafIndex(child);
437
+ let eid = tlasInstanceIds[instanceIdx];
438
+ let shapeId = getShapeId(eid);
439
+
440
+ let nodeOffset = blasMeta[shapeId * 4u];
441
+ let triIdOffset = blasMeta[shapeId * 4u + 1u];
442
+ let triOffset = blasMeta[shapeId * 4u + 2u];
443
+ let triCount_ = blasMeta[shapeId * 4u + 3u];
444
+
445
+ if (triCount_ == 0u) {
446
+ continue;
447
+ }
448
+
449
+ let invMatrix = instanceInverses[eid];
450
+ var objRay: Ray;
451
+ objRay.origin = (invMatrix * vec4(ray.origin, 1.0)).xyz;
452
+ objRay.direction = (invMatrix * vec4(ray.direction, 0.0)).xyz;
453
+
454
+ let blasHit = traceBLAS(objRay, nodeOffset, triIdOffset, triOffset, triCount_, tMax);
455
+ if (blasHit.hit && blasHit.t < tMax) {
456
+ return true;
457
+ }
458
+ } else if (stackPtr < MAX_STACK_DEPTH) {
459
+ stack[stackPtr] = child;
460
+ stackPtr++;
461
+ }
462
+ }
463
+ }
464
+
465
+ return false;
466
+ }
467
+ `;