simulationjsv2 0.7.4 → 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,12 +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 createUniformBindGroup, { SimSceneObjInfo, buildDepthTexture, buildMultisampleTexture, updateProjectionMatrix, createPipeline, getTotalVertices, logger, removeObjectId, updateOrthoProjectionMatrix, updateWorldProjectionMatrix, globalInfo, CachedArray, createDefaultPipelines } 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
- import { defaultShader } from './shaders.js';
9
6
  import { MemoBuffer } from './buffers.js';
7
+ import { globalInfo, logger } from './globals.js';
10
8
  const simjsFrameRateCss = `.simjs-frame-rate {
11
9
  position: absolute;
12
10
  top: 0;
@@ -55,8 +53,8 @@ class FrameRateView {
55
53
  }
56
54
  let aspectRatio = 0;
57
55
  const projMat = matrix4();
58
- const worldProjMat = matrix4();
59
- const orthoMatrix = matrix4();
56
+ export const worldProjectionMatrix = matrix4();
57
+ export const orthogonalMatrix = matrix4();
60
58
  export class Camera {
61
59
  pos;
62
60
  rotation;
@@ -152,12 +150,11 @@ export class Simulation extends Settings {
152
150
  fittingElement = false;
153
151
  running = true;
154
152
  initialized = false;
155
- pipelines = null;
156
- renderInfo = null;
157
153
  resizeEvents;
158
154
  frameRateView;
159
155
  transparentElements;
160
156
  vertexBuffer;
157
+ indexBuffer;
161
158
  constructor(idOrCanvasRef, sceneCamera = null, showFrameRate = false) {
162
159
  super();
163
160
  if (typeof idOrCanvasRef === 'string') {
@@ -185,6 +182,7 @@ export class Simulation extends Settings {
185
182
  this.frameRateView.updateFrameRate(1);
186
183
  this.transparentElements = new CachedArray();
187
184
  this.vertexBuffer = new MemoBuffer(GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST, 0);
185
+ this.indexBuffer = new MemoBuffer(GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST, 0);
188
186
  }
189
187
  handleCanvasResize(parent) {
190
188
  if (this.fittingElement) {
@@ -274,14 +272,6 @@ export class Simulation extends Settings {
274
272
  format: presentationFormat,
275
273
  alphaMode: 'opaque'
276
274
  });
277
- this.pipelines = createDefaultPipelines(defaultShader);
278
- const instanceBuffer = device.createBuffer({
279
- size: 10 * 4 * 16,
280
- usage: GPUBufferUsage.STORAGE
281
- });
282
- this.renderInfo = {
283
- instanceBuffer
284
- };
285
275
  this.render(device, ctx, canvas);
286
276
  })();
287
277
  }
@@ -311,8 +301,8 @@ export class Simulation extends Settings {
311
301
  updateProjectionMatrix(projMat, newAspectRatio);
312
302
  aspectRatio = newAspectRatio;
313
303
  }
314
- updateWorldProjectionMatrix(worldProjMat, projMat);
315
- updateOrthoProjectionMatrix(orthoMatrix, camera.getScreenSize());
304
+ updateWorldProjectionMatrix(worldProjectionMatrix, projMat);
305
+ updateOrthoProjectionMatrix(orthogonalMatrix, camera.getScreenSize());
316
306
  let multisampleTexture = buildMultisampleTexture(device, ctx, canvas.width, canvas.height);
317
307
  let depthTexture = buildDepthTexture(device, canvas.width, canvas.height);
318
308
  const renderPassDescriptor = {
@@ -328,7 +318,7 @@ export class Simulation extends Settings {
328
318
  let prev = Date.now() - 10;
329
319
  let prevFps = 0;
330
320
  const frame = async () => {
331
- if (!canvas || !this.renderInfo)
321
+ if (!canvas)
332
322
  return;
333
323
  requestAnimationFrame(frame);
334
324
  if (!this.running)
@@ -348,7 +338,7 @@ export class Simulation extends Settings {
348
338
  screenSize[1] = canvas.height;
349
339
  aspectRatio = camera.getAspectRatio();
350
340
  updateProjectionMatrix(projMat, aspectRatio);
351
- updateWorldProjectionMatrix(worldProjMat, projMat);
341
+ updateWorldProjectionMatrix(worldProjectionMatrix, projMat);
352
342
  multisampleTexture = buildMultisampleTexture(device, ctx, screenSize[0], screenSize[1]);
353
343
  depthTexture = buildDepthTexture(device, screenSize[0], screenSize[1]);
354
344
  renderPassDescriptor.depthStencilAttachment.view = depthTexture.createView();
@@ -360,133 +350,72 @@ export class Simulation extends Settings {
360
350
  // @ts-ignore
361
351
  renderPassDescriptor.colorAttachments[0].resolveTarget = ctx.getCurrentTexture().createView();
362
352
  if (camera.hasUpdated()) {
363
- updateOrthoProjectionMatrix(orthoMatrix, camera.getScreenSize());
364
- updateWorldProjectionMatrix(worldProjMat, projMat);
353
+ updateOrthoProjectionMatrix(orthogonalMatrix, camera.getScreenSize());
354
+ updateWorldProjectionMatrix(worldProjectionMatrix, projMat);
365
355
  }
366
356
  const commandEncoder = device.createCommandEncoder();
367
357
  const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
368
- const totalVertices = getTotalVertices(this.scene);
369
- this.vertexBuffer.setSize(totalVertices * 4 * BUF_LEN);
358
+ const [totalVerticesSize, totalIndexSize] = getVertexAndIndexSize(this.scene);
359
+ this.vertexBuffer.setSize(totalVerticesSize * 4);
360
+ this.indexBuffer.setSize(totalIndexSize * 4);
370
361
  this.transparentElements.reset();
371
- const opaqueOffset = this.renderScene(device, passEncoder, this.vertexBuffer.getBuffer(), this.scene, 0, diff, false);
372
- this.renderScene(device, passEncoder, this.vertexBuffer.getBuffer(), this.transparentElements.toArray(), opaqueOffset, diff, true);
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);
373
364
  camera.updateConsumed();
374
365
  passEncoder.end();
375
366
  device.queue.submit([commandEncoder.finish()]);
376
367
  };
377
368
  requestAnimationFrame(frame);
378
369
  }
379
- renderScene(device, passEncoder, vertexBuffer, scene, startOffset, diff, transparent, shaderInfo) {
380
- if (this.pipelines === null)
381
- return 0;
382
- let currentOffset = startOffset;
370
+ renderScene(device, passEncoder, vertexBuffer, indexBuffer, startVertexOffset, startIndexOffset, scene, numElements, diff, transparent) {
371
+ let vertexOffset = startVertexOffset;
372
+ let indexOffset = startIndexOffset;
383
373
  const toRemove = [];
384
- for (let i = 0; i < scene.length; i++) {
385
- const lifetime = scene[i].getLifetime();
374
+ for (let i = 0; i < numElements; i++) {
375
+ const sceneObj = scene[i];
376
+ const lifetime = sceneObj.getLifetime();
386
377
  if (lifetime !== null) {
387
- const complete = scene[i].lifetimeComplete();
378
+ const complete = sceneObj.lifetimeComplete();
388
379
  if (complete) {
389
380
  toRemove.push(i);
390
381
  continue;
391
382
  }
392
- scene[i].traverseLife(diff);
383
+ sceneObj.traverseLife(diff);
393
384
  }
394
- const obj = scene[i].getObj();
385
+ const obj = sceneObj.getObj();
395
386
  if (!transparent && obj.isTransparent()) {
396
- this.transparentElements.add(scene[i]);
387
+ this.transparentElements.add(sceneObj);
397
388
  continue;
398
389
  }
399
390
  if (obj.hasChildren()) {
400
- let shaderInfo = undefined;
401
- if (obj instanceof ShaderGroup) {
402
- const pipeline = obj.getPipeline();
403
- if (pipeline !== null) {
404
- shaderInfo = {
405
- pipeline,
406
- paramGenerator: obj.getVertexParamGenerator(),
407
- bufferInfo: obj.hasBindGroup()
408
- ? {
409
- buffers: obj.getBindGroupBuffers(device),
410
- layout: obj.getBindGroupLayout()
411
- }
412
- : null
413
- };
414
- }
415
- }
416
- currentOffset += this.renderScene(device, passEncoder, vertexBuffer, obj.getChildrenInfos(), currentOffset, diff, transparent, 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;
417
395
  }
418
396
  if (obj.isEmpty)
419
397
  continue;
420
- const buffer = new Float32Array(obj.getBuffer(shaderInfo?.paramGenerator));
421
- const bufLen = shaderInfo?.paramGenerator?.bufferSize || BUF_LEN;
422
- const vertexCount = buffer.length / bufLen;
423
- device.queue.writeBuffer(vertexBuffer, currentOffset, buffer.buffer, buffer.byteOffset, buffer.byteLength);
424
- vertexBuffer.unmap();
425
- passEncoder.setVertexBuffer(0, vertexBuffer, currentOffset, buffer.byteLength);
426
- const modelMatrix = obj.getModelMatrix();
427
- const uniformBuffer = obj.getUniformBuffer(modelMatrix);
428
- const projBuf = obj.is3d ? worldProjMat : orthoMatrix;
429
- device.queue.writeBuffer(uniformBuffer, worldProjMatOffset, projBuf.buffer, projBuf.byteOffset, projBuf.byteLength);
430
- if (shaderInfo) {
431
- passEncoder.setPipeline(shaderInfo.pipeline);
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]);
432
410
  }
433
- else if (obj.isWireframe()) {
434
- if (obj.isTransparent())
435
- passEncoder.setPipeline(this.pipelines.lineStripTransparent);
436
- else
437
- passEncoder.setPipeline(this.pipelines.lineStrip);
438
- }
439
- else {
440
- const type = obj.getGeometryType();
441
- // must be exhaustive
442
- if (type === 'strip') {
443
- if (obj.isTransparent())
444
- passEncoder.setPipeline(this.pipelines.triangleStripTransparent);
445
- else
446
- passEncoder.setPipeline(this.pipelines.triangleStrip);
447
- }
448
- else if (type === 'list') {
449
- if (obj.isTransparent())
450
- passEncoder.setPipeline(this.pipelines.triangleListTransparent);
451
- else
452
- passEncoder.setPipeline(this.pipelines.triangleList);
453
- }
454
- }
455
- let instances = 1;
456
- if (this.renderInfo) {
457
- let instanceBuffer;
458
- if (obj.isInstance) {
459
- instances = obj.getNumInstances();
460
- instanceBuffer =
461
- obj.getMatrixBuffer() ?? this.renderInfo.instanceBuffer;
462
- }
463
- else {
464
- instanceBuffer = this.renderInfo.instanceBuffer;
465
- }
466
- const uniformBindGroup = createUniformBindGroup(defaultShader, [uniformBuffer, instanceBuffer]);
467
- passEncoder.setBindGroup(0, uniformBindGroup);
468
- }
469
- if (shaderInfo && shaderInfo.bufferInfo) {
470
- const bindGroupEntries = shaderInfo.bufferInfo.buffers.map((buffer, index) => ({
471
- binding: index,
472
- resource: {
473
- buffer
474
- }
475
- }));
476
- const bindGroup = device.createBindGroup({
477
- layout: shaderInfo.bufferInfo.layout,
478
- entries: bindGroupEntries
479
- });
480
- passEncoder.setBindGroup(1, bindGroup);
481
- }
482
- // TODO maybe switch to drawIndexed
483
- passEncoder.draw(vertexCount, instances, 0, 0);
484
- currentOffset += buffer.byteLength;
411
+ passEncoder.drawIndexed(indices.length, instances);
412
+ vertexOffset += vertices.byteLength;
413
+ indexOffset += indices.byteLength;
485
414
  }
486
415
  for (let i = toRemove.length - 1; i >= 0; i--) {
487
- this.remove(scene[i].getObj());
416
+ this.remove(scene.at(i).getObj());
488
417
  }
489
- return currentOffset - startOffset;
418
+ return [vertexOffset - startVertexOffset, indexOffset - startIndexOffset];
490
419
  }
491
420
  fitElement() {
492
421
  if (this.canvasRef === null)
@@ -500,114 +429,3 @@ export class Simulation extends Settings {
500
429
  }
501
430
  }
502
431
  }
503
- const defaultShaderCode = `
504
- struct Uniforms {
505
- worldProjectionMatrix: mat4x4<f32>,
506
- modelProjectionMatrix: mat4x4<f32>,
507
- }
508
-
509
- @group(0) @binding(0) var<uniform> uniforms: Uniforms;
510
-
511
- @group(0) @binding(1) var<storage> instanceMatrices: array<mat4x4f>;
512
- `;
513
- export class ShaderGroup extends EmptyElement {
514
- code;
515
- module;
516
- pipeline;
517
- bindGroupLayout;
518
- topology;
519
- paramGenerator;
520
- vertexParams;
521
- bindGroup;
522
- valueBuffers;
523
- constructor(shaderCode, topology = 'triangle-list', vertexParams, paramGenerator, bindGroup) {
524
- super();
525
- this.geometry = new BlankGeometry();
526
- this.code = defaultShaderCode + shaderCode;
527
- this.module = null;
528
- this.pipeline = null;
529
- this.bindGroupLayout = null;
530
- this.bindGroup = bindGroup || null;
531
- this.topology = topology;
532
- this.paramGenerator = paramGenerator;
533
- this.vertexParams = vertexParams;
534
- this.valueBuffers = null;
535
- }
536
- initPipeline() {
537
- const device = globalInfo.errorGetDevice();
538
- this.module = device.createShaderModule({ code: this.code });
539
- const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
540
- const bindGroupLayout = defaultShader.getBindGroupLayout();
541
- const bindGroups = [bindGroupLayout];
542
- if (this.bindGroup !== null) {
543
- const entryValues = this.bindGroup.bindings.map((binding, index) => ({
544
- binding: index,
545
- visibility: binding.visibility,
546
- buffer: binding.buffer
547
- }));
548
- this.bindGroupLayout = device.createBindGroupLayout({
549
- entries: entryValues
550
- });
551
- bindGroups.push(this.bindGroupLayout);
552
- }
553
- this.pipeline = createPipeline(device, this.module, bindGroups, presentationFormat, this.topology,
554
- // TODO possibly make transparent materials
555
- false, this.vertexParams);
556
- }
557
- getBindGroupLayout() {
558
- return this.bindGroupLayout;
559
- }
560
- getPipeline() {
561
- if (!this.pipeline)
562
- this.initPipeline();
563
- return this.pipeline;
564
- }
565
- getBindGroupBuffers(device) {
566
- if (this.bindGroup === null)
567
- return null;
568
- if (device === null)
569
- return null;
570
- const values = this.bindGroup.values();
571
- if (this.valueBuffers === null) {
572
- this.valueBuffers = [];
573
- for (let i = 0; i < values.length; i++) {
574
- const buffer = this.createBuffer(device, values[i]);
575
- this.valueBuffers.push(buffer);
576
- }
577
- }
578
- else {
579
- for (let i = 0; i < values.length; i++) {
580
- const arrayConstructor = values[i].array;
581
- const array = new arrayConstructor(values[i].value);
582
- if (array.byteLength > this.valueBuffers[i].size) {
583
- const newBuffer = this.createBuffer(device, values[i]);
584
- this.valueBuffers[i].destroy();
585
- this.valueBuffers[i] = newBuffer;
586
- }
587
- else {
588
- device.queue.writeBuffer(this.valueBuffers[i], 0, array.buffer, array.byteOffset, array.byteLength);
589
- }
590
- }
591
- }
592
- return this.valueBuffers;
593
- }
594
- createBuffer(device, value) {
595
- const arrayConstructor = value.array;
596
- const array = new arrayConstructor(value.value);
597
- const buffer = device.createBuffer({
598
- mappedAtCreation: true,
599
- size: array.byteLength,
600
- usage: value.usage
601
- });
602
- const bufferArr = new arrayConstructor(buffer.getMappedRange());
603
- bufferArr.set(array);
604
- buffer.unmap();
605
- return buffer;
606
- }
607
- getVertexParamGenerator() {
608
- return this.paramGenerator;
609
- }
610
- hasBindGroup() {
611
- return !!this.bindGroup;
612
- }
613
- }
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,85 +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
72
  triangleListTransparent: GPURenderPipeline;
77
73
  triangleStripTransparent: GPURenderPipeline;
78
74
  lineStripTransparent: GPURenderPipeline;
79
- };
80
- export type RenderInfo = {
81
- instanceBuffer: GPUBuffer;
82
- };
83
- export type VertexParamGeneratorInfo = {
75
+ }
76
+ export interface VertexParamGeneratorInfo {
84
77
  bufferSize: number;
85
78
  createBuffer: (x: number, y: number, z: number, color: Color) => number[];
86
- };
87
- export type ShaderInfo = {
79
+ }
80
+ export interface ShaderInfo {
88
81
  pipeline: GPURenderPipeline;
89
82
  paramGenerator: VertexParamGeneratorInfo;
90
83
  bufferInfo: {
91
84
  buffers: GPUBuffer[];
92
85
  layout: GPUBindGroupLayout;
93
86
  } | null;
94
- };
95
- export type VertexParamInfo = {
87
+ }
88
+ export interface VertexParamInfo {
96
89
  format: GPUVertexFormat;
97
90
  size: number;
98
- };
99
- export type BindGroupEntry = {
91
+ }
92
+ export interface BindGroupEntry {
100
93
  visibility: GPUBindGroupLayoutEntry['visibility'];
101
94
  buffer: GPUBindGroupLayoutEntry['buffer'];
102
- };
95
+ }
103
96
  export type ArrayConstructors = Float32ArrayConstructor | Float64ArrayConstructor | Int8ArrayConstructor | Int16ArrayConstructor | Int32ArrayConstructor;
104
- export type ArrayTypes = Float32Array | Float64Array | Int8Array | Int16Array | Int32Array;
105
- export type BindGroupValue = {
97
+ export interface BindGroupValue {
106
98
  value: number[];
107
99
  usage: GPUBufferDescriptor['usage'];
108
100
  array: ArrayConstructors;
109
- };
110
- export type BindGroupInfo = {
101
+ }
102
+ export interface BindGroupInfo {
111
103
  bindings: BindGroupEntry[];
112
104
  values: () => BindGroupValue[];
113
- };
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[];
package/dist/utils.d.ts CHANGED
@@ -1,12 +1,15 @@
1
- import { SplinePoint2d } from './graphics.js';
1
+ /// <reference types="@webgpu/types" />
2
+ import { SimulationElement3d, SplinePoint2d } from './graphics.js';
2
3
  import { AnySimulationElement, FloatArray, Mat4, Vector2, Vector3, Vector4 } from './types.js';
3
4
  import { SimSceneObjInfo } from './internalUtils.js';
5
+ import { Shader } from './shaders.js';
4
6
  export declare class Color {
5
7
  r: number;
6
8
  g: number;
7
9
  b: number;
8
10
  a: number;
9
11
  constructor(r?: number, g?: number, b?: number, a?: number);
12
+ static fromVec4(vec: Vector4): Color;
10
13
  clone(): Color;
11
14
  toBuffer(): readonly [number, number, number, number];
12
15
  toVec4(): Vector4;
@@ -17,6 +20,8 @@ export declare class Color {
17
20
  a: number;
18
21
  };
19
22
  diff(color: Color): Color;
23
+ isTransparent(): boolean;
24
+ setValues(color: Color): void;
20
25
  }
21
26
  export declare class Vertex {
22
27
  private pos;
@@ -33,7 +38,6 @@ export declare class Vertex {
33
38
  setY(y: number): void;
34
39
  setZ(z: number): void;
35
40
  clone(): Vertex;
36
- toBuffer(defaultColor: Color): number[];
37
41
  }
38
42
  /**
39
43
  * @param onFrame - called every frame until the animation is finished
@@ -64,7 +68,6 @@ export declare function vector2(x?: number, y?: number): Vector2;
64
68
  export declare function matrix4(): Mat4;
65
69
  export declare function vector3FromVector2(vec: Vector2): Vector3;
66
70
  export declare function vector2FromVector3(vec: Vector3): Vector2;
67
- export declare function colorFromVector4(vec: Vector4): Color;
68
71
  export declare function randomInt(range: number, min?: number): number;
69
72
  export declare function randomColor(a?: number): Color;
70
73
  export declare function vertex(x?: number, y?: number, z?: number, color?: Color, uv?: Vector2): Vertex;
@@ -81,4 +84,6 @@ export declare function distance3d(vector1: Vector3, vector2: Vector3): number;
81
84
  export declare function toSceneObjInfo(el: AnySimulationElement, id?: string): SimSceneObjInfo;
82
85
  export declare function toSceneObjInfoMany(el: AnySimulationElement[], id?: (string | undefined)[]): SimSceneObjInfo[];
83
86
  export declare function interpolateColors(colors: Color[], t: number): Color;
87
+ export declare function createBindGroup(shader: Shader, bindGroupIndex: number, buffers: GPUBuffer[]): GPUBindGroup;
88
+ export declare function writeUniformWorldMatrix(el: SimulationElement3d): void;
84
89
  export {};
package/dist/utils.js CHANGED
@@ -1,6 +1,9 @@
1
1
  import { mat4, vec2, vec3, vec4 } from 'wgpu-matrix';
2
2
  import { SplinePoint2d } from './graphics.js';
3
- import { SimSceneObjInfo, bufferGenerator } from './internalUtils.js';
3
+ import { SimSceneObjInfo } from './internalUtils.js';
4
+ import { globalInfo } from './globals.js';
5
+ import { orthogonalMatrix, worldProjectionMatrix } from './simulation.js';
6
+ import { worldProjMatOffset } from './constants.js';
4
7
  export class Color {
5
8
  r; // 0 - 255
6
9
  g; // 0 - 255
@@ -12,6 +15,9 @@ export class Color {
12
15
  this.b = b;
13
16
  this.a = a;
14
17
  }
18
+ static fromVec4(vec) {
19
+ return new Color(vec[0], vec[1], vec[2], vec[3]);
20
+ }
15
21
  clone() {
16
22
  return new Color(this.r, this.g, this.b, this.a);
17
23
  }
@@ -32,6 +38,15 @@ export class Color {
32
38
  diff(color) {
33
39
  return new Color(this.r - color.r, this.g - color.g, this.b - color.b, this.a - color.a);
34
40
  }
41
+ isTransparent() {
42
+ return this.a < 1;
43
+ }
44
+ setValues(color) {
45
+ this.r = color.r;
46
+ this.g = color.g;
47
+ this.b = color.b;
48
+ this.a = color.a;
49
+ }
35
50
  }
36
51
  export class Vertex {
37
52
  pos;
@@ -39,7 +54,7 @@ export class Vertex {
39
54
  uv;
40
55
  constructor(x = 0, y = 0, z = 0, color, uv = vector2()) {
41
56
  this.pos = vector3(x, y, z);
42
- this.color = color || null;
57
+ this.color = color ?? null;
43
58
  this.uv = uv;
44
59
  }
45
60
  getPos() {
@@ -72,9 +87,6 @@ export class Vertex {
72
87
  clone() {
73
88
  return new Vertex(this.pos[0], this.pos[1], this.pos[2], this.color?.clone(), cloneBuf(this.uv));
74
89
  }
75
- toBuffer(defaultColor) {
76
- return bufferGenerator.generate(this.pos[0], this.pos[1], this.pos[2], this.color || defaultColor, this.uv);
77
- }
78
90
  }
79
91
  /**
80
92
  * @param onFrame - called every frame until the animation is finished
@@ -206,9 +218,6 @@ export function vector3FromVector2(vec) {
206
218
  export function vector2FromVector3(vec) {
207
219
  return vector2(vec[0], vec[1]);
208
220
  }
209
- export function colorFromVector4(vec) {
210
- return new Color(vec[0], vec[1], vec[2], vec[3]);
211
- }
212
221
  export function randomInt(range, min = 0) {
213
222
  return Math.floor(Math.random() * (range - min)) + min;
214
223
  }
@@ -284,3 +293,22 @@ export function interpolateColors(colors, t) {
284
293
  res.a += diff.a;
285
294
  return res;
286
295
  }
296
+ export function createBindGroup(shader, bindGroupIndex, buffers) {
297
+ const device = globalInfo.errorGetDevice();
298
+ const layout = shader.getBindGroupLayouts()[bindGroupIndex];
299
+ return device.createBindGroup({
300
+ layout: layout,
301
+ entries: buffers.map((buffer, index) => ({
302
+ binding: index,
303
+ resource: {
304
+ buffer
305
+ }
306
+ }))
307
+ });
308
+ }
309
+ export function writeUniformWorldMatrix(el) {
310
+ const device = globalInfo.errorGetDevice();
311
+ const uniformBuffer = el.getUniformBuffer();
312
+ const projBuf = el.is3d ? worldProjectionMatrix : orthogonalMatrix;
313
+ device.queue.writeBuffer(uniformBuffer, worldProjMatOffset, projBuf.buffer, projBuf.byteOffset, projBuf.byteLength);
314
+ }
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "types": "./dist/index.d.ts",
6
6
  "author": "Jackson Otto",
7
7
  "description": "A simple graphics library using WebGPU",
8
- "version": "0.7.4",
8
+ "version": "0.8.0",
9
9
  "exports": {
10
10
  ".": {
11
11
  "import": "./dist/index.js",
@@ -1 +0,0 @@
1
- export {};
package/dist/pipelines.js DELETED
@@ -1 +0,0 @@
1
- export {};