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.
package/dist/shaders.js CHANGED
@@ -1,29 +1,138 @@
1
- import { globalInfo } from './internalUtils.js';
1
+ import { MemoBuffer } from './buffers.js';
2
+ import { mat4ByteLength } from './constants.js';
3
+ import { globalInfo } from './globals.js';
4
+ import { color, createBindGroup, writeUniformWorldMatrix } from './utils.js';
5
+ export const uniformBufferSize = mat4ByteLength * 2 + 4 * 2 + 8; // 4x4 matrix * 2 + vec2<f32> + 8 bc 144 is cool
6
+ const defaultInfos = [
7
+ {
8
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
9
+ owned: false
10
+ },
11
+ {
12
+ usage: GPUBufferUsage.STORAGE,
13
+ defaultSize: 10 * 4 * 16 // not sure where this came from, made it up a while ago
14
+ }
15
+ ];
16
+ const defaultBufferWriter = (el) => {
17
+ writeUniformWorldMatrix(el);
18
+ // not writing to buffer[0] because the buffer exists
19
+ // on the element
20
+ };
21
+ const defaultBindGroupGenerator = (el, buffers) => {
22
+ const shader = el.getShader();
23
+ const gpuBuffers = [
24
+ el.getUniformBuffer(),
25
+ el.isInstance ? el.getInstanceBuffer() : buffers[0].getBuffer()
26
+ ];
27
+ return [createBindGroup(shader, 0, gpuBuffers)];
28
+ };
2
29
  export class Shader {
3
- bindGroupLayoutDescriptor;
4
- bindGroupLayout;
30
+ bindGroupLayoutDescriptors;
31
+ bindGroupLayouts;
32
+ module;
5
33
  code;
6
- constructor(code, descriptor) {
34
+ fragmentMain;
35
+ vertexMain;
36
+ vertexBuffers;
37
+ bufferLength;
38
+ bufferWriter;
39
+ vertexBufferWriter;
40
+ bindGroupGenerator;
41
+ buffers;
42
+ bufferInfos;
43
+ constructor(code, descriptors, vertexParams, bufferInfos, bufferWriter, bindGroupGenerator, vertexBufferWriter, vertexMain = 'vertex_main', fragmentMain = 'fragment_main') {
7
44
  this.code = code;
8
- this.bindGroupLayoutDescriptor = descriptor;
9
- this.bindGroupLayout = null;
45
+ this.bindGroupLayoutDescriptors = descriptors;
46
+ this.bindGroupLayouts = null;
47
+ this.module = null;
48
+ this.bufferWriter = bufferWriter;
49
+ this.vertexBufferWriter = vertexBufferWriter;
50
+ this.bindGroupGenerator = bindGroupGenerator;
51
+ this.vertexMain = vertexMain;
52
+ this.fragmentMain = fragmentMain;
53
+ this.bufferInfos = bufferInfos;
54
+ this.buffers = [];
55
+ for (let i = 0; i < bufferInfos.length; i++) {
56
+ if (bufferInfos[i].owned === false)
57
+ continue;
58
+ this.buffers.push(new MemoBuffer(bufferInfos[i].usage, bufferInfos[i].defaultSize ?? 0));
59
+ }
60
+ let stride = 0;
61
+ const attributes = [];
62
+ for (let i = 0; i < vertexParams.length; i++) {
63
+ attributes.push({
64
+ shaderLocation: i,
65
+ offset: stride,
66
+ format: vertexParams[i].format
67
+ });
68
+ stride += vertexParams[i].size;
69
+ }
70
+ this.bufferLength = stride / 4;
71
+ this.vertexBuffers = {
72
+ arrayStride: stride,
73
+ attributes
74
+ };
10
75
  }
11
76
  getCode() {
12
77
  return this.code;
13
78
  }
14
- getBindGroupLayout() {
79
+ getBufferLength() {
80
+ return this.bufferLength;
81
+ }
82
+ getVertexBuffers() {
83
+ return this.vertexBuffers;
84
+ }
85
+ getBindGroupLayouts() {
86
+ const device = globalInfo.errorGetDevice();
87
+ if (!this.bindGroupLayouts) {
88
+ this.bindGroupLayouts = this.bindGroupLayoutDescriptors.map((descriptor) => device.createBindGroupLayout(descriptor));
89
+ }
90
+ return this.bindGroupLayouts;
91
+ }
92
+ getBindGroupLayoutDescriptors() {
93
+ return this.bindGroupLayoutDescriptors;
94
+ }
95
+ getBufferInfo() {
96
+ return this.bufferInfos;
97
+ }
98
+ getBufferWriter() {
99
+ return this.bufferWriter;
100
+ }
101
+ getVertexBufferWriter() {
102
+ return this.vertexBufferWriter;
103
+ }
104
+ getBindGroupGenerator() {
105
+ return this.bindGroupGenerator;
106
+ }
107
+ getModule() {
15
108
  const device = globalInfo.errorGetDevice();
16
- if (!this.bindGroupLayout) {
17
- this.bindGroupLayout = device.createBindGroupLayout(this.bindGroupLayoutDescriptor);
109
+ if (!this.module) {
110
+ this.module = device.createShaderModule({ code: this.code });
18
111
  }
19
- return this.bindGroupLayout;
112
+ return this.module;
113
+ }
114
+ getVertexMain() {
115
+ return this.vertexMain;
116
+ }
117
+ getFragmentMain() {
118
+ return this.fragmentMain;
119
+ }
120
+ setVertexInfo(element, buffer, vertex, vertexIndex, offset) {
121
+ this.vertexBufferWriter(element, buffer, vertex, vertexIndex, offset);
122
+ }
123
+ writeBuffers(el) {
124
+ const device = globalInfo.errorGetDevice();
125
+ this.bufferWriter(el, this.buffers, device);
20
126
  }
21
- getBindGroupLayoutDescriptor() {
22
- return this.bindGroupLayoutDescriptor;
127
+ getBindGroups(el) {
128
+ return this.bindGroupGenerator(el, this.buffers);
23
129
  }
24
130
  }
25
- export const defaultShader = new Shader(`
26
- struct Uniforms {
131
+ const positionSize = 4 * 3;
132
+ const colorSize = 4 * 4;
133
+ const uvSize = 4 * 2;
134
+ const drawingInstancesSize = 4;
135
+ export const defaultShader = new Shader(`struct Uniforms {
27
136
  worldProjectionMatrix: mat4x4<f32>,
28
137
  modelProjectionMatrix: mat4x4<f32>,
29
138
  }
@@ -69,21 +178,153 @@ fn fragment_main(
69
178
  ) -> @location(0) vec4<f32> {
70
179
  return fragColor;
71
180
  }
72
- `, {
73
- entries: [
74
- {
75
- binding: 0,
76
- visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
77
- buffer: {
78
- type: 'uniform'
181
+ `, [
182
+ {
183
+ entries: [
184
+ {
185
+ binding: 0,
186
+ visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
187
+ buffer: {
188
+ type: 'uniform'
189
+ }
190
+ },
191
+ {
192
+ binding: 1,
193
+ visibility: GPUShaderStage.VERTEX,
194
+ buffer: {
195
+ type: 'read-only-storage'
196
+ }
79
197
  }
80
- },
81
- {
82
- binding: 1,
83
- visibility: GPUShaderStage.VERTEX,
84
- buffer: {
85
- type: 'read-only-storage'
198
+ ]
199
+ }
200
+ ], [
201
+ {
202
+ size: positionSize,
203
+ format: 'float32x3'
204
+ },
205
+ {
206
+ size: colorSize,
207
+ format: 'float32x4'
208
+ },
209
+ {
210
+ size: uvSize,
211
+ format: 'float32x2'
212
+ },
213
+ {
214
+ size: drawingInstancesSize,
215
+ format: 'float32'
216
+ }
217
+ ], defaultInfos, defaultBufferWriter, defaultBindGroupGenerator, (el, buffer, vertex, _, offset) => {
218
+ const material = el.getMaterial();
219
+ const color = material.getColor();
220
+ buffer[offset] = vertex[0];
221
+ buffer[offset + 1] = vertex[1];
222
+ buffer[offset + 2] = vertex[2];
223
+ buffer[offset + 3] = color.r / 255;
224
+ buffer[offset + 4] = color.g / 255;
225
+ buffer[offset + 5] = color.b / 255;
226
+ buffer[offset + 6] = color.a;
227
+ // TODO possibly change uv for textures
228
+ buffer[offset + 7] = 0;
229
+ buffer[offset + 8] = 0;
230
+ buffer[offset + 9] = el.isInstanced ? 1 : 0;
231
+ });
232
+ export const vertexColorShader = new Shader(`
233
+ struct Uniforms {
234
+ worldProjectionMatrix: mat4x4<f32>,
235
+ modelProjectionMatrix: mat4x4<f32>,
236
+ }
237
+
238
+ @group(0) @binding(0) var<uniform> uniforms: Uniforms;
239
+
240
+ @group(0) @binding(1) var<storage> instanceMatrices: array<mat4x4f>;
241
+
242
+ struct VertexOutput {
243
+ @builtin(position) Position: vec4<f32>,
244
+ @location(0) fragUV: vec2<f32>,
245
+ @location(1) fragColor: vec4<f32>,
246
+ @location(2) fragPosition: vec4<f32>,
247
+ }
248
+
249
+ @vertex
250
+ fn vertex_main(
251
+ @builtin(instance_index) instanceIdx: u32,
252
+ @location(0) position: vec3<f32>,
253
+ @location(1) color: vec4<f32>,
254
+ @location(2) uv: vec2<f32>,
255
+ @location(3) drawingInstance: f32
256
+ ) -> VertexOutput {
257
+ var output: VertexOutput;
258
+
259
+ if (drawingInstance == 1) {
260
+ output.Position = uniforms.worldProjectionMatrix * uniforms.modelProjectionMatrix * instanceMatrices[instanceIdx] * vec4(position, 1.0);
261
+ } else {
262
+ output.Position = uniforms.worldProjectionMatrix * uniforms.modelProjectionMatrix * vec4(position, 1.0);
263
+ }
264
+
265
+ output.fragUV = uv;
266
+ output.fragPosition = output.Position;
267
+ output.fragColor = color;
268
+ return output;
269
+ }
270
+
271
+ @fragment
272
+ fn fragment_main(
273
+ @location(0) fragUV: vec2<f32>,
274
+ @location(1) fragColor: vec4<f32>,
275
+ @location(2) fragPosition: vec4<f32>
276
+ ) -> @location(0) vec4<f32> {
277
+ return fragColor;
278
+ }
279
+ `, [
280
+ {
281
+ entries: [
282
+ {
283
+ binding: 0,
284
+ visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
285
+ buffer: {
286
+ type: 'uniform'
287
+ }
288
+ },
289
+ {
290
+ binding: 1,
291
+ visibility: GPUShaderStage.VERTEX,
292
+ buffer: {
293
+ type: 'read-only-storage'
294
+ }
86
295
  }
87
- }
88
- ]
296
+ ]
297
+ }
298
+ ], [
299
+ {
300
+ size: positionSize,
301
+ format: 'float32x3'
302
+ },
303
+ {
304
+ size: colorSize,
305
+ format: 'float32x4'
306
+ },
307
+ {
308
+ size: uvSize,
309
+ format: 'float32x2'
310
+ },
311
+ {
312
+ size: drawingInstancesSize,
313
+ format: 'float32'
314
+ }
315
+ ], defaultInfos, defaultBufferWriter, defaultBindGroupGenerator, (el, buffer, vertex, vertexIndex, offset) => {
316
+ const material = el.getMaterial();
317
+ const colors = material.getVertexColors();
318
+ const vertexColor = colors[vertexIndex] ?? color();
319
+ buffer[offset] = vertex[0];
320
+ buffer[offset + 1] = vertex[1];
321
+ buffer[offset + 2] = vertex[2];
322
+ buffer[offset + 3] = vertexColor.r / 255;
323
+ buffer[offset + 4] = vertexColor.g / 255;
324
+ buffer[offset + 5] = vertexColor.b / 255;
325
+ buffer[offset + 6] = vertexColor.a;
326
+ // TODO possibly change uv for textures
327
+ buffer[offset + 7] = 0;
328
+ buffer[offset + 8] = 0;
329
+ buffer[offset + 9] = el.isInstanced ? 1 : 0;
89
330
  });
@@ -1,9 +1,10 @@
1
- /// <reference types="@webgpu/types" />
2
- import { EmptyElement, SimulationElement3d } from './graphics.js';
3
- import type { Vector2, Vector3, LerpFunc, AnySimulationElement, VertexParamGeneratorInfo, VertexParamInfo, BindGroupInfo } from './types.js';
1
+ import { SimulationElement3d } from './graphics.js';
2
+ import type { Vector2, Vector3, LerpFunc, AnySimulationElement } from './types.js';
4
3
  import { Color } from './utils.js';
5
4
  import { SimSceneObjInfo } from './internalUtils.js';
6
5
  import { Settings } from './settings.js';
6
+ export declare const worldProjectionMatrix: import("./types.js").Mat4;
7
+ export declare const orthogonalMatrix: import("./types.js").Mat4;
7
8
  export declare class Camera {
8
9
  private pos;
9
10
  private rotation;
@@ -31,12 +32,11 @@ export declare class Simulation extends Settings {
31
32
  private fittingElement;
32
33
  private running;
33
34
  private initialized;
34
- private pipelines;
35
- private renderInfo;
36
35
  private resizeEvents;
37
36
  private frameRateView;
38
37
  private transparentElements;
39
38
  private vertexBuffer;
39
+ private indexBuffer;
40
40
  constructor(idOrCanvasRef: string | HTMLCanvasElement, sceneCamera?: Camera | null, showFrameRate?: boolean);
41
41
  private handleCanvasResize;
42
42
  onResize(cb: (width: number, height: number) => void): void;
@@ -60,22 +60,3 @@ export declare class Simulation extends Settings {
60
60
  private renderScene;
61
61
  fitElement(): void;
62
62
  }
63
- export declare class ShaderGroup extends EmptyElement {
64
- private code;
65
- private module;
66
- private pipeline;
67
- private bindGroupLayout;
68
- private topology;
69
- private paramGenerator;
70
- private vertexParams;
71
- private bindGroup;
72
- private valueBuffers;
73
- constructor(shaderCode: string, topology: GPUPrimitiveTopology | undefined, vertexParams: VertexParamInfo[], paramGenerator: VertexParamGeneratorInfo, bindGroup?: BindGroupInfo);
74
- private initPipeline;
75
- getBindGroupLayout(): GPUBindGroupLayout | null;
76
- getPipeline(): GPURenderPipeline | null;
77
- getBindGroupBuffers(device: GPUDevice): GPUBuffer[] | null;
78
- private createBuffer;
79
- getVertexParamGenerator(): VertexParamGeneratorInfo;
80
- hasBindGroup(): boolean;
81
- }