simulationjsv2 0.7.2 → 0.7.4
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 +3 -0
- package/dist/buffers.d.ts +11 -0
- package/dist/buffers.js +36 -0
- package/dist/graphics.d.ts +5 -3
- package/dist/graphics.js +56 -35
- package/dist/internalUtils.d.ts +21 -1
- package/dist/internalUtils.js +73 -3
- package/dist/materials.d.ts +3 -0
- package/dist/materials.js +3 -0
- package/dist/pipelines.d.ts +1 -0
- package/dist/pipelines.js +1 -0
- package/dist/shaders.d.ts +11 -0
- package/dist/shaders.js +89 -0
- package/dist/simulation.d.ts +2 -0
- package/dist/simulation.js +64 -145
- package/dist/types.d.ts +3 -2
- package/package.json +1 -1
package/TODO.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# TODO
|
|
2
2
|
|
|
3
|
+
- [ ] Make materials
|
|
4
|
+
- [ ] Move shader group to material
|
|
3
5
|
- [ ] Fix transparency
|
|
6
|
+
- [x] Change absolute pos function to pos function, and pos function to relative pos
|
|
4
7
|
- [x] Update `updateModelMatrix2d`
|
|
5
8
|
- [x] Trace line element (wireframe strip for tracing paths)
|
|
6
9
|
- [x] Test new transform things on 3d stuff
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/// <reference types="@webgpu/types" />
|
|
2
|
+
export declare class MemoBuffer {
|
|
3
|
+
private buffer;
|
|
4
|
+
private bufferSize;
|
|
5
|
+
private usage;
|
|
6
|
+
constructor(usage: GPUBufferDescriptor['usage'], size: number);
|
|
7
|
+
private allocBuffer;
|
|
8
|
+
getBuffer(): GPUBuffer;
|
|
9
|
+
setSize(size: number): void;
|
|
10
|
+
destroy(): void;
|
|
11
|
+
}
|
package/dist/buffers.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { globalInfo } from './internalUtils.js';
|
|
2
|
+
export class MemoBuffer {
|
|
3
|
+
buffer;
|
|
4
|
+
bufferSize;
|
|
5
|
+
usage;
|
|
6
|
+
constructor(usage, size) {
|
|
7
|
+
this.usage = usage;
|
|
8
|
+
this.bufferSize = size;
|
|
9
|
+
this.buffer = null;
|
|
10
|
+
}
|
|
11
|
+
allocBuffer() {
|
|
12
|
+
const device = globalInfo.getDevice();
|
|
13
|
+
if (!device)
|
|
14
|
+
return;
|
|
15
|
+
this.buffer = device.createBuffer({
|
|
16
|
+
size: this.bufferSize,
|
|
17
|
+
usage: this.usage
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
getBuffer() {
|
|
21
|
+
if (!this.buffer)
|
|
22
|
+
this.allocBuffer();
|
|
23
|
+
return this.buffer;
|
|
24
|
+
}
|
|
25
|
+
setSize(size) {
|
|
26
|
+
if (!this.buffer)
|
|
27
|
+
this.allocBuffer();
|
|
28
|
+
if (size > this.bufferSize) {
|
|
29
|
+
this.bufferSize = size;
|
|
30
|
+
this.allocBuffer();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
destroy() {
|
|
34
|
+
this.buffer?.destroy();
|
|
35
|
+
}
|
|
36
|
+
}
|
package/dist/graphics.d.ts
CHANGED
|
@@ -35,6 +35,7 @@ export declare abstract class SimulationElement3d {
|
|
|
35
35
|
setRotationOffset(offset: Vector3): void;
|
|
36
36
|
resetCenterOffset(): void;
|
|
37
37
|
getModelMatrix(): Mat4;
|
|
38
|
+
isTransparent(): boolean;
|
|
38
39
|
getUniformBuffer(mat: Mat4): GPUBuffer;
|
|
39
40
|
protected mirrorParentTransforms3d(mat: Mat4): void;
|
|
40
41
|
protected updateModelMatrix3d(): void;
|
|
@@ -44,8 +45,8 @@ export declare abstract class SimulationElement3d {
|
|
|
44
45
|
setWireframe(wireframe: boolean): void;
|
|
45
46
|
isWireframe(): boolean;
|
|
46
47
|
getColor(): Color;
|
|
48
|
+
getRelativePos(): Vector3;
|
|
47
49
|
getPos(): Vector3;
|
|
48
|
-
getAbsolutePos(): Vector3;
|
|
49
50
|
getRotation(): Vector3;
|
|
50
51
|
getCenterOffset(): Vector3;
|
|
51
52
|
fill(newColor: Color, t?: number, f?: LerpFunc): Promise<void>;
|
|
@@ -183,6 +184,7 @@ export declare class Spline2d extends SimulationElement2d {
|
|
|
183
184
|
private interpolateLimit;
|
|
184
185
|
private length;
|
|
185
186
|
constructor(pos: Vertex, points: SplinePoint2d[], thickness?: number, detail?: number);
|
|
187
|
+
isTransparent(): boolean;
|
|
186
188
|
private estimateLength;
|
|
187
189
|
getLength(): number;
|
|
188
190
|
setInterpolateStart(start: number, t?: number, f?: LerpFunc): Promise<void>;
|
|
@@ -200,11 +202,11 @@ export declare class Instance<T extends AnySimulationElement> extends Simulation
|
|
|
200
202
|
private matrixBuffer;
|
|
201
203
|
private baseMat;
|
|
202
204
|
private maxInstances;
|
|
205
|
+
private hasMapped;
|
|
203
206
|
isInstance: boolean;
|
|
204
207
|
constructor(obj: T, numInstances: number);
|
|
205
|
-
setNumInstances(numInstances: number): void;
|
|
208
|
+
setNumInstances(numInstances: number, forceResizeBuffer?: boolean): void;
|
|
206
209
|
setInstance(instance: number, transformation: Mat4): void;
|
|
207
|
-
private allocBuffer;
|
|
208
210
|
private mapBuffer;
|
|
209
211
|
getInstances(): Mat4[];
|
|
210
212
|
getNumInstances(): number;
|
package/dist/graphics.js
CHANGED
|
@@ -3,6 +3,7 @@ import { Vertex, cloneBuf, color, colorFromVector4, vector2, vector3, vertex, Co
|
|
|
3
3
|
import { BlankGeometry, CircleGeometry, CubeGeometry, Line2dGeometry, Line3dGeometry, PlaneGeometry, PolygonGeometry, Spline2dGeometry, SquareGeometry, TraceLines2dGeometry as TraceLinesGeometry } from './geometry.js';
|
|
4
4
|
import { SimSceneObjInfo, VertexCache, bufferGenerator, globalInfo, internalTransitionValues, logger, posTo2dScreen, vector3ToPixelRatio } from './internalUtils.js';
|
|
5
5
|
import { mat4ByteLength, modelProjMatOffset } from './constants.js';
|
|
6
|
+
import { MemoBuffer } from './buffers.js';
|
|
6
7
|
export class SimulationElement3d {
|
|
7
8
|
children;
|
|
8
9
|
uniformBuffer;
|
|
@@ -23,6 +24,7 @@ export class SimulationElement3d {
|
|
|
23
24
|
* @param pos - Expected to be adjusted to devicePixelRatio before reaching constructor
|
|
24
25
|
*/
|
|
25
26
|
constructor(pos, rotation, color = new Color()) {
|
|
27
|
+
const uniformBufferSize = mat4ByteLength * 2 + 4 * 2 + 8; // 4x4 matrix * 2 + vec2<f32> + 8 bc 144 is cool
|
|
26
28
|
this.pos = pos;
|
|
27
29
|
this.centerOffset = vector3();
|
|
28
30
|
// TODO test this
|
|
@@ -31,7 +33,7 @@ export class SimulationElement3d {
|
|
|
31
33
|
this.vertexCache = new VertexCache();
|
|
32
34
|
this.wireframe = false;
|
|
33
35
|
this.rotation = cloneBuf(rotation);
|
|
34
|
-
this.uniformBuffer =
|
|
36
|
+
this.uniformBuffer = new MemoBuffer(GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, uniformBufferSize);
|
|
35
37
|
this.children = [];
|
|
36
38
|
this.modelMatrix = matrix4();
|
|
37
39
|
this.parent = null;
|
|
@@ -78,23 +80,20 @@ export class SimulationElement3d {
|
|
|
78
80
|
this.updateModelMatrix3d();
|
|
79
81
|
return this.modelMatrix;
|
|
80
82
|
}
|
|
83
|
+
isTransparent() {
|
|
84
|
+
return this.color.a < 1;
|
|
85
|
+
}
|
|
81
86
|
getUniformBuffer(mat) {
|
|
82
87
|
const device = globalInfo.errorGetDevice();
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
size: uniformBufferSize,
|
|
87
|
-
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
device.queue.writeBuffer(this.uniformBuffer, modelProjMatOffset, mat);
|
|
91
|
-
return this.uniformBuffer;
|
|
88
|
+
const buffer = this.uniformBuffer.getBuffer();
|
|
89
|
+
device.queue.writeBuffer(buffer, modelProjMatOffset, mat);
|
|
90
|
+
return buffer;
|
|
92
91
|
}
|
|
93
92
|
mirrorParentTransforms3d(mat) {
|
|
94
93
|
if (!this.parent)
|
|
95
94
|
return;
|
|
96
95
|
this.parent.mirrorParentTransforms3d(mat);
|
|
97
|
-
mat4.translate(mat, this.parent.
|
|
96
|
+
mat4.translate(mat, this.parent.getRelativePos(), mat);
|
|
98
97
|
const parentRot = this.parent.getRotation();
|
|
99
98
|
mat4.rotateZ(mat, parentRot[2], mat);
|
|
100
99
|
mat4.rotateY(mat, parentRot[1], mat);
|
|
@@ -150,10 +149,10 @@ export class SimulationElement3d {
|
|
|
150
149
|
getColor() {
|
|
151
150
|
return this.color;
|
|
152
151
|
}
|
|
153
|
-
|
|
152
|
+
getRelativePos() {
|
|
154
153
|
return this.pos;
|
|
155
154
|
}
|
|
156
|
-
|
|
155
|
+
getPos() {
|
|
157
156
|
const vec = vector3();
|
|
158
157
|
this.updateModelMatrix3d();
|
|
159
158
|
mat4.getTranslation(this.modelMatrix, vec);
|
|
@@ -884,6 +883,17 @@ export class Spline2d extends SimulationElement2d {
|
|
|
884
883
|
this.geometry = new Spline2dGeometry(points, this.getColor(), this.thickness, this.detail);
|
|
885
884
|
this.estimateLength();
|
|
886
885
|
}
|
|
886
|
+
isTransparent() {
|
|
887
|
+
const curves = this.geometry.getCurves();
|
|
888
|
+
for (let i = 0; i < curves.length; i++) {
|
|
889
|
+
const colors = curves[i].getColors();
|
|
890
|
+
for (let j = 0; j < colors.length; j++) {
|
|
891
|
+
if (colors[j]?.a ?? 0 < 1)
|
|
892
|
+
return true;
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
return false;
|
|
896
|
+
}
|
|
887
897
|
estimateLength() {
|
|
888
898
|
this.length = 0;
|
|
889
899
|
const curves = this.geometry.getCurves();
|
|
@@ -927,7 +937,7 @@ export class Spline2d extends SimulationElement2d {
|
|
|
927
937
|
const clonePoint = newPoint.clone();
|
|
928
938
|
const start = clonePoint.getStart()?.getPos() || vector3();
|
|
929
939
|
const end = clonePoint.getEnd().getPos();
|
|
930
|
-
const pos = this.
|
|
940
|
+
const pos = this.getRelativePos();
|
|
931
941
|
vec3.sub(start, pos, start);
|
|
932
942
|
vec3.sub(end, pos, end);
|
|
933
943
|
this.geometry.updatePoint(pointIndex, clonePoint);
|
|
@@ -979,29 +989,31 @@ export class Instance extends SimulationElement3d {
|
|
|
979
989
|
matrixBuffer;
|
|
980
990
|
baseMat;
|
|
981
991
|
maxInstances;
|
|
992
|
+
hasMapped;
|
|
982
993
|
isInstance = true;
|
|
983
994
|
constructor(obj, numInstances) {
|
|
984
995
|
super(vector3(), vector3());
|
|
985
996
|
// 32 matrices
|
|
986
997
|
this.maxInstances = 32;
|
|
987
|
-
this.matrixBuffer =
|
|
998
|
+
this.matrixBuffer = new MemoBuffer(GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST, this.maxInstances * mat4ByteLength);
|
|
988
999
|
obj.isInstanced = true;
|
|
989
1000
|
this.obj = obj;
|
|
990
1001
|
this.instanceMatrix = [];
|
|
991
1002
|
this.is3d = obj.is3d;
|
|
992
1003
|
this.geometry = new BlankGeometry();
|
|
1004
|
+
this.hasMapped = false;
|
|
993
1005
|
this.baseMat = matrix4();
|
|
994
1006
|
for (let i = 0; i < numInstances; i++) {
|
|
995
1007
|
const clone = cloneBuf(this.baseMat);
|
|
996
1008
|
this.instanceMatrix.push(clone);
|
|
997
1009
|
}
|
|
998
1010
|
}
|
|
999
|
-
setNumInstances(numInstances) {
|
|
1011
|
+
setNumInstances(numInstances, forceResizeBuffer = false) {
|
|
1000
1012
|
if (numInstances < 0)
|
|
1001
1013
|
throw logger.error('Num instances is less than 0');
|
|
1002
|
-
if (numInstances > this.maxInstances) {
|
|
1014
|
+
if (numInstances > this.maxInstances || forceResizeBuffer) {
|
|
1003
1015
|
this.maxInstances = numInstances;
|
|
1004
|
-
this.
|
|
1016
|
+
this.matrixBuffer.setSize(numInstances * mat4ByteLength);
|
|
1005
1017
|
}
|
|
1006
1018
|
const oldLen = this.instanceMatrix.length;
|
|
1007
1019
|
if (numInstances < oldLen) {
|
|
@@ -1024,29 +1036,36 @@ export class Instance extends SimulationElement3d {
|
|
|
1024
1036
|
if (instance >= this.instanceMatrix.length || instance < 0)
|
|
1025
1037
|
return;
|
|
1026
1038
|
this.instanceMatrix[instance] = transformation;
|
|
1027
|
-
}
|
|
1028
|
-
allocBuffer(size) {
|
|
1029
1039
|
const device = globalInfo.getDevice();
|
|
1030
1040
|
if (!device)
|
|
1031
1041
|
return;
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
}
|
|
1042
|
+
// this.allocBuffer(size);
|
|
1043
|
+
const gpuBuffer = this.matrixBuffer.getBuffer();
|
|
1044
|
+
const buf = new Float32Array(transformation);
|
|
1045
|
+
device.queue.writeBuffer(gpuBuffer, instance * mat4ByteLength, buf.buffer, buf.byteOffset, buf.byteLength);
|
|
1046
|
+
gpuBuffer.unmap();
|
|
1047
|
+
}
|
|
1048
|
+
// private allocBuffer(size: number) {
|
|
1049
|
+
// const device = globalInfo.getDevice();
|
|
1050
|
+
// if (!device) return;
|
|
1051
|
+
// const byteSize = size * mat4ByteLength;
|
|
1052
|
+
// this.matrixBuffer = device.createBuffer({
|
|
1053
|
+
// size: byteSize,
|
|
1054
|
+
// usage:
|
|
1055
|
+
// });
|
|
1056
|
+
// }
|
|
1038
1057
|
mapBuffer() {
|
|
1039
1058
|
const device = globalInfo.getDevice();
|
|
1040
1059
|
if (!device)
|
|
1041
1060
|
return;
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
}
|
|
1061
|
+
const minSize = this.maxInstances * mat4ByteLength;
|
|
1062
|
+
const size = Math.max(minSize, this.instanceMatrix.length);
|
|
1063
|
+
this.matrixBuffer.setSize(size);
|
|
1064
|
+
const gpuBuffer = this.matrixBuffer.getBuffer();
|
|
1047
1065
|
const buf = new Float32Array(this.instanceMatrix.map((mat) => [...mat]).flat());
|
|
1048
|
-
device.queue.writeBuffer(
|
|
1049
|
-
|
|
1066
|
+
device.queue.writeBuffer(gpuBuffer, 0, buf.buffer, buf.byteOffset, buf.byteLength);
|
|
1067
|
+
gpuBuffer.unmap();
|
|
1068
|
+
this.hasMapped = true;
|
|
1050
1069
|
}
|
|
1051
1070
|
getInstances() {
|
|
1052
1071
|
return this.instanceMatrix;
|
|
@@ -1055,8 +1074,10 @@ export class Instance extends SimulationElement3d {
|
|
|
1055
1074
|
return this.instanceMatrix.length;
|
|
1056
1075
|
}
|
|
1057
1076
|
getMatrixBuffer() {
|
|
1058
|
-
this.
|
|
1059
|
-
|
|
1077
|
+
if (!this.hasMapped) {
|
|
1078
|
+
this.mapBuffer();
|
|
1079
|
+
}
|
|
1080
|
+
return this.matrixBuffer.getBuffer();
|
|
1060
1081
|
}
|
|
1061
1082
|
getVertexCount() {
|
|
1062
1083
|
return this.obj.getVertexCount();
|
package/dist/internalUtils.d.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { VertexParamGeneratorInfo, Mat4, Vector2, Vector3, VertexParamInfo } from './types.js';
|
|
3
3
|
import { Color } from './utils.js';
|
|
4
4
|
import { SimulationElement3d } from './graphics.js';
|
|
5
|
+
import { Shader } from './shaders.js';
|
|
5
6
|
export declare class VertexCache {
|
|
6
7
|
private vertices;
|
|
7
8
|
private hasUpdated;
|
|
@@ -20,6 +21,15 @@ export declare class GlobalInfo {
|
|
|
20
21
|
getDevice(): GPUDevice | null;
|
|
21
22
|
}
|
|
22
23
|
export declare const globalInfo: GlobalInfo;
|
|
24
|
+
export declare class CachedArray<T> {
|
|
25
|
+
private length;
|
|
26
|
+
private data;
|
|
27
|
+
constructor();
|
|
28
|
+
add(index: T): void;
|
|
29
|
+
reset(): void;
|
|
30
|
+
clearCache(): void;
|
|
31
|
+
toArray(): T[];
|
|
32
|
+
}
|
|
23
33
|
export declare const updateProjectionMatrix: (mat: Mat4, aspectRatio: number, zNear?: number, zFar?: number) => any;
|
|
24
34
|
export declare const updateWorldProjectionMatrix: (worldProjMat: Mat4, projMat: Mat4) => void;
|
|
25
35
|
export declare const updateOrthoProjectionMatrix: (mat: Mat4, screenSize: [number, number]) => Float32Array;
|
|
@@ -65,11 +75,21 @@ declare class BufferGenerator {
|
|
|
65
75
|
export declare const bufferGenerator: BufferGenerator;
|
|
66
76
|
export declare function vector3ToPixelRatio(vec: Vector3): void;
|
|
67
77
|
export declare function vector2ToPixelRatio(vec: Vector2): void;
|
|
68
|
-
export declare function createPipeline(device: GPUDevice, module: GPUShaderModule, bindGroupLayouts: GPUBindGroupLayout[], presentationFormat: GPUTextureFormat, topology: GPUPrimitiveTopology, vertexParams?: VertexParamInfo[]): GPURenderPipeline;
|
|
78
|
+
export declare function createPipeline(device: GPUDevice, module: GPUShaderModule, bindGroupLayouts: GPUBindGroupLayout[], presentationFormat: GPUTextureFormat, topology: GPUPrimitiveTopology, transparent: boolean, vertexParams?: VertexParamInfo[]): GPURenderPipeline;
|
|
69
79
|
export declare function triangulateWireFrameOrder(len: number): number[];
|
|
70
80
|
export declare function getTotalVertices(scene: SimSceneObjInfo[]): number;
|
|
71
81
|
export declare function vectorCompAngle(a: number, b: number): number;
|
|
72
82
|
export declare function angleBetween(pos1: Vector3, pos2: Vector3): Vector3;
|
|
73
83
|
export declare function internalTransitionValues(onFrame: (deltaT: number, t: number, total: number) => void, adjustment: () => void, transitionLength: number, func?: (n: number) => number): Promise<void>;
|
|
74
84
|
export declare function posTo2dScreen(pos: Vector3): Vector3;
|
|
85
|
+
export declare function createShaderModule(shader: Shader): GPUShaderModule;
|
|
86
|
+
export declare function createDefaultPipelines(shader: Shader): {
|
|
87
|
+
triangleList: GPURenderPipeline;
|
|
88
|
+
triangleStrip: GPURenderPipeline;
|
|
89
|
+
lineStrip: GPURenderPipeline;
|
|
90
|
+
triangleListTransparent: GPURenderPipeline;
|
|
91
|
+
triangleStripTransparent: GPURenderPipeline;
|
|
92
|
+
lineStripTransparent: GPURenderPipeline;
|
|
93
|
+
};
|
|
94
|
+
export default function createUniformBindGroup(shader: Shader, buffers: GPUBuffer[]): GPUBindGroup;
|
|
75
95
|
export {};
|
package/dist/internalUtils.js
CHANGED
|
@@ -44,6 +44,33 @@ export class GlobalInfo {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
export const globalInfo = new GlobalInfo();
|
|
47
|
+
export class CachedArray {
|
|
48
|
+
length;
|
|
49
|
+
data;
|
|
50
|
+
constructor() {
|
|
51
|
+
this.length = 0;
|
|
52
|
+
this.data = [];
|
|
53
|
+
}
|
|
54
|
+
add(index) {
|
|
55
|
+
if (this.length < this.data.length) {
|
|
56
|
+
this.data[this.length - 1] = index;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
this.data.push(index);
|
|
60
|
+
}
|
|
61
|
+
this.length++;
|
|
62
|
+
}
|
|
63
|
+
reset() {
|
|
64
|
+
this.length = 0;
|
|
65
|
+
}
|
|
66
|
+
clearCache() {
|
|
67
|
+
this.reset();
|
|
68
|
+
this.data = [];
|
|
69
|
+
}
|
|
70
|
+
toArray() {
|
|
71
|
+
return this.data.slice(0, this.length);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
47
74
|
export const updateProjectionMatrix = (mat, aspectRatio, zNear = 1, zFar = 500) => {
|
|
48
75
|
const fov = Math.PI / 4;
|
|
49
76
|
return mat4.perspective(fov, aspectRatio, zNear, zFar, mat);
|
|
@@ -219,7 +246,7 @@ export function vector2ToPixelRatio(vec) {
|
|
|
219
246
|
vec[0] *= devicePixelRatio;
|
|
220
247
|
vec[1] *= devicePixelRatio;
|
|
221
248
|
}
|
|
222
|
-
export function createPipeline(device, module, bindGroupLayouts, presentationFormat, topology, vertexParams) {
|
|
249
|
+
export function createPipeline(device, module, bindGroupLayouts, presentationFormat, topology, transparent, vertexParams) {
|
|
223
250
|
let params = [
|
|
224
251
|
{
|
|
225
252
|
// position
|
|
@@ -279,7 +306,17 @@ export function createPipeline(device, module, bindGroupLayouts, presentationFor
|
|
|
279
306
|
entryPoint: 'fragment_main',
|
|
280
307
|
targets: [
|
|
281
308
|
{
|
|
282
|
-
format: presentationFormat
|
|
309
|
+
format: presentationFormat,
|
|
310
|
+
blend: {
|
|
311
|
+
color: {
|
|
312
|
+
srcFactor: 'src-alpha',
|
|
313
|
+
dstFactor: 'one-minus-src-alpha'
|
|
314
|
+
},
|
|
315
|
+
alpha: {
|
|
316
|
+
srcFactor: 'src-alpha',
|
|
317
|
+
dstFactor: 'one-minus-src-alpha'
|
|
318
|
+
}
|
|
319
|
+
}
|
|
283
320
|
}
|
|
284
321
|
]
|
|
285
322
|
},
|
|
@@ -290,7 +327,7 @@ export function createPipeline(device, module, bindGroupLayouts, presentationFor
|
|
|
290
327
|
count: 4
|
|
291
328
|
},
|
|
292
329
|
depthStencil: {
|
|
293
|
-
depthWriteEnabled:
|
|
330
|
+
depthWriteEnabled: !transparent,
|
|
294
331
|
depthCompare: 'less',
|
|
295
332
|
format: 'depth24plus'
|
|
296
333
|
}
|
|
@@ -346,3 +383,36 @@ export function posTo2dScreen(pos) {
|
|
|
346
383
|
newPos[1] = camera.getScreenSize()[1] + newPos[1];
|
|
347
384
|
return newPos;
|
|
348
385
|
}
|
|
386
|
+
export function createShaderModule(shader) {
|
|
387
|
+
const device = globalInfo.errorGetDevice();
|
|
388
|
+
return device.createShaderModule({
|
|
389
|
+
code: shader.getCode()
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
export function createDefaultPipelines(shader) {
|
|
393
|
+
const device = globalInfo.errorGetDevice();
|
|
394
|
+
const bindGroupLayout = device.createBindGroupLayout(shader.getBindGroupLayoutDescriptor());
|
|
395
|
+
const shaderModule = createShaderModule(shader);
|
|
396
|
+
const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
|
|
397
|
+
return {
|
|
398
|
+
triangleList: createPipeline(device, shaderModule, [bindGroupLayout], presentationFormat, 'triangle-list', false),
|
|
399
|
+
triangleStrip: createPipeline(device, shaderModule, [bindGroupLayout], presentationFormat, 'triangle-strip', false),
|
|
400
|
+
lineStrip: createPipeline(device, shaderModule, [bindGroupLayout], presentationFormat, 'line-strip', false),
|
|
401
|
+
triangleListTransparent: createPipeline(device, shaderModule, [bindGroupLayout], presentationFormat, 'triangle-list', true),
|
|
402
|
+
triangleStripTransparent: createPipeline(device, shaderModule, [bindGroupLayout], presentationFormat, 'triangle-strip', true),
|
|
403
|
+
lineStripTransparent: createPipeline(device, shaderModule, [bindGroupLayout], presentationFormat, 'line-strip', true)
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
export default function createUniformBindGroup(shader, buffers) {
|
|
407
|
+
const device = globalInfo.errorGetDevice();
|
|
408
|
+
const bindGroupLayout = shader.getBindGroupLayout();
|
|
409
|
+
return device.createBindGroup({
|
|
410
|
+
layout: bindGroupLayout,
|
|
411
|
+
entries: buffers.map((buffer, index) => ({
|
|
412
|
+
binding: index,
|
|
413
|
+
resource: {
|
|
414
|
+
buffer
|
|
415
|
+
}
|
|
416
|
+
}))
|
|
417
|
+
});
|
|
418
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/// <reference types="@webgpu/types" />
|
|
2
|
+
export declare class Shader {
|
|
3
|
+
private bindGroupLayoutDescriptor;
|
|
4
|
+
private bindGroupLayout;
|
|
5
|
+
private code;
|
|
6
|
+
constructor(code: string, descriptor: GPUBindGroupLayoutDescriptor);
|
|
7
|
+
getCode(): string;
|
|
8
|
+
getBindGroupLayout(): GPUBindGroupLayout;
|
|
9
|
+
getBindGroupLayoutDescriptor(): GPUBindGroupLayoutDescriptor;
|
|
10
|
+
}
|
|
11
|
+
export declare const defaultShader: Shader;
|
package/dist/shaders.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { globalInfo } from './internalUtils.js';
|
|
2
|
+
export class Shader {
|
|
3
|
+
bindGroupLayoutDescriptor;
|
|
4
|
+
bindGroupLayout;
|
|
5
|
+
code;
|
|
6
|
+
constructor(code, descriptor) {
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.bindGroupLayoutDescriptor = descriptor;
|
|
9
|
+
this.bindGroupLayout = null;
|
|
10
|
+
}
|
|
11
|
+
getCode() {
|
|
12
|
+
return this.code;
|
|
13
|
+
}
|
|
14
|
+
getBindGroupLayout() {
|
|
15
|
+
const device = globalInfo.errorGetDevice();
|
|
16
|
+
if (!this.bindGroupLayout) {
|
|
17
|
+
this.bindGroupLayout = device.createBindGroupLayout(this.bindGroupLayoutDescriptor);
|
|
18
|
+
}
|
|
19
|
+
return this.bindGroupLayout;
|
|
20
|
+
}
|
|
21
|
+
getBindGroupLayoutDescriptor() {
|
|
22
|
+
return this.bindGroupLayoutDescriptor;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export const defaultShader = new Shader(`
|
|
26
|
+
struct Uniforms {
|
|
27
|
+
worldProjectionMatrix: mat4x4<f32>,
|
|
28
|
+
modelProjectionMatrix: mat4x4<f32>,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@group(0) @binding(0) var<uniform> uniforms: Uniforms;
|
|
32
|
+
|
|
33
|
+
@group(0) @binding(1) var<storage> instanceMatrices: array<mat4x4f>;
|
|
34
|
+
|
|
35
|
+
struct VertexOutput {
|
|
36
|
+
@builtin(position) Position: vec4<f32>,
|
|
37
|
+
@location(0) fragUV: vec2<f32>,
|
|
38
|
+
@location(1) fragColor: vec4<f32>,
|
|
39
|
+
@location(2) fragPosition: vec4<f32>,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@vertex
|
|
43
|
+
fn vertex_main(
|
|
44
|
+
@builtin(instance_index) instanceIdx: u32,
|
|
45
|
+
@location(0) position: vec3<f32>,
|
|
46
|
+
@location(1) color: vec4<f32>,
|
|
47
|
+
@location(2) uv: vec2<f32>,
|
|
48
|
+
@location(3) drawingInstance: f32
|
|
49
|
+
) -> VertexOutput {
|
|
50
|
+
var output: VertexOutput;
|
|
51
|
+
|
|
52
|
+
if (drawingInstance == 1) {
|
|
53
|
+
output.Position = uniforms.worldProjectionMatrix * uniforms.modelProjectionMatrix * instanceMatrices[instanceIdx] * vec4(position, 1.0);
|
|
54
|
+
} else {
|
|
55
|
+
output.Position = uniforms.worldProjectionMatrix * uniforms.modelProjectionMatrix * vec4(position, 1.0);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
output.fragUV = uv;
|
|
59
|
+
output.fragPosition = output.Position;
|
|
60
|
+
output.fragColor = color;
|
|
61
|
+
return output;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@fragment
|
|
65
|
+
fn fragment_main(
|
|
66
|
+
@location(0) fragUV: vec2<f32>,
|
|
67
|
+
@location(1) fragColor: vec4<f32>,
|
|
68
|
+
@location(2) fragPosition: vec4<f32>
|
|
69
|
+
) -> @location(0) vec4<f32> {
|
|
70
|
+
return fragColor;
|
|
71
|
+
}
|
|
72
|
+
`, {
|
|
73
|
+
entries: [
|
|
74
|
+
{
|
|
75
|
+
binding: 0,
|
|
76
|
+
visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
|
|
77
|
+
buffer: {
|
|
78
|
+
type: 'uniform'
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
binding: 1,
|
|
83
|
+
visibility: GPUShaderStage.VERTEX,
|
|
84
|
+
buffer: {
|
|
85
|
+
type: 'read-only-storage'
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
});
|
package/dist/simulation.d.ts
CHANGED
|
@@ -35,6 +35,8 @@ export declare class Simulation extends Settings {
|
|
|
35
35
|
private renderInfo;
|
|
36
36
|
private resizeEvents;
|
|
37
37
|
private frameRateView;
|
|
38
|
+
private transparentElements;
|
|
39
|
+
private vertexBuffer;
|
|
38
40
|
constructor(idOrCanvasRef: string | HTMLCanvasElement, sceneCamera?: Camera | null, showFrameRate?: boolean);
|
|
39
41
|
private handleCanvasResize;
|
|
40
42
|
onResize(cb: (width: number, height: number) => void): void;
|
package/dist/simulation.js
CHANGED
|
@@ -3,56 +3,10 @@ import { EmptyElement, SimulationElement3d } from './graphics.js';
|
|
|
3
3
|
import { BUF_LEN, worldProjMatOffset } from './constants.js';
|
|
4
4
|
import { Color, matrix4, transitionValues, vector2, vector3 } from './utils.js';
|
|
5
5
|
import { BlankGeometry } from './geometry.js';
|
|
6
|
-
import { SimSceneObjInfo, buildDepthTexture, buildMultisampleTexture, updateProjectionMatrix, createPipeline, getTotalVertices, logger, removeObjectId, updateOrthoProjectionMatrix, updateWorldProjectionMatrix, globalInfo } from './internalUtils.js';
|
|
6
|
+
import createUniformBindGroup, { SimSceneObjInfo, buildDepthTexture, buildMultisampleTexture, updateProjectionMatrix, createPipeline, getTotalVertices, logger, removeObjectId, updateOrthoProjectionMatrix, updateWorldProjectionMatrix, globalInfo, CachedArray, createDefaultPipelines } from './internalUtils.js';
|
|
7
7
|
import { Settings } from './settings.js';
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
`;
|
|
8
|
+
import { defaultShader } from './shaders.js';
|
|
9
|
+
import { MemoBuffer } from './buffers.js';
|
|
56
10
|
const simjsFrameRateCss = `.simjs-frame-rate {
|
|
57
11
|
position: absolute;
|
|
58
12
|
top: 0;
|
|
@@ -69,16 +23,21 @@ class FrameRateView {
|
|
|
69
23
|
fpsBuffer = [];
|
|
70
24
|
maxFpsBufferLength = 8;
|
|
71
25
|
prevAvg = 0;
|
|
26
|
+
showing;
|
|
72
27
|
constructor(show) {
|
|
73
28
|
this.el = document.createElement('div');
|
|
74
29
|
this.el.classList.add('simjs-frame-rate');
|
|
30
|
+
this.showing = show;
|
|
75
31
|
const style = document.createElement('style');
|
|
76
32
|
style.innerHTML = simjsFrameRateCss;
|
|
77
|
-
if (
|
|
33
|
+
if (this.showing) {
|
|
78
34
|
document.head.appendChild(style);
|
|
79
35
|
document.body.appendChild(this.el);
|
|
80
36
|
}
|
|
81
37
|
}
|
|
38
|
+
isActive() {
|
|
39
|
+
return this.showing;
|
|
40
|
+
}
|
|
82
41
|
updateFrameRate(num) {
|
|
83
42
|
if (this.fpsBuffer.length < this.maxFpsBufferLength) {
|
|
84
43
|
this.fpsBuffer.push(num);
|
|
@@ -94,24 +53,6 @@ class FrameRateView {
|
|
|
94
53
|
}
|
|
95
54
|
}
|
|
96
55
|
}
|
|
97
|
-
const baseBindGroupLayout = {
|
|
98
|
-
entries: [
|
|
99
|
-
{
|
|
100
|
-
binding: 0,
|
|
101
|
-
visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
|
|
102
|
-
buffer: {
|
|
103
|
-
type: 'uniform'
|
|
104
|
-
}
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
binding: 1,
|
|
108
|
-
visibility: GPUShaderStage.VERTEX,
|
|
109
|
-
buffer: {
|
|
110
|
-
type: 'read-only-storage'
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
]
|
|
114
|
-
};
|
|
115
56
|
let aspectRatio = 0;
|
|
116
57
|
const projMat = matrix4();
|
|
117
58
|
const worldProjMat = matrix4();
|
|
@@ -215,21 +156,21 @@ export class Simulation extends Settings {
|
|
|
215
156
|
renderInfo = null;
|
|
216
157
|
resizeEvents;
|
|
217
158
|
frameRateView;
|
|
159
|
+
transparentElements;
|
|
160
|
+
vertexBuffer;
|
|
218
161
|
constructor(idOrCanvasRef, sceneCamera = null, showFrameRate = false) {
|
|
219
162
|
super();
|
|
220
163
|
if (typeof idOrCanvasRef === 'string') {
|
|
221
164
|
const ref = document.getElementById(idOrCanvasRef);
|
|
222
|
-
if (ref
|
|
223
|
-
this.canvasRef = ref;
|
|
224
|
-
else
|
|
165
|
+
if (!ref)
|
|
225
166
|
throw logger.error(`Cannot find canvas with id ${idOrCanvasRef}`);
|
|
167
|
+
this.canvasRef = ref;
|
|
226
168
|
}
|
|
227
169
|
else if (idOrCanvasRef instanceof HTMLCanvasElement) {
|
|
228
170
|
this.canvasRef = idOrCanvasRef;
|
|
229
171
|
}
|
|
230
|
-
else
|
|
172
|
+
else
|
|
231
173
|
throw logger.error(`Canvas ref/id provided is invalid`);
|
|
232
|
-
}
|
|
233
174
|
const parent = this.canvasRef.parentElement;
|
|
234
175
|
if (sceneCamera) {
|
|
235
176
|
camera = sceneCamera;
|
|
@@ -242,6 +183,8 @@ export class Simulation extends Settings {
|
|
|
242
183
|
});
|
|
243
184
|
this.frameRateView = new FrameRateView(showFrameRate);
|
|
244
185
|
this.frameRateView.updateFrameRate(1);
|
|
186
|
+
this.transparentElements = new CachedArray();
|
|
187
|
+
this.vertexBuffer = new MemoBuffer(GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST, 0);
|
|
245
188
|
}
|
|
246
189
|
handleCanvasResize(parent) {
|
|
247
190
|
if (this.fittingElement) {
|
|
@@ -320,13 +263,26 @@ export class Simulation extends Settings {
|
|
|
320
263
|
throw logger.error('Context is null');
|
|
321
264
|
const device = await adapter.requestDevice();
|
|
322
265
|
globalInfo.setDevice(device);
|
|
266
|
+
const screenSize = vector2(this.canvasRef.width, this.canvasRef.height);
|
|
267
|
+
camera.setScreenSize(screenSize);
|
|
268
|
+
const canvas = this.canvasRef;
|
|
269
|
+
canvas.width = canvas.clientWidth * devicePixelRatio;
|
|
270
|
+
canvas.height = canvas.clientHeight * devicePixelRatio;
|
|
271
|
+
const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
|
|
323
272
|
ctx.configure({
|
|
324
273
|
device,
|
|
325
|
-
format:
|
|
274
|
+
format: presentationFormat,
|
|
275
|
+
alphaMode: 'opaque'
|
|
326
276
|
});
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
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
|
+
this.render(device, ctx, canvas);
|
|
330
286
|
})();
|
|
331
287
|
}
|
|
332
288
|
stop() {
|
|
@@ -341,35 +297,7 @@ export class Simulation extends Settings {
|
|
|
341
297
|
getSceneObjects() {
|
|
342
298
|
return this.scene.map((item) => item.getObj());
|
|
343
299
|
}
|
|
344
|
-
render(ctx) {
|
|
345
|
-
const device = globalInfo.getDevice();
|
|
346
|
-
if (this.canvasRef === null || device === null)
|
|
347
|
-
return;
|
|
348
|
-
const canvas = this.canvasRef;
|
|
349
|
-
canvas.width = canvas.clientWidth * devicePixelRatio;
|
|
350
|
-
canvas.height = canvas.clientHeight * devicePixelRatio;
|
|
351
|
-
const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
|
|
352
|
-
const shaderModule = device.createShaderModule({ code: shader });
|
|
353
|
-
ctx.configure({
|
|
354
|
-
device,
|
|
355
|
-
format: presentationFormat,
|
|
356
|
-
alphaMode: 'premultiplied'
|
|
357
|
-
});
|
|
358
|
-
const instanceBuffer = device.createBuffer({
|
|
359
|
-
size: 10 * 4 * 16,
|
|
360
|
-
usage: GPUBufferUsage.STORAGE
|
|
361
|
-
});
|
|
362
|
-
const bindGroupLayout = device.createBindGroupLayout(baseBindGroupLayout);
|
|
363
|
-
this.renderInfo = {
|
|
364
|
-
bindGroupLayout,
|
|
365
|
-
instanceBuffer,
|
|
366
|
-
vertexBuffer: null
|
|
367
|
-
};
|
|
368
|
-
this.pipelines = {
|
|
369
|
-
triangleList: createPipeline(device, shaderModule, [bindGroupLayout], presentationFormat, 'triangle-list'),
|
|
370
|
-
triangleStrip: createPipeline(device, shaderModule, [bindGroupLayout], presentationFormat, 'triangle-strip'),
|
|
371
|
-
lineStrip: createPipeline(device, shaderModule, [bindGroupLayout], presentationFormat, 'line-strip')
|
|
372
|
-
};
|
|
300
|
+
render(device, ctx, canvas) {
|
|
373
301
|
const colorAttachment = {
|
|
374
302
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
375
303
|
// @ts-ignore
|
|
@@ -400,9 +328,7 @@ export class Simulation extends Settings {
|
|
|
400
328
|
let prev = Date.now() - 10;
|
|
401
329
|
let prevFps = 0;
|
|
402
330
|
const frame = async () => {
|
|
403
|
-
if (!canvas)
|
|
404
|
-
return;
|
|
405
|
-
if (!this.renderInfo)
|
|
331
|
+
if (!canvas || !this.renderInfo)
|
|
406
332
|
return;
|
|
407
333
|
requestAnimationFrame(frame);
|
|
408
334
|
if (!this.running)
|
|
@@ -411,12 +337,10 @@ export class Simulation extends Settings {
|
|
|
411
337
|
const diff = Math.max(now - prev, 1);
|
|
412
338
|
prev = now;
|
|
413
339
|
const fps = 1000 / diff;
|
|
414
|
-
if (fps === prevFps) {
|
|
340
|
+
if (this.frameRateView.isActive() && fps === prevFps) {
|
|
415
341
|
this.frameRateView.updateFrameRate(fps);
|
|
416
342
|
}
|
|
417
343
|
prevFps = fps;
|
|
418
|
-
canvas.width = canvas.clientWidth * devicePixelRatio;
|
|
419
|
-
canvas.height = canvas.clientHeight * devicePixelRatio;
|
|
420
344
|
const screenSize = camera.getScreenSize();
|
|
421
345
|
if (screenSize[0] !== canvas.width || screenSize[1] !== canvas.height) {
|
|
422
346
|
camera.setScreenSize(vector2(canvas.width, canvas.height));
|
|
@@ -441,23 +365,18 @@ export class Simulation extends Settings {
|
|
|
441
365
|
}
|
|
442
366
|
const commandEncoder = device.createCommandEncoder();
|
|
443
367
|
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
|
|
444
|
-
passEncoder.setPipeline(this.pipelines.triangleList);
|
|
445
368
|
const totalVertices = getTotalVertices(this.scene);
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
|
|
451
|
-
});
|
|
452
|
-
}
|
|
453
|
-
this.renderScene(device, passEncoder, this.renderInfo.vertexBuffer, this.scene, 0, diff);
|
|
369
|
+
this.vertexBuffer.setSize(totalVertices * 4 * BUF_LEN);
|
|
370
|
+
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);
|
|
454
373
|
camera.updateConsumed();
|
|
455
374
|
passEncoder.end();
|
|
456
375
|
device.queue.submit([commandEncoder.finish()]);
|
|
457
376
|
};
|
|
458
377
|
requestAnimationFrame(frame);
|
|
459
378
|
}
|
|
460
|
-
renderScene(device, passEncoder, vertexBuffer, scene, startOffset, diff, shaderInfo) {
|
|
379
|
+
renderScene(device, passEncoder, vertexBuffer, scene, startOffset, diff, transparent, shaderInfo) {
|
|
461
380
|
if (this.pipelines === null)
|
|
462
381
|
return 0;
|
|
463
382
|
let currentOffset = startOffset;
|
|
@@ -473,6 +392,10 @@ export class Simulation extends Settings {
|
|
|
473
392
|
scene[i].traverseLife(diff);
|
|
474
393
|
}
|
|
475
394
|
const obj = scene[i].getObj();
|
|
395
|
+
if (!transparent && obj.isTransparent()) {
|
|
396
|
+
this.transparentElements.add(scene[i]);
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
476
399
|
if (obj.hasChildren()) {
|
|
477
400
|
let shaderInfo = undefined;
|
|
478
401
|
if (obj instanceof ShaderGroup) {
|
|
@@ -490,7 +413,7 @@ export class Simulation extends Settings {
|
|
|
490
413
|
};
|
|
491
414
|
}
|
|
492
415
|
}
|
|
493
|
-
currentOffset += this.renderScene(device, passEncoder, vertexBuffer, obj.getChildrenInfos(), currentOffset, diff, shaderInfo);
|
|
416
|
+
currentOffset += this.renderScene(device, passEncoder, vertexBuffer, obj.getChildrenInfos(), currentOffset, diff, transparent, shaderInfo);
|
|
494
417
|
}
|
|
495
418
|
if (obj.isEmpty)
|
|
496
419
|
continue;
|
|
@@ -508,15 +431,25 @@ export class Simulation extends Settings {
|
|
|
508
431
|
passEncoder.setPipeline(shaderInfo.pipeline);
|
|
509
432
|
}
|
|
510
433
|
else if (obj.isWireframe()) {
|
|
511
|
-
|
|
434
|
+
if (obj.isTransparent())
|
|
435
|
+
passEncoder.setPipeline(this.pipelines.lineStripTransparent);
|
|
436
|
+
else
|
|
437
|
+
passEncoder.setPipeline(this.pipelines.lineStrip);
|
|
512
438
|
}
|
|
513
439
|
else {
|
|
514
440
|
const type = obj.getGeometryType();
|
|
441
|
+
// must be exhaustive
|
|
515
442
|
if (type === 'strip') {
|
|
516
|
-
|
|
443
|
+
if (obj.isTransparent())
|
|
444
|
+
passEncoder.setPipeline(this.pipelines.triangleStripTransparent);
|
|
445
|
+
else
|
|
446
|
+
passEncoder.setPipeline(this.pipelines.triangleStrip);
|
|
517
447
|
}
|
|
518
448
|
else if (type === 'list') {
|
|
519
|
-
|
|
449
|
+
if (obj.isTransparent())
|
|
450
|
+
passEncoder.setPipeline(this.pipelines.triangleListTransparent);
|
|
451
|
+
else
|
|
452
|
+
passEncoder.setPipeline(this.pipelines.triangleList);
|
|
520
453
|
}
|
|
521
454
|
}
|
|
522
455
|
let instances = 1;
|
|
@@ -530,23 +463,7 @@ export class Simulation extends Settings {
|
|
|
530
463
|
else {
|
|
531
464
|
instanceBuffer = this.renderInfo.instanceBuffer;
|
|
532
465
|
}
|
|
533
|
-
const uniformBindGroup =
|
|
534
|
-
layout: this.renderInfo.bindGroupLayout,
|
|
535
|
-
entries: [
|
|
536
|
-
{
|
|
537
|
-
binding: 0,
|
|
538
|
-
resource: {
|
|
539
|
-
buffer: uniformBuffer
|
|
540
|
-
}
|
|
541
|
-
},
|
|
542
|
-
{
|
|
543
|
-
binding: 1,
|
|
544
|
-
resource: {
|
|
545
|
-
buffer: instanceBuffer
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
]
|
|
549
|
-
});
|
|
466
|
+
const uniformBindGroup = createUniformBindGroup(defaultShader, [uniformBuffer, instanceBuffer]);
|
|
550
467
|
passEncoder.setBindGroup(0, uniformBindGroup);
|
|
551
468
|
}
|
|
552
469
|
if (shaderInfo && shaderInfo.bufferInfo) {
|
|
@@ -620,7 +537,7 @@ export class ShaderGroup extends EmptyElement {
|
|
|
620
537
|
const device = globalInfo.errorGetDevice();
|
|
621
538
|
this.module = device.createShaderModule({ code: this.code });
|
|
622
539
|
const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
|
|
623
|
-
const bindGroupLayout =
|
|
540
|
+
const bindGroupLayout = defaultShader.getBindGroupLayout();
|
|
624
541
|
const bindGroups = [bindGroupLayout];
|
|
625
542
|
if (this.bindGroup !== null) {
|
|
626
543
|
const entryValues = this.bindGroup.bindings.map((binding, index) => ({
|
|
@@ -633,7 +550,9 @@ export class ShaderGroup extends EmptyElement {
|
|
|
633
550
|
});
|
|
634
551
|
bindGroups.push(this.bindGroupLayout);
|
|
635
552
|
}
|
|
636
|
-
this.pipeline = createPipeline(device, this.module, bindGroups, presentationFormat, this.topology,
|
|
553
|
+
this.pipeline = createPipeline(device, this.module, bindGroups, presentationFormat, this.topology,
|
|
554
|
+
// TODO possibly make transparent materials
|
|
555
|
+
false, this.vertexParams);
|
|
637
556
|
}
|
|
638
557
|
getBindGroupLayout() {
|
|
639
558
|
return this.bindGroupLayout;
|
package/dist/types.d.ts
CHANGED
|
@@ -73,11 +73,12 @@ export type PipelineGroup = {
|
|
|
73
73
|
triangleList: GPURenderPipeline;
|
|
74
74
|
triangleStrip: GPURenderPipeline;
|
|
75
75
|
lineStrip: GPURenderPipeline;
|
|
76
|
+
triangleListTransparent: GPURenderPipeline;
|
|
77
|
+
triangleStripTransparent: GPURenderPipeline;
|
|
78
|
+
lineStripTransparent: GPURenderPipeline;
|
|
76
79
|
};
|
|
77
80
|
export type RenderInfo = {
|
|
78
81
|
instanceBuffer: GPUBuffer;
|
|
79
|
-
bindGroupLayout: GPUBindGroupLayout;
|
|
80
|
-
vertexBuffer: GPUBuffer | null;
|
|
81
82
|
};
|
|
82
83
|
export type VertexParamGeneratorInfo = {
|
|
83
84
|
bufferSize: number;
|