simulationjsv2 0.7.3 → 0.8.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.
@@ -1,58 +1,10 @@
1
1
  import { vec3 } from 'wgpu-matrix';
2
- import { EmptyElement, SimulationElement3d } from './graphics.js';
3
- import { BUF_LEN, worldProjMatOffset } from './constants.js';
2
+ import { SimulationElement3d } from './graphics.js';
4
3
  import { Color, matrix4, transitionValues, vector2, vector3 } from './utils.js';
5
- import { BlankGeometry } from './geometry.js';
6
- import { SimSceneObjInfo, buildDepthTexture, buildMultisampleTexture, updateProjectionMatrix, createPipeline, getTotalVertices, logger, removeObjectId, updateOrthoProjectionMatrix, updateWorldProjectionMatrix, globalInfo } from './internalUtils.js';
4
+ import { SimSceneObjInfo, buildDepthTexture, buildMultisampleTexture, updateProjectionMatrix, getVertexAndIndexSize, removeObjectId, updateOrthoProjectionMatrix, updateWorldProjectionMatrix, CachedArray } from './internalUtils.js';
7
5
  import { Settings } from './settings.js';
8
- const shader = `
9
- struct Uniforms {
10
- worldProjectionMatrix: mat4x4<f32>,
11
- modelProjectionMatrix: mat4x4<f32>,
12
- }
13
-
14
- @group(0) @binding(0) var<uniform> uniforms: Uniforms;
15
-
16
- @group(0) @binding(1) var<storage> instanceMatrices: array<mat4x4f>;
17
-
18
- struct VertexOutput {
19
- @builtin(position) Position: vec4<f32>,
20
- @location(0) fragUV: vec2<f32>,
21
- @location(1) fragColor: vec4<f32>,
22
- @location(2) fragPosition: vec4<f32>,
23
- }
24
-
25
- @vertex
26
- fn vertex_main(
27
- @builtin(instance_index) instanceIdx: u32,
28
- @location(0) position: vec3<f32>,
29
- @location(1) color: vec4<f32>,
30
- @location(2) uv: vec2<f32>,
31
- @location(3) drawingInstance: f32
32
- ) -> VertexOutput {
33
- var output: VertexOutput;
34
-
35
- if (drawingInstance == 1) {
36
- output.Position = uniforms.worldProjectionMatrix * uniforms.modelProjectionMatrix * instanceMatrices[instanceIdx] * vec4(position, 1.0);
37
- } else {
38
- output.Position = uniforms.worldProjectionMatrix * uniforms.modelProjectionMatrix * vec4(position, 1.0);
39
- }
40
-
41
- output.fragUV = uv;
42
- output.fragPosition = output.Position;
43
- output.fragColor = color;
44
- return output;
45
- }
46
-
47
- @fragment
48
- fn fragment_main(
49
- @location(0) fragUV: vec2<f32>,
50
- @location(1) fragColor: vec4<f32>,
51
- @location(2) fragPosition: vec4<f32>
52
- ) -> @location(0) vec4<f32> {
53
- return fragColor;
54
- }
55
- `;
6
+ import { MemoBuffer } from './buffers.js';
7
+ import { globalInfo, logger } from './globals.js';
56
8
  const simjsFrameRateCss = `.simjs-frame-rate {
57
9
  position: absolute;
58
10
  top: 0;
@@ -99,28 +51,10 @@ class FrameRateView {
99
51
  }
100
52
  }
101
53
  }
102
- const baseBindGroupLayout = {
103
- entries: [
104
- {
105
- binding: 0,
106
- visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
107
- buffer: {
108
- type: 'uniform'
109
- }
110
- },
111
- {
112
- binding: 1,
113
- visibility: GPUShaderStage.VERTEX,
114
- buffer: {
115
- type: 'read-only-storage'
116
- }
117
- }
118
- ]
119
- };
120
54
  let aspectRatio = 0;
121
55
  const projMat = matrix4();
122
- const worldProjMat = matrix4();
123
- const orthoMatrix = matrix4();
56
+ export const worldProjectionMatrix = matrix4();
57
+ export const orthogonalMatrix = matrix4();
124
58
  export class Camera {
125
59
  pos;
126
60
  rotation;
@@ -216,25 +150,24 @@ export class Simulation extends Settings {
216
150
  fittingElement = false;
217
151
  running = true;
218
152
  initialized = false;
219
- pipelines = null;
220
- renderInfo = null;
221
153
  resizeEvents;
222
154
  frameRateView;
155
+ transparentElements;
156
+ vertexBuffer;
157
+ indexBuffer;
223
158
  constructor(idOrCanvasRef, sceneCamera = null, showFrameRate = false) {
224
159
  super();
225
160
  if (typeof idOrCanvasRef === 'string') {
226
161
  const ref = document.getElementById(idOrCanvasRef);
227
- if (ref !== null)
228
- this.canvasRef = ref;
229
- else
162
+ if (!ref)
230
163
  throw logger.error(`Cannot find canvas with id ${idOrCanvasRef}`);
164
+ this.canvasRef = ref;
231
165
  }
232
166
  else if (idOrCanvasRef instanceof HTMLCanvasElement) {
233
167
  this.canvasRef = idOrCanvasRef;
234
168
  }
235
- else {
169
+ else
236
170
  throw logger.error(`Canvas ref/id provided is invalid`);
237
- }
238
171
  const parent = this.canvasRef.parentElement;
239
172
  if (sceneCamera) {
240
173
  camera = sceneCamera;
@@ -247,6 +180,9 @@ export class Simulation extends Settings {
247
180
  });
248
181
  this.frameRateView = new FrameRateView(showFrameRate);
249
182
  this.frameRateView.updateFrameRate(1);
183
+ this.transparentElements = new CachedArray();
184
+ this.vertexBuffer = new MemoBuffer(GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST, 0);
185
+ this.indexBuffer = new MemoBuffer(GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST, 0);
250
186
  }
251
187
  handleCanvasResize(parent) {
252
188
  if (this.fittingElement) {
@@ -325,13 +261,18 @@ export class Simulation extends Settings {
325
261
  throw logger.error('Context is null');
326
262
  const device = await adapter.requestDevice();
327
263
  globalInfo.setDevice(device);
264
+ const screenSize = vector2(this.canvasRef.width, this.canvasRef.height);
265
+ camera.setScreenSize(screenSize);
266
+ const canvas = this.canvasRef;
267
+ canvas.width = canvas.clientWidth * devicePixelRatio;
268
+ canvas.height = canvas.clientHeight * devicePixelRatio;
269
+ const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
328
270
  ctx.configure({
329
271
  device,
330
- format: 'bgra8unorm'
272
+ format: presentationFormat,
273
+ alphaMode: 'opaque'
331
274
  });
332
- const screenSize = vector2(this.canvasRef.width, this.canvasRef.height);
333
- camera.setScreenSize(screenSize);
334
- this.render(ctx);
275
+ this.render(device, ctx, canvas);
335
276
  })();
336
277
  }
337
278
  stop() {
@@ -346,35 +287,7 @@ export class Simulation extends Settings {
346
287
  getSceneObjects() {
347
288
  return this.scene.map((item) => item.getObj());
348
289
  }
349
- render(ctx) {
350
- const device = globalInfo.getDevice();
351
- if (this.canvasRef === null || device === null)
352
- return;
353
- const canvas = this.canvasRef;
354
- canvas.width = canvas.clientWidth * devicePixelRatio;
355
- canvas.height = canvas.clientHeight * devicePixelRatio;
356
- const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
357
- const shaderModule = device.createShaderModule({ code: shader });
358
- ctx.configure({
359
- device,
360
- format: presentationFormat,
361
- alphaMode: 'premultiplied'
362
- });
363
- const instanceBuffer = device.createBuffer({
364
- size: 10 * 4 * 16,
365
- usage: GPUBufferUsage.STORAGE
366
- });
367
- const bindGroupLayout = device.createBindGroupLayout(baseBindGroupLayout);
368
- this.renderInfo = {
369
- bindGroupLayout,
370
- instanceBuffer,
371
- vertexBuffer: null
372
- };
373
- this.pipelines = {
374
- triangleList: createPipeline(device, shaderModule, [bindGroupLayout], presentationFormat, 'triangle-list'),
375
- triangleStrip: createPipeline(device, shaderModule, [bindGroupLayout], presentationFormat, 'triangle-strip'),
376
- lineStrip: createPipeline(device, shaderModule, [bindGroupLayout], presentationFormat, 'line-strip')
377
- };
290
+ render(device, ctx, canvas) {
378
291
  const colorAttachment = {
379
292
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
380
293
  // @ts-ignore
@@ -388,8 +301,8 @@ export class Simulation extends Settings {
388
301
  updateProjectionMatrix(projMat, newAspectRatio);
389
302
  aspectRatio = newAspectRatio;
390
303
  }
391
- updateWorldProjectionMatrix(worldProjMat, projMat);
392
- updateOrthoProjectionMatrix(orthoMatrix, camera.getScreenSize());
304
+ updateWorldProjectionMatrix(worldProjectionMatrix, projMat);
305
+ updateOrthoProjectionMatrix(orthogonalMatrix, camera.getScreenSize());
393
306
  let multisampleTexture = buildMultisampleTexture(device, ctx, canvas.width, canvas.height);
394
307
  let depthTexture = buildDepthTexture(device, canvas.width, canvas.height);
395
308
  const renderPassDescriptor = {
@@ -405,7 +318,7 @@ export class Simulation extends Settings {
405
318
  let prev = Date.now() - 10;
406
319
  let prevFps = 0;
407
320
  const frame = async () => {
408
- if (!canvas || !this.renderInfo)
321
+ if (!canvas)
409
322
  return;
410
323
  requestAnimationFrame(frame);
411
324
  if (!this.running)
@@ -414,12 +327,10 @@ export class Simulation extends Settings {
414
327
  const diff = Math.max(now - prev, 1);
415
328
  prev = now;
416
329
  const fps = 1000 / diff;
417
- if (fps === prevFps && this.frameRateView.isActive()) {
330
+ if (this.frameRateView.isActive() && fps === prevFps) {
418
331
  this.frameRateView.updateFrameRate(fps);
419
332
  }
420
333
  prevFps = fps;
421
- canvas.width = canvas.clientWidth * devicePixelRatio;
422
- canvas.height = canvas.clientHeight * devicePixelRatio;
423
334
  const screenSize = camera.getScreenSize();
424
335
  if (screenSize[0] !== canvas.width || screenSize[1] !== canvas.height) {
425
336
  camera.setScreenSize(vector2(canvas.width, canvas.height));
@@ -427,7 +338,7 @@ export class Simulation extends Settings {
427
338
  screenSize[1] = canvas.height;
428
339
  aspectRatio = camera.getAspectRatio();
429
340
  updateProjectionMatrix(projMat, aspectRatio);
430
- updateWorldProjectionMatrix(worldProjMat, projMat);
341
+ updateWorldProjectionMatrix(worldProjectionMatrix, projMat);
431
342
  multisampleTexture = buildMultisampleTexture(device, ctx, screenSize[0], screenSize[1]);
432
343
  depthTexture = buildDepthTexture(device, screenSize[0], screenSize[1]);
433
344
  renderPassDescriptor.depthStencilAttachment.view = depthTexture.createView();
@@ -439,140 +350,72 @@ export class Simulation extends Settings {
439
350
  // @ts-ignore
440
351
  renderPassDescriptor.colorAttachments[0].resolveTarget = ctx.getCurrentTexture().createView();
441
352
  if (camera.hasUpdated()) {
442
- updateOrthoProjectionMatrix(orthoMatrix, camera.getScreenSize());
443
- updateWorldProjectionMatrix(worldProjMat, projMat);
353
+ updateOrthoProjectionMatrix(orthogonalMatrix, camera.getScreenSize());
354
+ updateWorldProjectionMatrix(worldProjectionMatrix, projMat);
444
355
  }
445
356
  const commandEncoder = device.createCommandEncoder();
446
357
  const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
447
- passEncoder.setPipeline(this.pipelines.triangleList);
448
- const totalVertices = getTotalVertices(this.scene);
449
- if (this.renderInfo.vertexBuffer === null ||
450
- this.renderInfo.vertexBuffer.size / (4 * BUF_LEN) < totalVertices) {
451
- this.renderInfo.vertexBuffer = device.createBuffer({
452
- size: totalVertices * 4 * BUF_LEN,
453
- usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
454
- });
455
- }
456
- this.renderScene(device, passEncoder, this.renderInfo.vertexBuffer, this.scene, 0, diff);
358
+ const [totalVerticesSize, totalIndexSize] = getVertexAndIndexSize(this.scene);
359
+ this.vertexBuffer.setSize(totalVerticesSize * 4);
360
+ this.indexBuffer.setSize(totalIndexSize * 4);
361
+ this.transparentElements.reset();
362
+ const [opaqueVertexOffset, opaqueIndexOffset] = this.renderScene(device, passEncoder, this.vertexBuffer.getBuffer(), this.indexBuffer.getBuffer(), 0, 0, this.scene, this.scene.length, diff, false);
363
+ this.renderScene(device, passEncoder, this.vertexBuffer.getBuffer(), this.indexBuffer.getBuffer(), opaqueVertexOffset, opaqueIndexOffset, this.transparentElements.getArray(), this.transparentElements.length, diff, true);
457
364
  camera.updateConsumed();
458
365
  passEncoder.end();
459
366
  device.queue.submit([commandEncoder.finish()]);
460
367
  };
461
368
  requestAnimationFrame(frame);
462
369
  }
463
- renderScene(device, passEncoder, vertexBuffer, scene, startOffset, diff, shaderInfo) {
464
- if (this.pipelines === null)
465
- return 0;
466
- let currentOffset = startOffset;
370
+ renderScene(device, passEncoder, vertexBuffer, indexBuffer, startVertexOffset, startIndexOffset, scene, numElements, diff, transparent) {
371
+ let vertexOffset = startVertexOffset;
372
+ let indexOffset = startIndexOffset;
467
373
  const toRemove = [];
468
- for (let i = 0; i < scene.length; i++) {
469
- const lifetime = scene[i].getLifetime();
374
+ for (let i = 0; i < numElements; i++) {
375
+ const sceneObj = scene[i];
376
+ const lifetime = sceneObj.getLifetime();
470
377
  if (lifetime !== null) {
471
- const complete = scene[i].lifetimeComplete();
378
+ const complete = sceneObj.lifetimeComplete();
472
379
  if (complete) {
473
380
  toRemove.push(i);
474
381
  continue;
475
382
  }
476
- scene[i].traverseLife(diff);
383
+ sceneObj.traverseLife(diff);
384
+ }
385
+ const obj = sceneObj.getObj();
386
+ if (!transparent && obj.isTransparent()) {
387
+ this.transparentElements.add(sceneObj);
388
+ continue;
477
389
  }
478
- const obj = scene[i].getObj();
479
390
  if (obj.hasChildren()) {
480
- let shaderInfo = undefined;
481
- if (obj instanceof ShaderGroup) {
482
- const pipeline = obj.getPipeline();
483
- if (pipeline !== null) {
484
- shaderInfo = {
485
- pipeline,
486
- paramGenerator: obj.getVertexParamGenerator(),
487
- bufferInfo: obj.hasBindGroup()
488
- ? {
489
- buffers: obj.getBindGroupBuffers(device),
490
- layout: obj.getBindGroupLayout()
491
- }
492
- : null
493
- };
494
- }
495
- }
496
- currentOffset += this.renderScene(device, passEncoder, vertexBuffer, obj.getChildrenInfos(), currentOffset, diff, shaderInfo);
391
+ const childObjects = obj.getChildrenInfos();
392
+ const [vertexDiff, indexDiff] = this.renderScene(device, passEncoder, vertexBuffer, indexBuffer, vertexOffset, indexOffset, childObjects, childObjects.length, diff, transparent);
393
+ vertexOffset += vertexDiff;
394
+ indexOffset += indexDiff;
497
395
  }
498
396
  if (obj.isEmpty)
499
397
  continue;
500
- const buffer = new Float32Array(obj.getBuffer(shaderInfo?.paramGenerator));
501
- const bufLen = shaderInfo?.paramGenerator?.bufferSize || BUF_LEN;
502
- const vertexCount = buffer.length / bufLen;
503
- device.queue.writeBuffer(vertexBuffer, currentOffset, buffer.buffer, buffer.byteOffset, buffer.byteLength);
504
- vertexBuffer.unmap();
505
- passEncoder.setVertexBuffer(0, vertexBuffer, currentOffset, buffer.byteLength);
506
- const modelMatrix = obj.getModelMatrix();
507
- const uniformBuffer = obj.getUniformBuffer(modelMatrix);
508
- const projBuf = obj.is3d ? worldProjMat : orthoMatrix;
509
- device.queue.writeBuffer(uniformBuffer, worldProjMatOffset, projBuf.buffer, projBuf.byteOffset, projBuf.byteLength);
510
- if (shaderInfo) {
511
- passEncoder.setPipeline(shaderInfo.pipeline);
512
- }
513
- else if (obj.isWireframe()) {
514
- passEncoder.setPipeline(this.pipelines.lineStrip);
398
+ const vertices = obj.getVertexBuffer();
399
+ const indices = obj.getIndexBuffer();
400
+ device.queue.writeBuffer(vertexBuffer, vertexOffset, vertices.buffer, vertices.byteOffset, vertices.byteLength);
401
+ device.queue.writeBuffer(indexBuffer, indexOffset, indices.buffer, indices.byteOffset, indices.byteLength);
402
+ passEncoder.setVertexBuffer(0, vertexBuffer, vertexOffset, vertices.byteLength);
403
+ passEncoder.setIndexBuffer(indexBuffer, 'uint32', indexOffset, indices.byteLength);
404
+ passEncoder.setPipeline(obj.getPipeline());
405
+ obj.writeBuffers();
406
+ const instances = obj.isInstance ? obj.getNumInstances() : 1;
407
+ const bindGroups = obj.getShader().getBindGroups(obj);
408
+ for (let i = 0; i < bindGroups.length; i++) {
409
+ passEncoder.setBindGroup(i, bindGroups[i]);
515
410
  }
516
- else {
517
- const type = obj.getGeometryType();
518
- if (type === 'strip') {
519
- passEncoder.setPipeline(this.pipelines.triangleStrip);
520
- }
521
- else if (type === 'list') {
522
- passEncoder.setPipeline(this.pipelines.triangleList);
523
- }
524
- }
525
- let instances = 1;
526
- if (this.renderInfo) {
527
- let instanceBuffer;
528
- if (obj.isInstance) {
529
- instances = obj.getNumInstances();
530
- instanceBuffer =
531
- obj.getMatrixBuffer() ?? this.renderInfo.instanceBuffer;
532
- }
533
- else {
534
- instanceBuffer = this.renderInfo.instanceBuffer;
535
- }
536
- const uniformBindGroup = device.createBindGroup({
537
- layout: this.renderInfo.bindGroupLayout,
538
- entries: [
539
- {
540
- binding: 0,
541
- resource: {
542
- buffer: uniformBuffer
543
- }
544
- },
545
- {
546
- binding: 1,
547
- resource: {
548
- buffer: instanceBuffer
549
- }
550
- }
551
- ]
552
- });
553
- passEncoder.setBindGroup(0, uniformBindGroup);
554
- }
555
- if (shaderInfo && shaderInfo.bufferInfo) {
556
- const bindGroupEntries = shaderInfo.bufferInfo.buffers.map((buffer, index) => ({
557
- binding: index,
558
- resource: {
559
- buffer
560
- }
561
- }));
562
- const bindGroup = device.createBindGroup({
563
- layout: shaderInfo.bufferInfo.layout,
564
- entries: bindGroupEntries
565
- });
566
- passEncoder.setBindGroup(1, bindGroup);
567
- }
568
- // TODO maybe switch to drawIndexed
569
- passEncoder.draw(vertexCount, instances, 0, 0);
570
- currentOffset += buffer.byteLength;
411
+ passEncoder.drawIndexed(indices.length, instances);
412
+ vertexOffset += vertices.byteLength;
413
+ indexOffset += indices.byteLength;
571
414
  }
572
415
  for (let i = toRemove.length - 1; i >= 0; i--) {
573
- this.remove(scene[i].getObj());
416
+ this.remove(scene.at(i).getObj());
574
417
  }
575
- return currentOffset - startOffset;
418
+ return [vertexOffset - startVertexOffset, indexOffset - startIndexOffset];
576
419
  }
577
420
  fitElement() {
578
421
  if (this.canvasRef === null)
@@ -586,112 +429,3 @@ export class Simulation extends Settings {
586
429
  }
587
430
  }
588
431
  }
589
- const defaultShaderCode = `
590
- struct Uniforms {
591
- worldProjectionMatrix: mat4x4<f32>,
592
- modelProjectionMatrix: mat4x4<f32>,
593
- }
594
-
595
- @group(0) @binding(0) var<uniform> uniforms: Uniforms;
596
-
597
- @group(0) @binding(1) var<storage> instanceMatrices: array<mat4x4f>;
598
- `;
599
- export class ShaderGroup extends EmptyElement {
600
- code;
601
- module;
602
- pipeline;
603
- bindGroupLayout;
604
- topology;
605
- paramGenerator;
606
- vertexParams;
607
- bindGroup;
608
- valueBuffers;
609
- constructor(shaderCode, topology = 'triangle-list', vertexParams, paramGenerator, bindGroup) {
610
- super();
611
- this.geometry = new BlankGeometry();
612
- this.code = defaultShaderCode + shaderCode;
613
- this.module = null;
614
- this.pipeline = null;
615
- this.bindGroupLayout = null;
616
- this.bindGroup = bindGroup || null;
617
- this.topology = topology;
618
- this.paramGenerator = paramGenerator;
619
- this.vertexParams = vertexParams;
620
- this.valueBuffers = null;
621
- }
622
- initPipeline() {
623
- const device = globalInfo.errorGetDevice();
624
- this.module = device.createShaderModule({ code: this.code });
625
- const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
626
- const bindGroupLayout = device.createBindGroupLayout(baseBindGroupLayout);
627
- const bindGroups = [bindGroupLayout];
628
- if (this.bindGroup !== null) {
629
- const entryValues = this.bindGroup.bindings.map((binding, index) => ({
630
- binding: index,
631
- visibility: binding.visibility,
632
- buffer: binding.buffer
633
- }));
634
- this.bindGroupLayout = device.createBindGroupLayout({
635
- entries: entryValues
636
- });
637
- bindGroups.push(this.bindGroupLayout);
638
- }
639
- this.pipeline = createPipeline(device, this.module, bindGroups, presentationFormat, this.topology, this.vertexParams);
640
- }
641
- getBindGroupLayout() {
642
- return this.bindGroupLayout;
643
- }
644
- getPipeline() {
645
- if (!this.pipeline)
646
- this.initPipeline();
647
- return this.pipeline;
648
- }
649
- getBindGroupBuffers(device) {
650
- if (this.bindGroup === null)
651
- return null;
652
- if (device === null)
653
- return null;
654
- const values = this.bindGroup.values();
655
- if (this.valueBuffers === null) {
656
- this.valueBuffers = [];
657
- for (let i = 0; i < values.length; i++) {
658
- const buffer = this.createBuffer(device, values[i]);
659
- this.valueBuffers.push(buffer);
660
- }
661
- }
662
- else {
663
- for (let i = 0; i < values.length; i++) {
664
- const arrayConstructor = values[i].array;
665
- const array = new arrayConstructor(values[i].value);
666
- if (array.byteLength > this.valueBuffers[i].size) {
667
- const newBuffer = this.createBuffer(device, values[i]);
668
- this.valueBuffers[i].destroy();
669
- this.valueBuffers[i] = newBuffer;
670
- }
671
- else {
672
- device.queue.writeBuffer(this.valueBuffers[i], 0, array.buffer, array.byteOffset, array.byteLength);
673
- }
674
- }
675
- }
676
- return this.valueBuffers;
677
- }
678
- createBuffer(device, value) {
679
- const arrayConstructor = value.array;
680
- const array = new arrayConstructor(value.value);
681
- const buffer = device.createBuffer({
682
- mappedAtCreation: true,
683
- size: array.byteLength,
684
- usage: value.usage
685
- });
686
- const bufferArr = new arrayConstructor(buffer.getMappedRange());
687
- bufferArr.set(array);
688
- buffer.unmap();
689
- return buffer;
690
- }
691
- getVertexParamGenerator() {
692
- return this.paramGenerator;
693
- }
694
- hasBindGroup() {
695
- return !!this.bindGroup;
696
- }
697
- }
package/dist/types.d.ts CHANGED
@@ -1,7 +1,11 @@
1
1
  /// <reference types="@webgpu/types" />
2
+ import { MemoBuffer } from './buffers.js';
2
3
  import { CubicBezierCurve2d, SimulationElement2d, SimulationElement3d, SplinePoint2d } from './graphics.js';
3
- import { Color, Vertex } from './utils.js';
4
+ import { Color } from './utils.js';
4
5
  export type FloatArray = Float32Array | Float64Array;
6
+ export type UintArray = Uint8Array | Uint16Array | Uint32Array;
7
+ export type IntArray = Int8Array | Int16Array | Int32Array;
8
+ export type ArrayTypes = FloatArray | UintArray | IntArray;
5
9
  export type Vector4 = FloatArray & [number, number, number, number];
6
10
  export type Vector3 = FloatArray & [number, number, number];
7
11
  export type Vector2 = FloatArray & [number, number];
@@ -29,84 +33,86 @@ export type VertexColorMap = Record<number, Color>;
29
33
  export type ElementRotation<T extends Vector2 | Vector3> = T extends Vector2 ? number : T;
30
34
  export type AnySimulationElement = SimulationElement2d | SimulationElement3d;
31
35
  export type EmptyParams = object;
32
- export type CubeGeometryParams = {
36
+ export interface CubeGeometryParams {
33
37
  width: number;
34
38
  height: number;
35
39
  depth: number;
36
- };
37
- export type SquareGeometryParams = {
40
+ }
41
+ export interface SquareGeometryParams {
38
42
  width: number;
39
43
  height: number;
40
- colorMap: VertexColorMap;
41
- centerOffset: Vector2;
42
- };
43
- export type CircleGeometryParams = {
44
+ }
45
+ export interface CircleGeometryParams {
44
46
  radius: number;
45
47
  detail: number;
46
- };
47
- export type Spline2dGeometryParams = {
48
+ }
49
+ export interface Spline2dGeometryParams {
48
50
  points: SplinePoint2d[];
49
- curves: CubicBezierCurve2d[];
50
- distance: number;
51
51
  detail: number;
52
52
  interpolateStart: number;
53
53
  interpolateLimit: number;
54
54
  thickness: number;
55
- color: Color;
56
- vertexColors: Color[];
57
- };
58
- export type LineGeometryParams = {
55
+ curves: CubicBezierCurve2d[];
56
+ distance: number;
57
+ vertexInterpolations: number[];
58
+ curveVertexIndices: number[];
59
+ }
60
+ export interface LineGeometryParams {
59
61
  pos: Vector3;
60
62
  to: Vector3;
61
- fromColor: Color | null;
62
- toColor: Color | null;
63
63
  thickness: number;
64
- };
65
- export type PolygonGeometryParams = {
66
- points: Vertex[];
67
- };
68
- export type TraceLinesParams = {
69
- vertices: Vertex[];
64
+ }
65
+ export interface TraceLinesParams {
70
66
  maxLength: number | null;
71
- };
72
- export type PipelineGroup = {
67
+ }
68
+ export interface PipelineGroup {
73
69
  triangleList: GPURenderPipeline;
74
70
  triangleStrip: GPURenderPipeline;
75
71
  lineStrip: GPURenderPipeline;
76
- };
77
- export type RenderInfo = {
78
- instanceBuffer: GPUBuffer;
79
- bindGroupLayout: GPUBindGroupLayout;
80
- vertexBuffer: GPUBuffer | null;
81
- };
82
- export type VertexParamGeneratorInfo = {
72
+ triangleListTransparent: GPURenderPipeline;
73
+ triangleStripTransparent: GPURenderPipeline;
74
+ lineStripTransparent: GPURenderPipeline;
75
+ }
76
+ export interface VertexParamGeneratorInfo {
83
77
  bufferSize: number;
84
78
  createBuffer: (x: number, y: number, z: number, color: Color) => number[];
85
- };
86
- export type ShaderInfo = {
79
+ }
80
+ export interface ShaderInfo {
87
81
  pipeline: GPURenderPipeline;
88
82
  paramGenerator: VertexParamGeneratorInfo;
89
83
  bufferInfo: {
90
84
  buffers: GPUBuffer[];
91
85
  layout: GPUBindGroupLayout;
92
86
  } | null;
93
- };
94
- export type VertexParamInfo = {
87
+ }
88
+ export interface VertexParamInfo {
95
89
  format: GPUVertexFormat;
96
90
  size: number;
97
- };
98
- export type BindGroupEntry = {
91
+ }
92
+ export interface BindGroupEntry {
99
93
  visibility: GPUBindGroupLayoutEntry['visibility'];
100
94
  buffer: GPUBindGroupLayoutEntry['buffer'];
101
- };
95
+ }
102
96
  export type ArrayConstructors = Float32ArrayConstructor | Float64ArrayConstructor | Int8ArrayConstructor | Int16ArrayConstructor | Int32ArrayConstructor;
103
- export type ArrayTypes = Float32Array | Float64Array | Int8Array | Int16Array | Int32Array;
104
- export type BindGroupValue = {
97
+ export interface BindGroupValue {
105
98
  value: number[];
106
99
  usage: GPUBufferDescriptor['usage'];
107
100
  array: ArrayConstructors;
108
- };
109
- export type BindGroupInfo = {
101
+ }
102
+ export interface BindGroupInfo {
110
103
  bindings: BindGroupEntry[];
111
104
  values: () => BindGroupValue[];
112
- };
105
+ }
106
+ export interface SimulationElementInfo {
107
+ topology: GPUPrimitiveTopology;
108
+ transparent: boolean;
109
+ cullMode: GPUCullMode;
110
+ }
111
+ export interface BufferInfo {
112
+ usage: GPUBufferDescriptor['usage'];
113
+ defaultSize?: number;
114
+ owned?: boolean;
115
+ }
116
+ export type VertexBufferWriter = (element: SimulationElement3d, buffer: Float32Array, vertex: Vector3, vertexIndex: number, offset: number) => void;
117
+ export type BufferWriter = (element: SimulationElement3d, buffers: MemoBuffer[], device: GPUDevice) => void;
118
+ export type BindGroupGenerator = (element: SimulationElement3d, buffers: MemoBuffer[]) => GPUBindGroup[];