simulationjsv2 0.4.9 → 0.4.10
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/TODO.md +1 -1
- package/dist/geometry.d.ts +8 -8
- package/dist/geometry.js +14 -15
- package/dist/graphics.d.ts +2 -2
- package/dist/graphics.js +7 -5
- package/dist/internalUtils.d.ts +3 -3
- package/dist/internalUtils.js +52 -29
- package/dist/simulation.d.ts +19 -5
- package/dist/simulation.js +97 -14
- package/dist/types.d.ts +17 -0
- package/package.json +1 -1
package/TODO.md
CHANGED
package/dist/geometry.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CircleGeometryParams, CubeGeometryParams, EmptyParams, Line2dGeometryParams, Line3dGeometryParams, Mat4, PolygonGeometryParams, Spline2dGeometryParams, SquareGeometryParams, Vector2, Vector3, VertexColorMap } from './types.js';
|
|
1
|
+
import { BufferExtenderInfo, CircleGeometryParams, CubeGeometryParams, EmptyParams, Line2dGeometryParams, Line3dGeometryParams, Mat4, PolygonGeometryParams, Spline2dGeometryParams, SquareGeometryParams, Vector2, Vector3, VertexColorMap } from './types.js';
|
|
2
2
|
import { Color, Vertex } from './utils.js';
|
|
3
3
|
import { CubicBezierCurve2d, SplinePoint2d } from './graphics.js';
|
|
4
4
|
export declare abstract class Geometry<T extends EmptyParams> {
|
|
@@ -14,9 +14,9 @@ export declare abstract class Geometry<T extends EmptyParams> {
|
|
|
14
14
|
abstract recompute(): void;
|
|
15
15
|
getTriangleVertexCount(): number;
|
|
16
16
|
getWireframeVertexCount(): number;
|
|
17
|
-
protected bufferFromOrder(order: number[], color: Color): number[];
|
|
18
|
-
getWireframeBuffer(color: Color): number[];
|
|
19
|
-
getTriangleBuffer(color: Color): number[];
|
|
17
|
+
protected bufferFromOrder(order: number[], color: Color, bufferExtender?: BufferExtenderInfo): number[];
|
|
18
|
+
getWireframeBuffer(color: Color, bufferExtender?: BufferExtenderInfo): number[];
|
|
19
|
+
getTriangleBuffer(color: Color, bufferExtender?: BufferExtenderInfo): number[];
|
|
20
20
|
}
|
|
21
21
|
export declare class PlaneGeometry extends Geometry<EmptyParams> {
|
|
22
22
|
protected params: {};
|
|
@@ -26,7 +26,7 @@ export declare class PlaneGeometry extends Geometry<EmptyParams> {
|
|
|
26
26
|
constructor(vertices: Vertex[]);
|
|
27
27
|
recompute(): void;
|
|
28
28
|
updateVertices(vertices: Vertex[]): void;
|
|
29
|
-
getTriangleBuffer(color: Color): number[];
|
|
29
|
+
getTriangleBuffer(color: Color, bufferExtender?: BufferExtenderInfo): number[];
|
|
30
30
|
}
|
|
31
31
|
export declare class CubeGeometry extends Geometry<CubeGeometryParams> {
|
|
32
32
|
protected params: CubeGeometryParams;
|
|
@@ -48,7 +48,7 @@ export declare class SquareGeometry extends Geometry<SquareGeometryParams> {
|
|
|
48
48
|
setWidth(width: number): void;
|
|
49
49
|
setHeight(height: number): void;
|
|
50
50
|
recompute(): void;
|
|
51
|
-
getTriangleBuffer(color: Color): number[];
|
|
51
|
+
getTriangleBuffer(color: Color, bufferExtender?: BufferExtenderInfo): number[];
|
|
52
52
|
}
|
|
53
53
|
export declare class BlankGeometry extends Geometry<EmptyParams> {
|
|
54
54
|
protected wireframeOrder: never[];
|
|
@@ -83,8 +83,8 @@ export declare class Spline2dGeometry extends Geometry<Spline2dGeometryParams> {
|
|
|
83
83
|
private computeCurves;
|
|
84
84
|
private updateWireframeOrder;
|
|
85
85
|
recompute(): void;
|
|
86
|
-
getWireframeBuffer(color: Color): number[];
|
|
87
|
-
getTriangleBuffer(_: Color): number[];
|
|
86
|
+
getWireframeBuffer(color: Color, bufferExtender?: BufferExtenderInfo): number[];
|
|
87
|
+
getTriangleBuffer(_: Color, bufferExtender?: BufferExtenderInfo): number[];
|
|
88
88
|
}
|
|
89
89
|
export declare class Line2dGeometry extends Geometry<Line2dGeometryParams> {
|
|
90
90
|
protected wireframeOrder: number[];
|
package/dist/geometry.js
CHANGED
|
@@ -24,20 +24,20 @@ export class Geometry {
|
|
|
24
24
|
getWireframeVertexCount() {
|
|
25
25
|
return this.wireframeOrder.length;
|
|
26
26
|
}
|
|
27
|
-
bufferFromOrder(order, color) {
|
|
27
|
+
bufferFromOrder(order, color, bufferExtender) {
|
|
28
28
|
return order
|
|
29
29
|
.map((vertexIndex) => {
|
|
30
30
|
const pos = cloneBuf(this.vertices[vertexIndex]);
|
|
31
31
|
vec3.transformMat4(pos, this.matrix, pos);
|
|
32
|
-
return bufferGenerator.generate(pos[0], pos[1], pos[2], color);
|
|
32
|
+
return bufferGenerator.generate(pos[0], pos[1], pos[2], color, vector2(), bufferExtender);
|
|
33
33
|
})
|
|
34
34
|
.flat();
|
|
35
35
|
}
|
|
36
|
-
getWireframeBuffer(color) {
|
|
37
|
-
return this.bufferFromOrder(this.wireframeOrder, color);
|
|
36
|
+
getWireframeBuffer(color, bufferExtender) {
|
|
37
|
+
return this.bufferFromOrder(this.wireframeOrder, color, bufferExtender);
|
|
38
38
|
}
|
|
39
|
-
getTriangleBuffer(color) {
|
|
40
|
-
return this.bufferFromOrder(this.triangleOrder, color);
|
|
39
|
+
getTriangleBuffer(color, bufferExtender) {
|
|
40
|
+
return this.bufferFromOrder(this.triangleOrder, color, bufferExtender);
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
export class PlaneGeometry extends Geometry {
|
|
@@ -61,13 +61,13 @@ export class PlaneGeometry extends Geometry {
|
|
|
61
61
|
.fill(0)
|
|
62
62
|
.map((_, index) => index)).flat();
|
|
63
63
|
}
|
|
64
|
-
getTriangleBuffer(color) {
|
|
64
|
+
getTriangleBuffer(color, bufferExtender) {
|
|
65
65
|
return this.triangleOrder
|
|
66
66
|
.map((index) => {
|
|
67
67
|
const vertex = this.rawVertices[index];
|
|
68
68
|
const pos = cloneBuf(vertex.getPos());
|
|
69
69
|
vec3.transformMat4(pos, this.matrix, pos);
|
|
70
|
-
return bufferGenerator.generate(pos[0], pos[1], pos[2], vertex.getColor() || color);
|
|
70
|
+
return bufferGenerator.generate(pos[0], pos[1], pos[2], vertex.getColor() || color, vector2(), bufferExtender);
|
|
71
71
|
})
|
|
72
72
|
.flat();
|
|
73
73
|
}
|
|
@@ -155,12 +155,12 @@ export class SquareGeometry extends Geometry {
|
|
|
155
155
|
vector3(-this.params.width * centerOffset[0], -this.params.height * (1 - centerOffset[1]))
|
|
156
156
|
];
|
|
157
157
|
}
|
|
158
|
-
getTriangleBuffer(color) {
|
|
158
|
+
getTriangleBuffer(color, bufferExtender) {
|
|
159
159
|
return this.triangleOrder
|
|
160
160
|
.map((vertexIndex) => {
|
|
161
161
|
const pos = cloneBuf(this.vertices[vertexIndex]);
|
|
162
162
|
vec3.transformMat4(pos, this.matrix, pos);
|
|
163
|
-
return bufferGenerator.generate(pos[0], pos[1], pos[2], this.params.colorMap[vertexIndex] || color);
|
|
163
|
+
return bufferGenerator.generate(pos[0], pos[1], pos[2], this.params.colorMap[vertexIndex] || color, vector2(), bufferExtender);
|
|
164
164
|
})
|
|
165
165
|
.flat();
|
|
166
166
|
}
|
|
@@ -349,22 +349,21 @@ export class Spline2dGeometry extends Geometry {
|
|
|
349
349
|
.map((_, index) => index)).flat();
|
|
350
350
|
this.updateWireframeOrder();
|
|
351
351
|
}
|
|
352
|
-
getWireframeBuffer(color) {
|
|
352
|
+
getWireframeBuffer(color, bufferExtender) {
|
|
353
353
|
return this.wireframeOrder
|
|
354
354
|
.map((vertexIndex) => {
|
|
355
355
|
const vertex = cloneBuf(this.vertices[vertexIndex]);
|
|
356
356
|
vec3.transformMat4(vertex, this.matrix, vertex);
|
|
357
|
-
return bufferGenerator.generate(vertex[0], vertex[1], vertex[2], color);
|
|
357
|
+
return bufferGenerator.generate(vertex[0], vertex[1], vertex[2], color, vector2(), bufferExtender);
|
|
358
358
|
})
|
|
359
359
|
.flat();
|
|
360
360
|
}
|
|
361
|
-
|
|
362
|
-
getTriangleBuffer(_) {
|
|
361
|
+
getTriangleBuffer(_, bufferExtender) {
|
|
363
362
|
return this.triangleOrder
|
|
364
363
|
.map((vertexIndex) => {
|
|
365
364
|
const vertex = cloneBuf(this.vertices[vertexIndex]);
|
|
366
365
|
vec3.transformMat4(vertex, this.matrix, vertex);
|
|
367
|
-
return bufferGenerator.generate(vertex[0], vertex[1], vertex[2], this.params.vertexColors[vertexIndex]);
|
|
366
|
+
return bufferGenerator.generate(vertex[0], vertex[1], vertex[2], this.params.vertexColors[vertexIndex], vector2(), bufferExtender);
|
|
368
367
|
})
|
|
369
368
|
.flat();
|
|
370
369
|
}
|
package/dist/graphics.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="@webgpu/types" />
|
|
2
2
|
import { Camera } from './simulation.js';
|
|
3
|
-
import type { Vector2, Vector3, LerpFunc, VertexColorMap, ElementRotation, Mat4, AnySimulationElement } from './types.js';
|
|
3
|
+
import type { Vector2, Vector3, LerpFunc, VertexColorMap, ElementRotation, Mat4, AnySimulationElement, BufferExtenderInfo } from './types.js';
|
|
4
4
|
import { Vertex, Color } from './utils.js';
|
|
5
5
|
import { BlankGeometry, CircleGeometry, CubeGeometry, Geometry, Line2dGeometry, Line3dGeometry, PlaneGeometry, PolygonGeometry, Spline2dGeometry, SquareGeometry } from './geometry.js';
|
|
6
6
|
import { VertexCache } from './internalUtils.js';
|
|
@@ -30,7 +30,7 @@ export declare abstract class SimulationElement<T extends Vector2 | Vector3 = Ve
|
|
|
30
30
|
protected abstract updateMatrix(camera: Camera): void;
|
|
31
31
|
getVertexCount(): number;
|
|
32
32
|
protected defaultUpdateMatrix(camera: Camera): void;
|
|
33
|
-
getBuffer(camera: Camera): number[];
|
|
33
|
+
getBuffer(camera: Camera, bufferExtender?: BufferExtenderInfo): number[];
|
|
34
34
|
}
|
|
35
35
|
export declare abstract class SimulationElement3d extends SimulationElement {
|
|
36
36
|
protected pos: Vector3;
|
package/dist/graphics.js
CHANGED
|
@@ -73,19 +73,21 @@ export class SimulationElement {
|
|
|
73
73
|
}
|
|
74
74
|
this.geometry.updateMatrix(matrix);
|
|
75
75
|
}
|
|
76
|
-
getBuffer(camera) {
|
|
77
|
-
|
|
76
|
+
getBuffer(camera, bufferExtender) {
|
|
77
|
+
const shouldEvalExtender = bufferExtender?.shouldEvaluate?.();
|
|
78
|
+
const reEvalExtender = shouldEvalExtender === undefined ? true : shouldEvalExtender;
|
|
79
|
+
if (this.vertexCache.shouldUpdate() || camera.hasUpdated() || reEvalExtender) {
|
|
78
80
|
this.updateMatrix(camera);
|
|
79
81
|
this.geometry.recompute();
|
|
80
82
|
if (this.isInstanced) {
|
|
81
83
|
bufferGenerator.setInstancing(true);
|
|
82
84
|
}
|
|
83
|
-
let resBuffer
|
|
85
|
+
let resBuffer;
|
|
84
86
|
if (this.isWireframe()) {
|
|
85
|
-
resBuffer = this.geometry.getWireframeBuffer(this.color);
|
|
87
|
+
resBuffer = this.geometry.getWireframeBuffer(this.color, bufferExtender);
|
|
86
88
|
}
|
|
87
89
|
else {
|
|
88
|
-
resBuffer = this.geometry.getTriangleBuffer(this.color);
|
|
90
|
+
resBuffer = this.geometry.getTriangleBuffer(this.color, bufferExtender);
|
|
89
91
|
}
|
|
90
92
|
bufferGenerator.setInstancing(false);
|
|
91
93
|
this.vertexCache.setCache(resBuffer);
|
package/dist/internalUtils.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="@webgpu/types" />
|
|
2
|
-
import { AnySimulationElement, Mat4, Vector2, Vector3 } from './types.js';
|
|
2
|
+
import { AnySimulationElement, BufferExtenderInfo, Mat4, Vector2, Vector3, VertexParamInfo } from './types.js';
|
|
3
3
|
import { Color } from './utils.js';
|
|
4
4
|
export declare class VertexCache {
|
|
5
5
|
private vertices;
|
|
@@ -52,14 +52,14 @@ declare class BufferGenerator {
|
|
|
52
52
|
private instancing;
|
|
53
53
|
constructor();
|
|
54
54
|
setInstancing(state: boolean): void;
|
|
55
|
-
generate(x: number, y: number, z: number, color: Color, uv?: Vector2): number[];
|
|
55
|
+
generate(x: number, y: number, z: number, color: Color, uv?: Vector2, bufferExtender?: BufferExtenderInfo): number[];
|
|
56
56
|
}
|
|
57
57
|
export declare const bufferGenerator: BufferGenerator;
|
|
58
58
|
export declare function vector3ToPixelRatio(vec: Vector3): void;
|
|
59
59
|
export declare function vector2ToPixelRatio(vec: Vector2): void;
|
|
60
60
|
export declare function matrixFromRotation(rotation: Vector3): Mat4;
|
|
61
61
|
export declare function rotateMat4(mat: Mat4, rotation: Vector3): void;
|
|
62
|
-
export declare function createPipeline(device: GPUDevice, module: GPUShaderModule, bindGroupLayout: GPUBindGroupLayout, presentationFormat: GPUTextureFormat, entryPoint: string, topology: GPUPrimitiveTopology): GPURenderPipeline;
|
|
62
|
+
export declare function createPipeline(device: GPUDevice, module: GPUShaderModule, bindGroupLayout: GPUBindGroupLayout, presentationFormat: GPUTextureFormat, entryPoint: string, topology: GPUPrimitiveTopology, vertexParams?: VertexParamInfo[]): GPURenderPipeline;
|
|
63
63
|
export declare function triangulateWireFrameOrder(len: number): number[];
|
|
64
64
|
export declare function getTotalVertices(scene: SimSceneObjInfo[]): number;
|
|
65
65
|
export {};
|
package/dist/internalUtils.js
CHANGED
|
@@ -182,7 +182,15 @@ class BufferGenerator {
|
|
|
182
182
|
setInstancing(state) {
|
|
183
183
|
this.instancing = state;
|
|
184
184
|
}
|
|
185
|
-
generate(x, y, z, color, uv = vector2()) {
|
|
185
|
+
generate(x, y, z, color, uv = vector2(), bufferExtender) {
|
|
186
|
+
if (bufferExtender) {
|
|
187
|
+
const buf = bufferExtender.extender(x, y, z, color);
|
|
188
|
+
if (buf.length !== bufferExtender.size) {
|
|
189
|
+
logger.log_error(`Vertex size for shader group does not match buffer extension size (${buf.length} to expected ${bufferExtender.size})`);
|
|
190
|
+
return [];
|
|
191
|
+
}
|
|
192
|
+
return buf;
|
|
193
|
+
}
|
|
186
194
|
return [x, y, z, 1, ...color.toBuffer(), ...uv, this.instancing ? 1 : 0];
|
|
187
195
|
}
|
|
188
196
|
}
|
|
@@ -208,7 +216,47 @@ export function rotateMat4(mat, rotation) {
|
|
|
208
216
|
mat4.rotateY(mat, rotation[1], mat);
|
|
209
217
|
mat4.rotateX(mat, rotation[0], mat);
|
|
210
218
|
}
|
|
211
|
-
export function createPipeline(device, module, bindGroupLayout, presentationFormat, entryPoint, topology) {
|
|
219
|
+
export function createPipeline(device, module, bindGroupLayout, presentationFormat, entryPoint, topology, vertexParams) {
|
|
220
|
+
let params = [
|
|
221
|
+
{
|
|
222
|
+
// position
|
|
223
|
+
shaderLocation: 0,
|
|
224
|
+
offset: 0,
|
|
225
|
+
format: 'float32x4'
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
// color
|
|
229
|
+
shaderLocation: 1,
|
|
230
|
+
offset: colorOffset,
|
|
231
|
+
format: 'float32x4'
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
// size
|
|
235
|
+
shaderLocation: 2,
|
|
236
|
+
offset: uvOffset,
|
|
237
|
+
format: 'float32x2'
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
// drawing instances
|
|
241
|
+
shaderLocation: 3,
|
|
242
|
+
offset: drawingInstancesOffset,
|
|
243
|
+
format: 'float32'
|
|
244
|
+
}
|
|
245
|
+
];
|
|
246
|
+
let stride = vertexSize;
|
|
247
|
+
if (vertexParams) {
|
|
248
|
+
params = [];
|
|
249
|
+
let offset = 0;
|
|
250
|
+
for (let i = 0; i < vertexParams.length; i++) {
|
|
251
|
+
params.push({
|
|
252
|
+
shaderLocation: i,
|
|
253
|
+
offset,
|
|
254
|
+
format: vertexParams[i].format
|
|
255
|
+
});
|
|
256
|
+
offset += vertexParams[i].size;
|
|
257
|
+
}
|
|
258
|
+
stride = offset;
|
|
259
|
+
}
|
|
212
260
|
return device.createRenderPipeline({
|
|
213
261
|
layout: device.createPipelineLayout({
|
|
214
262
|
bindGroupLayouts: [bindGroupLayout]
|
|
@@ -218,33 +266,8 @@ export function createPipeline(device, module, bindGroupLayout, presentationForm
|
|
|
218
266
|
entryPoint,
|
|
219
267
|
buffers: [
|
|
220
268
|
{
|
|
221
|
-
arrayStride:
|
|
222
|
-
attributes:
|
|
223
|
-
{
|
|
224
|
-
// position
|
|
225
|
-
shaderLocation: 0,
|
|
226
|
-
offset: 0,
|
|
227
|
-
format: 'float32x4'
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
// color
|
|
231
|
-
shaderLocation: 1,
|
|
232
|
-
offset: colorOffset,
|
|
233
|
-
format: 'float32x4'
|
|
234
|
-
},
|
|
235
|
-
{
|
|
236
|
-
// size
|
|
237
|
-
shaderLocation: 2,
|
|
238
|
-
offset: uvOffset,
|
|
239
|
-
format: 'float32x2'
|
|
240
|
-
},
|
|
241
|
-
{
|
|
242
|
-
// drawing instances
|
|
243
|
-
shaderLocation: 3,
|
|
244
|
-
offset: drawingInstancesOffset,
|
|
245
|
-
format: 'float32'
|
|
246
|
-
}
|
|
247
|
-
]
|
|
269
|
+
arrayStride: stride,
|
|
270
|
+
attributes: params
|
|
248
271
|
}
|
|
249
272
|
]
|
|
250
273
|
},
|
package/dist/simulation.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="@webgpu/types" />
|
|
2
2
|
import { SimulationElement3d } from './graphics.js';
|
|
3
|
-
import type { Vector2, Vector3, LerpFunc, AnySimulationElement } from './types.js';
|
|
3
|
+
import type { Vector2, Vector3, LerpFunc, AnySimulationElement, BufferExtenderInfo, VertexParamInfo } from './types.js';
|
|
4
4
|
import { Color } from './utils.js';
|
|
5
5
|
import { BlankGeometry } from './geometry.js';
|
|
6
6
|
import { SimSceneObjInfo } from './internalUtils.js';
|
|
@@ -39,13 +39,13 @@ export declare class SceneCollection extends SimulationElement3d {
|
|
|
39
39
|
protected geometry: BlankGeometry;
|
|
40
40
|
private name;
|
|
41
41
|
private scene;
|
|
42
|
-
|
|
43
|
-
constructor(name
|
|
42
|
+
protected device: GPUDevice | null;
|
|
43
|
+
constructor(name?: string);
|
|
44
44
|
setWireframe(_: boolean): void;
|
|
45
|
-
getName(): string;
|
|
45
|
+
getName(): string | null;
|
|
46
46
|
getScene(): SimSceneObjInfo[];
|
|
47
47
|
setDevice(device: GPUDevice): void;
|
|
48
|
-
|
|
48
|
+
protected propagateDevice(device: GPUDevice): void;
|
|
49
49
|
getVertexCount(): number;
|
|
50
50
|
getSceneObjects(): AnySimulationElement[];
|
|
51
51
|
setSceneObjects(newScene: AnySimulationElement[]): void;
|
|
@@ -82,3 +82,17 @@ export declare class Camera {
|
|
|
82
82
|
getPos(): Vector3;
|
|
83
83
|
getAspectRatio(): number;
|
|
84
84
|
}
|
|
85
|
+
export declare class ShaderGroup extends SceneCollection {
|
|
86
|
+
protected geometry: BlankGeometry;
|
|
87
|
+
private code;
|
|
88
|
+
private module;
|
|
89
|
+
private pipeline;
|
|
90
|
+
private topology;
|
|
91
|
+
private bufferExtender;
|
|
92
|
+
private vertexParams;
|
|
93
|
+
constructor(shaderCode: string, topology: GPUPrimitiveTopology | undefined, vertexParams: VertexParamInfo[], bufferExtender: BufferExtenderInfo);
|
|
94
|
+
protected propagateDevice(device: GPUDevice): void;
|
|
95
|
+
getPipeline(): GPURenderPipeline | null;
|
|
96
|
+
protected updateMatrix(camera: Camera): void;
|
|
97
|
+
getBufferExtender(): BufferExtenderInfo;
|
|
98
|
+
}
|
package/dist/simulation.js
CHANGED
|
@@ -31,9 +31,15 @@ fn vertex_main_3d(
|
|
|
31
31
|
) -> VertexOutput {
|
|
32
32
|
var output : VertexOutput;
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
if (drawingInstance == 1) {
|
|
35
|
+
let transformedPos = instanceMatrices[instanceIdx] * position;
|
|
36
|
+
output.Position = uniforms.modelViewProjectionMatrix * transformedPos;
|
|
37
|
+
} else {
|
|
38
|
+
output.Position = uniforms.modelViewProjectionMatrix * position;
|
|
39
|
+
}
|
|
40
|
+
|
|
35
41
|
output.fragUV = uv;
|
|
36
|
-
output.fragPosition =
|
|
42
|
+
output.fragPosition = output.Position;
|
|
37
43
|
output.fragColor = color;
|
|
38
44
|
return output;
|
|
39
45
|
}
|
|
@@ -56,7 +62,7 @@ fn vertex_main_2d(
|
|
|
56
62
|
}
|
|
57
63
|
|
|
58
64
|
output.fragUV = uv;
|
|
59
|
-
output.fragPosition =
|
|
65
|
+
output.fragPosition = output.Position;
|
|
60
66
|
output.fragColor = color;
|
|
61
67
|
return output;
|
|
62
68
|
}
|
|
@@ -70,9 +76,7 @@ fn fragment_main(
|
|
|
70
76
|
return fragColor;
|
|
71
77
|
}
|
|
72
78
|
`;
|
|
73
|
-
const simjsFrameRateCss =
|
|
74
|
-
|
|
75
|
-
.simjs-frame-rate {
|
|
79
|
+
const simjsFrameRateCss = `.simjs-frame-rate {
|
|
76
80
|
position: absolute;
|
|
77
81
|
top: 0;
|
|
78
82
|
left: 0;
|
|
@@ -80,13 +84,14 @@ const simjsFrameRateCss = `@import url('https://fonts.googleapis.com/css2?family
|
|
|
80
84
|
color: white;
|
|
81
85
|
padding: 8px 12px;
|
|
82
86
|
z-index: 1000;
|
|
83
|
-
font-family:
|
|
87
|
+
font-family: monospace;
|
|
84
88
|
font-size: 16px;
|
|
85
89
|
}`;
|
|
86
90
|
class FrameRateView {
|
|
87
91
|
el;
|
|
88
92
|
fpsBuffer = [];
|
|
89
93
|
maxFpsBufferLength = 8;
|
|
94
|
+
prevAvg = 0;
|
|
90
95
|
constructor(show) {
|
|
91
96
|
this.el = document.createElement('div');
|
|
92
97
|
this.el.classList.add('simjs-frame-rate');
|
|
@@ -106,7 +111,10 @@ class FrameRateView {
|
|
|
106
111
|
this.fpsBuffer.push(num);
|
|
107
112
|
}
|
|
108
113
|
const fps = Math.round(this.fpsBuffer.reduce((acc, curr) => acc + curr, 0) / this.fpsBuffer.length);
|
|
109
|
-
this.
|
|
114
|
+
if (fps !== this.prevAvg) {
|
|
115
|
+
this.el.innerHTML = `${fps} FPS`;
|
|
116
|
+
this.prevAvg = fps;
|
|
117
|
+
}
|
|
110
118
|
}
|
|
111
119
|
}
|
|
112
120
|
export class Simulation {
|
|
@@ -394,7 +402,7 @@ export class Simulation {
|
|
|
394
402
|
};
|
|
395
403
|
requestAnimationFrame(frame);
|
|
396
404
|
}
|
|
397
|
-
renderScene(device, passEncoder, vertexBuffer, scene, startOffset, diff) {
|
|
405
|
+
renderScene(device, passEncoder, vertexBuffer, scene, startOffset, diff, shaderInfo) {
|
|
398
406
|
if (this.pipelines === null)
|
|
399
407
|
return 0;
|
|
400
408
|
let currentOffset = startOffset;
|
|
@@ -411,15 +419,26 @@ export class Simulation {
|
|
|
411
419
|
}
|
|
412
420
|
const obj = scene[i].getObj();
|
|
413
421
|
if (obj instanceof SceneCollection) {
|
|
414
|
-
|
|
422
|
+
let shaderInfo = undefined;
|
|
423
|
+
if (obj instanceof ShaderGroup) {
|
|
424
|
+
const pipeline = obj.getPipeline();
|
|
425
|
+
if (pipeline !== null) {
|
|
426
|
+
shaderInfo = { pipeline, bufferExtender: obj.getBufferExtender() };
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
currentOffset += this.renderScene(device, passEncoder, vertexBuffer, obj.getScene(), currentOffset, diff, shaderInfo || undefined);
|
|
415
430
|
continue;
|
|
416
431
|
}
|
|
417
|
-
const buffer = new Float32Array(obj.getBuffer(this.camera));
|
|
418
|
-
const
|
|
432
|
+
const buffer = new Float32Array(obj.getBuffer(this.camera, shaderInfo?.bufferExtender));
|
|
433
|
+
const bufLen = shaderInfo?.bufferExtender?.size || BUF_LEN;
|
|
434
|
+
const vertexCount = buffer.length / bufLen;
|
|
419
435
|
device.queue.writeBuffer(vertexBuffer, currentOffset, buffer);
|
|
420
436
|
vertexBuffer.unmap();
|
|
421
437
|
const is3d = Boolean(obj.is3d);
|
|
422
|
-
if (
|
|
438
|
+
if (shaderInfo) {
|
|
439
|
+
passEncoder.setPipeline(shaderInfo.pipeline);
|
|
440
|
+
}
|
|
441
|
+
else if (obj.isWireframe()) {
|
|
423
442
|
if (is3d) {
|
|
424
443
|
passEncoder.setPipeline(this.pipelines.lineStrip3d);
|
|
425
444
|
}
|
|
@@ -500,7 +519,7 @@ export class SceneCollection extends SimulationElement3d {
|
|
|
500
519
|
constructor(name) {
|
|
501
520
|
super(vector3());
|
|
502
521
|
this.wireframe = false;
|
|
503
|
-
this.name = name;
|
|
522
|
+
this.name = name || null;
|
|
504
523
|
this.scene = [];
|
|
505
524
|
this.geometry = new BlankGeometry();
|
|
506
525
|
}
|
|
@@ -564,9 +583,11 @@ export class SceneCollection extends SimulationElement3d {
|
|
|
564
583
|
getSceneBuffer(camera) {
|
|
565
584
|
return this.scene.map((item) => item.getObj().getBuffer(camera)).flat();
|
|
566
585
|
}
|
|
586
|
+
// TODO - improve
|
|
567
587
|
getWireframe(camera) {
|
|
568
588
|
return this.getSceneBuffer(camera);
|
|
569
589
|
}
|
|
590
|
+
// TODO - improve
|
|
570
591
|
getTriangles(camera) {
|
|
571
592
|
return this.getSceneBuffer(camera);
|
|
572
593
|
}
|
|
@@ -661,3 +682,65 @@ export class Camera {
|
|
|
661
682
|
return this.aspectRatio;
|
|
662
683
|
}
|
|
663
684
|
}
|
|
685
|
+
export class ShaderGroup extends SceneCollection {
|
|
686
|
+
geometry;
|
|
687
|
+
code;
|
|
688
|
+
module;
|
|
689
|
+
pipeline;
|
|
690
|
+
topology;
|
|
691
|
+
bufferExtender;
|
|
692
|
+
vertexParams;
|
|
693
|
+
constructor(shaderCode, topology = 'triangle-list', vertexParams, bufferExtender) {
|
|
694
|
+
super();
|
|
695
|
+
const defaultCode = `
|
|
696
|
+
struct Uniforms {
|
|
697
|
+
modelViewProjectionMatrix : mat4x4<f32>,
|
|
698
|
+
orthoProjectionMatrix : mat4x4<f32>
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
@group(0) @binding(0) var<uniform> uniforms : Uniforms;
|
|
702
|
+
|
|
703
|
+
@group(0) @binding(1) var<storage, read> instanceMatrices : array<mat4x4f>;
|
|
704
|
+
`;
|
|
705
|
+
this.geometry = new BlankGeometry();
|
|
706
|
+
this.code = defaultCode + shaderCode;
|
|
707
|
+
this.module = null;
|
|
708
|
+
this.pipeline = null;
|
|
709
|
+
this.topology = topology;
|
|
710
|
+
this.bufferExtender = bufferExtender;
|
|
711
|
+
this.vertexParams = vertexParams;
|
|
712
|
+
}
|
|
713
|
+
propagateDevice(device) {
|
|
714
|
+
super.propagateDevice(device);
|
|
715
|
+
this.module = device.createShaderModule({ code: this.code });
|
|
716
|
+
const bindGroupLayout = device.createBindGroupLayout({
|
|
717
|
+
entries: [
|
|
718
|
+
{
|
|
719
|
+
binding: 0,
|
|
720
|
+
visibility: GPUShaderStage.VERTEX,
|
|
721
|
+
buffer: {
|
|
722
|
+
type: 'uniform'
|
|
723
|
+
}
|
|
724
|
+
},
|
|
725
|
+
{
|
|
726
|
+
binding: 1,
|
|
727
|
+
visibility: GPUShaderStage.VERTEX,
|
|
728
|
+
buffer: {
|
|
729
|
+
type: 'read-only-storage'
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
]
|
|
733
|
+
});
|
|
734
|
+
const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
|
|
735
|
+
this.pipeline = createPipeline(device, this.module, bindGroupLayout, presentationFormat, 'vertex_main_2d', this.topology, this.vertexParams);
|
|
736
|
+
}
|
|
737
|
+
getPipeline() {
|
|
738
|
+
return this.pipeline;
|
|
739
|
+
}
|
|
740
|
+
updateMatrix(camera) {
|
|
741
|
+
this.defaultUpdateMatrix(camera);
|
|
742
|
+
}
|
|
743
|
+
getBufferExtender() {
|
|
744
|
+
return this.bufferExtender;
|
|
745
|
+
}
|
|
746
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -78,3 +78,20 @@ export type RenderInfo = {
|
|
|
78
78
|
bindGroupLayout: GPUBindGroupLayout;
|
|
79
79
|
vertexBuffer: GPUBuffer | null;
|
|
80
80
|
};
|
|
81
|
+
export type BindingInfo = {
|
|
82
|
+
visibility: GPUBindGroupLayoutEntry['visibility'];
|
|
83
|
+
buffer: GPUBindGroupLayoutEntry['buffer'];
|
|
84
|
+
};
|
|
85
|
+
export type BufferExtenderInfo = {
|
|
86
|
+
size: number;
|
|
87
|
+
extender: (x: number, y: number, z: number, color: Color) => number[];
|
|
88
|
+
shouldEvaluate?: () => boolean;
|
|
89
|
+
};
|
|
90
|
+
export type ShaderInfo = {
|
|
91
|
+
pipeline: GPURenderPipeline;
|
|
92
|
+
bufferExtender: BufferExtenderInfo;
|
|
93
|
+
};
|
|
94
|
+
export type VertexParamInfo = {
|
|
95
|
+
format: GPUVertexFormat;
|
|
96
|
+
size: number;
|
|
97
|
+
};
|