@footgun/cobalt 0.8.0 → 0.8.1
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/CHANGELOG.md +4 -0
- package/bundle.js +3 -3
- package/package.json +1 -1
- package/src/cobalt.js +1 -0
- package/src/displacement/{displacement-composition.ts → displacement-composition.js} +21 -57
- package/src/displacement/displacement-parameters-buffer.js +21 -0
- package/src/displacement/{displacement-texture.ts → displacement-texture.js} +29 -87
- package/src/displacement/{triangles-buffer.ts → triangles-buffer.js} +18 -44
- package/src/light/{lights-buffer.ts → lights-buffer.js} +13 -36
- package/src/light/{lights-renderer.ts → lights-renderer.js} +24 -72
- package/src/light/texture/{lights-texture-initializer.ts → lights-texture-initializer.js} +11 -27
- package/src/light/texture/{lights-texture-mask.ts → lights-texture-mask.js} +36 -87
- package/src/light/texture/{lights-texture.ts → lights-texture.js} +16 -52
- package/src/light/{viewport.ts → viewport.js} +11 -34
- package/src/displacement/displacement-parameters-buffer.ts +0 -44
- package/src/light/types.ts +0 -23
package/package.json
CHANGED
package/src/cobalt.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { default as createTexture } from './create-texture.js'
|
|
2
2
|
export { default as createTextureFromBuffer } from './create-texture-from-buffer.js'
|
|
3
3
|
export { default as createTextureFromUrl } from './create-texture-from-url.js'
|
|
4
|
+
export { default as getPreferredFormat } from './get-preferred-format.js'
|
|
4
5
|
|
|
5
6
|
// built-in run nodes
|
|
6
7
|
import bloomNode from './bloom/bloom.js'
|
|
@@ -1,50 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { DisplacementParametersBuffer } from "./displacement-parameters-buffer";
|
|
4
|
-
import compositionWGSL from "./composition.wgsl"
|
|
5
|
-
|
|
6
|
-
type Parameters = {
|
|
7
|
-
readonly device: GPUDevice;
|
|
8
|
-
readonly targetFormat: GPUTextureFormat;
|
|
9
|
-
|
|
10
|
-
readonly colorTextureView: GPUTextureView;
|
|
11
|
-
readonly noiseMapTextureView: GPUTextureView;
|
|
12
|
-
readonly displacementTextureView: GPUTextureView;
|
|
13
|
-
|
|
14
|
-
readonly displacementParametersBuffer: DisplacementParametersBuffer;
|
|
15
|
-
};
|
|
1
|
+
import compositionWGSL from "./composition.wgsl";
|
|
16
2
|
|
|
17
3
|
class DisplacementComposition {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
private colorTextureView: GPUTextureView;
|
|
30
|
-
private noiseMapTextureView: GPUTextureView;
|
|
31
|
-
private displacementTextureView: GPUTextureView;
|
|
32
|
-
|
|
33
|
-
public constructor(params: Parameters) {
|
|
4
|
+
device;
|
|
5
|
+
targetFormat;
|
|
6
|
+
renderPipeline;
|
|
7
|
+
colorSampler;
|
|
8
|
+
noiseSampler;
|
|
9
|
+
displacementParametersBuffer;
|
|
10
|
+
renderBundle = null;
|
|
11
|
+
colorTextureView;
|
|
12
|
+
noiseMapTextureView;
|
|
13
|
+
displacementTextureView;
|
|
14
|
+
constructor(params) {
|
|
34
15
|
this.device = params.device;
|
|
35
|
-
|
|
36
16
|
this.targetFormat = params.targetFormat;
|
|
37
17
|
this.colorTextureView = params.colorTextureView;
|
|
38
18
|
this.noiseMapTextureView = params.noiseMapTextureView;
|
|
39
19
|
this.displacementTextureView = params.displacementTextureView;
|
|
40
|
-
|
|
41
20
|
this.displacementParametersBuffer = params.displacementParametersBuffer;
|
|
42
|
-
|
|
43
21
|
const shaderModule = this.device.createShaderModule({
|
|
44
22
|
label: "DisplacementComposition shader module",
|
|
45
23
|
code: compositionWGSL,
|
|
46
24
|
});
|
|
47
|
-
|
|
48
25
|
this.renderPipeline = this.device.createRenderPipeline({
|
|
49
26
|
label: "DisplacementComposition renderpipeline",
|
|
50
27
|
layout: "auto",
|
|
@@ -56,15 +33,14 @@ class DisplacementComposition {
|
|
|
56
33
|
module: shaderModule,
|
|
57
34
|
entryPoint: "main_fragment",
|
|
58
35
|
targets: [{
|
|
59
|
-
|
|
60
|
-
|
|
36
|
+
format: params.targetFormat,
|
|
37
|
+
}],
|
|
61
38
|
},
|
|
62
39
|
primitive: {
|
|
63
40
|
cullMode: "none",
|
|
64
41
|
topology: "triangle-strip",
|
|
65
42
|
},
|
|
66
43
|
});
|
|
67
|
-
|
|
68
44
|
this.noiseSampler = this.device.createSampler({
|
|
69
45
|
label: "DisplacementComposition noisesampler",
|
|
70
46
|
addressModeU: "repeat",
|
|
@@ -74,7 +50,6 @@ class DisplacementComposition {
|
|
|
74
50
|
minFilter: "linear",
|
|
75
51
|
mipmapFilter: "linear",
|
|
76
52
|
});
|
|
77
|
-
|
|
78
53
|
this.colorSampler = this.device.createSampler({
|
|
79
54
|
label: "DisplacementComposition colorSampler",
|
|
80
55
|
addressModeU: "clamp-to-edge",
|
|
@@ -85,34 +60,28 @@ class DisplacementComposition {
|
|
|
85
60
|
mipmapFilter: "linear",
|
|
86
61
|
});
|
|
87
62
|
}
|
|
88
|
-
|
|
89
|
-
public getRenderBundle(): GPURenderBundle {
|
|
63
|
+
getRenderBundle() {
|
|
90
64
|
if (!this.renderBundle) {
|
|
91
65
|
this.renderBundle = this.buildRenderBundle();
|
|
92
66
|
}
|
|
93
67
|
return this.renderBundle;
|
|
94
68
|
}
|
|
95
|
-
|
|
96
|
-
public destroy(): void {
|
|
69
|
+
destroy() {
|
|
97
70
|
// nothing to do
|
|
98
71
|
}
|
|
99
|
-
|
|
100
|
-
public setColorTextureView(textureView: GPUTextureView): void {
|
|
72
|
+
setColorTextureView(textureView) {
|
|
101
73
|
this.colorTextureView = textureView;
|
|
102
74
|
this.renderBundle = null;
|
|
103
75
|
}
|
|
104
|
-
|
|
105
|
-
public setNoiseMapTextureView(textureView: GPUTextureView): void {
|
|
76
|
+
setNoiseMapTextureView(textureView) {
|
|
106
77
|
this.noiseMapTextureView = textureView;
|
|
107
78
|
this.renderBundle = null;
|
|
108
79
|
}
|
|
109
|
-
|
|
110
|
-
public setDisplacementTextureView(textureView: GPUTextureView): void {
|
|
80
|
+
setDisplacementTextureView(textureView) {
|
|
111
81
|
this.displacementTextureView = textureView;
|
|
112
82
|
this.renderBundle = null;
|
|
113
83
|
}
|
|
114
|
-
|
|
115
|
-
private buildRenderBundle(): GPURenderBundle {
|
|
84
|
+
buildRenderBundle() {
|
|
116
85
|
const bindgroup = this.device.createBindGroup({
|
|
117
86
|
label: "DisplacementComposition bindgroup 0",
|
|
118
87
|
layout: this.renderPipeline.getBindGroupLayout(0),
|
|
@@ -143,7 +112,6 @@ class DisplacementComposition {
|
|
|
143
112
|
},
|
|
144
113
|
],
|
|
145
114
|
});
|
|
146
|
-
|
|
147
115
|
const renderBundleEncoder = this.device.createRenderBundleEncoder({
|
|
148
116
|
label: "DisplacementComposition renderbundle encoder",
|
|
149
117
|
colorFormats: [this.targetFormat],
|
|
@@ -154,8 +122,4 @@ class DisplacementComposition {
|
|
|
154
122
|
return renderBundleEncoder.finish({ label: "DisplacementComposition renderbundle" });
|
|
155
123
|
}
|
|
156
124
|
}
|
|
157
|
-
|
|
158
|
-
export {
|
|
159
|
-
DisplacementComposition
|
|
160
|
-
};
|
|
161
|
-
|
|
125
|
+
export { DisplacementComposition };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
class DisplacementParametersBuffer {
|
|
2
|
+
device;
|
|
3
|
+
bufferGpu;
|
|
4
|
+
needsUpdate = true;
|
|
5
|
+
constructor(params) {
|
|
6
|
+
this.device = params.device;
|
|
7
|
+
this.bufferGpu = this.device.createBuffer({
|
|
8
|
+
label: "DisplacementParametersBuffer buffer",
|
|
9
|
+
size: 16,
|
|
10
|
+
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
|
|
11
|
+
});
|
|
12
|
+
this.setParameters(params.initialParameters);
|
|
13
|
+
}
|
|
14
|
+
setParameters(params) {
|
|
15
|
+
this.device.queue.writeBuffer(this.bufferGpu, 0, new Float32Array([params.offsetX, params.offsetY, params.scale]));
|
|
16
|
+
}
|
|
17
|
+
destroy() {
|
|
18
|
+
this.bufferGpu.destroy();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export { DisplacementParametersBuffer };
|
|
@@ -1,63 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import displacementWGSL from './displacement.wgsl'
|
|
4
|
-
import * as wgpuMatrix from "wgpu-matrix";
|
|
5
|
-
import { TrianglesBuffer } from "./triangles-buffer";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
type Viewport = {
|
|
9
|
-
readonly width: number;
|
|
10
|
-
readonly height: number;
|
|
11
|
-
readonly zoom: number;
|
|
12
|
-
readonly position: [number, number];
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
type Parameters = {
|
|
16
|
-
readonly device: GPUDevice;
|
|
17
|
-
|
|
18
|
-
readonly width: number;
|
|
19
|
-
readonly height: number;
|
|
20
|
-
|
|
21
|
-
readonly blurFactor: number;
|
|
22
|
-
|
|
23
|
-
readonly trianglesBuffer: TrianglesBuffer;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
type TextureWithView = {
|
|
27
|
-
readonly texture: GPUTexture;
|
|
28
|
-
readonly view: GPUTextureView;
|
|
29
|
-
};
|
|
1
|
+
import displacementWGSL from './displacement.wgsl';
|
|
2
|
+
import * as wgpuMatrix from "wgpu-matrix";
|
|
30
3
|
|
|
31
4
|
class DisplacementTexture {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
private readonly trianglesBuffer: TrianglesBuffer;
|
|
45
|
-
|
|
46
|
-
public constructor(params: Parameters) {
|
|
5
|
+
device;
|
|
6
|
+
format = "r8unorm";
|
|
7
|
+
downsizeFactor;
|
|
8
|
+
multisample;
|
|
9
|
+
textureSimple;
|
|
10
|
+
textureMultisampled = null;
|
|
11
|
+
renderPipeline;
|
|
12
|
+
bindgroup;
|
|
13
|
+
uniformsBuffer;
|
|
14
|
+
trianglesBuffer;
|
|
15
|
+
constructor(params) {
|
|
47
16
|
this.device = params.device;
|
|
48
17
|
this.downsizeFactor = params.blurFactor;
|
|
49
18
|
this.multisample = this.downsizeFactor > 1 ? 4 : 1;
|
|
50
|
-
|
|
51
19
|
[this.textureSimple, this.textureMultisampled] = this.createTextures(params.width, params.height);
|
|
52
|
-
|
|
53
20
|
this.trianglesBuffer = params.trianglesBuffer;
|
|
54
|
-
|
|
55
21
|
const shaderModule = this.device.createShaderModule({
|
|
56
22
|
label: "DisplacementTexture shader module",
|
|
57
23
|
code: displacementWGSL,
|
|
58
|
-
|
|
59
24
|
});
|
|
60
|
-
|
|
61
25
|
this.renderPipeline = this.device.createRenderPipeline({
|
|
62
26
|
label: "DisplacementTexture renderpipeline",
|
|
63
27
|
layout: "auto",
|
|
@@ -82,8 +46,8 @@ class DisplacementTexture {
|
|
|
82
46
|
module: shaderModule,
|
|
83
47
|
entryPoint: "main_fragment",
|
|
84
48
|
targets: [{
|
|
85
|
-
|
|
86
|
-
|
|
49
|
+
format: this.format,
|
|
50
|
+
}],
|
|
87
51
|
},
|
|
88
52
|
primitive: {
|
|
89
53
|
cullMode: "none",
|
|
@@ -93,13 +57,11 @@ class DisplacementTexture {
|
|
|
93
57
|
count: this.multisample,
|
|
94
58
|
},
|
|
95
59
|
});
|
|
96
|
-
|
|
97
60
|
this.uniformsBuffer = this.device.createBuffer({
|
|
98
61
|
label: "DisplacementTexture uniforms buffer",
|
|
99
62
|
size: 64,
|
|
100
63
|
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
|
|
101
64
|
});
|
|
102
|
-
|
|
103
65
|
this.bindgroup = this.device.createBindGroup({
|
|
104
66
|
label: "DisplacementTexture bindgroup",
|
|
105
67
|
layout: this.renderPipeline.getBindGroupLayout(0),
|
|
@@ -111,11 +73,9 @@ class DisplacementTexture {
|
|
|
111
73
|
],
|
|
112
74
|
});
|
|
113
75
|
}
|
|
114
|
-
|
|
115
|
-
public update(commandEncoder: GPUCommandEncoder): void {
|
|
76
|
+
update(commandEncoder) {
|
|
116
77
|
const targetTexture = this.textureMultisampled ?? this.textureSimple;
|
|
117
|
-
|
|
118
|
-
const textureRenderpassColorAttachment: GPURenderPassColorAttachment = {
|
|
78
|
+
const textureRenderpassColorAttachment = {
|
|
119
79
|
view: targetTexture.view,
|
|
120
80
|
clearValue: [0, 0, 0, 1],
|
|
121
81
|
loadOp: "clear",
|
|
@@ -124,12 +84,10 @@ class DisplacementTexture {
|
|
|
124
84
|
if (this.textureMultisampled) {
|
|
125
85
|
textureRenderpassColorAttachment.resolveTarget = this.textureSimple.view;
|
|
126
86
|
}
|
|
127
|
-
|
|
128
87
|
const renderpassEncoder = commandEncoder.beginRenderPass({
|
|
129
88
|
label: "DisplacementTexture render to texture renderpass",
|
|
130
89
|
colorAttachments: [textureRenderpassColorAttachment],
|
|
131
90
|
});
|
|
132
|
-
|
|
133
91
|
const [textureWidth, textureHeight] = [targetTexture.texture.width, targetTexture.texture.height];
|
|
134
92
|
renderpassEncoder.setViewport(0, 0, textureWidth, textureHeight, 0, 1);
|
|
135
93
|
renderpassEncoder.setScissorRect(0, 0, textureWidth, textureHeight);
|
|
@@ -138,50 +96,40 @@ class DisplacementTexture {
|
|
|
138
96
|
renderpassEncoder.setVertexBuffer(0, this.trianglesBuffer.bufferGpu);
|
|
139
97
|
renderpassEncoder.draw(3 * this.trianglesBuffer.spriteCount);
|
|
140
98
|
renderpassEncoder.end();
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
|
|
99
|
+
}
|
|
100
|
+
;
|
|
101
|
+
resize(width, height) {
|
|
144
102
|
this.textureSimple.texture.destroy();
|
|
145
103
|
this.textureMultisampled?.texture.destroy();
|
|
146
|
-
|
|
147
104
|
[this.textureSimple, this.textureMultisampled] = this.createTextures(width, height);
|
|
148
105
|
}
|
|
149
|
-
|
|
150
|
-
public setViewport(viewport: Viewport): void {
|
|
106
|
+
setViewport(viewport) {
|
|
151
107
|
const scaling = [1, 1, 1];
|
|
152
108
|
const rotation = 0;
|
|
153
109
|
const translation = [1, 1, 0];
|
|
154
|
-
|
|
155
110
|
const modelMatrix = wgpuMatrix.mat4.identity();
|
|
156
111
|
wgpuMatrix.mat4.multiply(wgpuMatrix.mat4.scaling(scaling), modelMatrix, modelMatrix);
|
|
157
112
|
wgpuMatrix.mat4.multiply(wgpuMatrix.mat4.rotationZ(rotation), modelMatrix, modelMatrix);
|
|
158
113
|
wgpuMatrix.mat4.multiply(wgpuMatrix.mat4.translation(translation), modelMatrix, modelMatrix);
|
|
159
|
-
|
|
160
114
|
const viewMatrix = wgpuMatrix.mat4.translation([-viewport.position[0], -viewport.position[1], 0]);
|
|
161
|
-
|
|
162
|
-
const
|
|
163
|
-
const gameHeight = viewport.height / viewport.zoom
|
|
115
|
+
const gameWidth = viewport.width / viewport.zoom;
|
|
116
|
+
const gameHeight = viewport.height / viewport.zoom;
|
|
164
117
|
// left right bottom top near far
|
|
165
|
-
const projectionMatrix = wgpuMatrix.mat4.ortho(0, gameWidth, gameHeight, 0, -10.0, 10.0)
|
|
166
|
-
|
|
118
|
+
const projectionMatrix = wgpuMatrix.mat4.ortho(0, gameWidth, gameHeight, 0, -10.0, 10.0);
|
|
167
119
|
const mvpMatrix = wgpuMatrix.mat4.identity();
|
|
168
120
|
wgpuMatrix.mat4.multiply(viewMatrix, modelMatrix, mvpMatrix);
|
|
169
121
|
wgpuMatrix.mat4.multiply(projectionMatrix, mvpMatrix, mvpMatrix);
|
|
170
|
-
|
|
171
122
|
this.device.queue.writeBuffer(this.uniformsBuffer, 0, mvpMatrix);
|
|
172
123
|
}
|
|
173
|
-
|
|
174
|
-
public getView(): GPUTextureView {
|
|
124
|
+
getView() {
|
|
175
125
|
return this.textureSimple.view;
|
|
176
126
|
}
|
|
177
|
-
|
|
178
|
-
public destroy(): void {
|
|
127
|
+
destroy() {
|
|
179
128
|
this.textureSimple.texture.destroy();
|
|
180
129
|
this.textureMultisampled?.texture.destroy();
|
|
181
130
|
this.uniformsBuffer.destroy();
|
|
182
131
|
}
|
|
183
|
-
|
|
184
|
-
private createTextures(width: number, height: number): [TextureWithView, TextureWithView | null] {
|
|
132
|
+
createTextures(width, height) {
|
|
185
133
|
const texture = this.device.createTexture({
|
|
186
134
|
label: "DisplacementTexture texture",
|
|
187
135
|
size: [
|
|
@@ -195,8 +143,7 @@ class DisplacementTexture {
|
|
|
195
143
|
texture,
|
|
196
144
|
view: texture.createView({ label: "DisplacementTexture texture view" }),
|
|
197
145
|
};
|
|
198
|
-
|
|
199
|
-
let textureMultisampled: TextureWithView | null = null;
|
|
146
|
+
let textureMultisampled = null;
|
|
200
147
|
if (this.multisample > 1) {
|
|
201
148
|
const textureMulti = this.device.createTexture({
|
|
202
149
|
label: "DisplacementTexture texture multisampled",
|
|
@@ -210,12 +157,7 @@ class DisplacementTexture {
|
|
|
210
157
|
view: textureMulti.createView({ label: "DisplacementTexture texture multisampled view" }),
|
|
211
158
|
};
|
|
212
159
|
}
|
|
213
|
-
|
|
214
160
|
return [textureSimple, textureMultisampled];
|
|
215
161
|
}
|
|
216
162
|
}
|
|
217
|
-
|
|
218
|
-
export {
|
|
219
|
-
DisplacementTexture
|
|
220
|
-
};
|
|
221
|
-
|
|
163
|
+
export { DisplacementTexture };
|
|
@@ -1,74 +1,53 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import uuid from '../uuid.js'
|
|
4
|
-
|
|
5
|
-
type Parameters = {
|
|
6
|
-
readonly device: GPUDevice;
|
|
7
|
-
readonly maxSpriteCount: number;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
type Point = [number, number];
|
|
11
|
-
type TriangleVertices = [Point, Point, Point];
|
|
12
|
-
type TriangleData = [number, number, number, number, number, number];
|
|
1
|
+
import uuid from '../uuid.js';
|
|
13
2
|
|
|
14
3
|
class TrianglesBuffer {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
private readonly sprites: Map<number, TriangleData> = new Map();
|
|
22
|
-
public get spriteCount(): number {
|
|
4
|
+
device;
|
|
5
|
+
floatsPerSprite = 6; // vec2(translate) + vec2(scale) + rotation + opacity
|
|
6
|
+
bufferGpu;
|
|
7
|
+
bufferNeedsUpdate = false;
|
|
8
|
+
sprites = new Map();
|
|
9
|
+
get spriteCount() {
|
|
23
10
|
return this.sprites.size;
|
|
24
11
|
}
|
|
25
|
-
|
|
26
|
-
public constructor(params: Parameters) {
|
|
12
|
+
constructor(params) {
|
|
27
13
|
this.device = params.device;
|
|
28
|
-
|
|
29
14
|
this.bufferGpu = this.device.createBuffer({
|
|
30
15
|
size: params.maxSpriteCount * this.floatsPerSprite * Float32Array.BYTES_PER_ELEMENT,
|
|
31
16
|
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
|
|
32
17
|
});
|
|
33
18
|
}
|
|
34
|
-
|
|
35
|
-
public destroy(): void {
|
|
19
|
+
destroy() {
|
|
36
20
|
this.bufferGpu.destroy;
|
|
37
21
|
}
|
|
38
|
-
|
|
39
|
-
public update(): void {
|
|
22
|
+
update() {
|
|
40
23
|
if (this.bufferNeedsUpdate) {
|
|
41
|
-
const bufferData
|
|
24
|
+
const bufferData = [];
|
|
42
25
|
for (const sprite of this.sprites.values()) {
|
|
43
26
|
bufferData.push(...sprite);
|
|
44
|
-
}
|
|
27
|
+
}
|
|
28
|
+
;
|
|
45
29
|
const buffer = new Float32Array(bufferData);
|
|
46
30
|
this.device.queue.writeBuffer(this.bufferGpu, 0, buffer);
|
|
47
31
|
}
|
|
48
32
|
}
|
|
49
|
-
|
|
50
|
-
public addTriangle(triangleVertices: TriangleVertices): number {
|
|
33
|
+
addTriangle(triangleVertices) {
|
|
51
34
|
const triangleId = uuid();
|
|
52
35
|
if (this.sprites.has(triangleId)) {
|
|
53
36
|
throw new Error(`Duplicate triangle "${triangleId}".`);
|
|
54
37
|
}
|
|
55
|
-
|
|
56
38
|
const triangleData = this.buildTriangleData(triangleVertices);
|
|
57
39
|
this.sprites.set(triangleId, triangleData);
|
|
58
40
|
this.bufferNeedsUpdate = true;
|
|
59
|
-
|
|
60
41
|
return triangleId;
|
|
61
42
|
}
|
|
62
|
-
|
|
63
|
-
public removeTriangle(triangleId: number): void {
|
|
43
|
+
removeTriangle(triangleId) {
|
|
64
44
|
if (!this.sprites.has(triangleId)) {
|
|
65
45
|
throw new Error(`Unknown triangle "${triangleId}".`);
|
|
66
46
|
}
|
|
67
47
|
this.sprites.delete(triangleId);
|
|
68
48
|
this.bufferNeedsUpdate = true;
|
|
69
49
|
}
|
|
70
|
-
|
|
71
|
-
public setTriangle(triangleId: number, triangleVertices: TriangleVertices): void {
|
|
50
|
+
setTriangle(triangleId, triangleVertices) {
|
|
72
51
|
if (!this.sprites.has(triangleId)) {
|
|
73
52
|
throw new Error(`Unknown triangle "${triangleId}".`);
|
|
74
53
|
}
|
|
@@ -76,8 +55,7 @@ class TrianglesBuffer {
|
|
|
76
55
|
this.sprites.set(triangleId, triangleData);
|
|
77
56
|
this.bufferNeedsUpdate = true;
|
|
78
57
|
}
|
|
79
|
-
|
|
80
|
-
private buildTriangleData(triangleVertices: TriangleVertices): TriangleData {
|
|
58
|
+
buildTriangleData(triangleVertices) {
|
|
81
59
|
return [
|
|
82
60
|
triangleVertices[0][0],
|
|
83
61
|
triangleVertices[0][1],
|
|
@@ -88,8 +66,4 @@ class TrianglesBuffer {
|
|
|
88
66
|
];
|
|
89
67
|
}
|
|
90
68
|
}
|
|
91
|
-
|
|
92
|
-
export {
|
|
93
|
-
TrianglesBuffer
|
|
94
|
-
};
|
|
95
|
-
|
|
69
|
+
export { TrianglesBuffer };
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
/// <reference types="@webgpu/types"/>
|
|
2
|
-
|
|
3
|
-
import { type Light } from "./types";
|
|
4
|
-
|
|
5
1
|
class LightsBuffer {
|
|
6
|
-
|
|
2
|
+
static structs = {
|
|
7
3
|
definition: `
|
|
8
4
|
struct Light { // align(16) size(48)
|
|
9
5
|
color: vec3<f32>, // offset(0) align(16) size(12)
|
|
@@ -28,24 +24,16 @@ struct LightsBuffer { // align(16)
|
|
|
28
24
|
lights: { offset: 16, stride: 48 },
|
|
29
25
|
},
|
|
30
26
|
};
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
private readonly buffer: {
|
|
38
|
-
readonly bufferCpu: ArrayBuffer;
|
|
39
|
-
readonly bufferGpu: GPUBuffer;
|
|
40
|
-
};
|
|
41
|
-
public get gpuBuffer(): GPUBuffer {
|
|
27
|
+
device;
|
|
28
|
+
maxLightsCount;
|
|
29
|
+
currentLightsCount = 0;
|
|
30
|
+
buffer;
|
|
31
|
+
get gpuBuffer() {
|
|
42
32
|
return this.buffer.bufferGpu;
|
|
43
33
|
}
|
|
44
|
-
|
|
45
|
-
public constructor(device: GPUDevice, maxLightsCount: number) {
|
|
34
|
+
constructor(device, maxLightsCount) {
|
|
46
35
|
this.device = device;
|
|
47
36
|
this.maxLightsCount = maxLightsCount;
|
|
48
|
-
|
|
49
37
|
const bufferCpu = new ArrayBuffer(LightsBuffer.computeBufferBytesLength(maxLightsCount));
|
|
50
38
|
const bufferGpu = device.createBuffer({
|
|
51
39
|
label: "LightsBuffer buffer",
|
|
@@ -53,19 +41,15 @@ struct LightsBuffer { // align(16)
|
|
|
53
41
|
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.VERTEX,
|
|
54
42
|
});
|
|
55
43
|
this.buffer = { bufferCpu, bufferGpu };
|
|
56
|
-
|
|
57
44
|
this.setLights([]);
|
|
58
45
|
}
|
|
59
|
-
|
|
60
|
-
public setLights(lights: ReadonlyArray<Light>): void {
|
|
46
|
+
setLights(lights) {
|
|
61
47
|
if (lights.length > this.maxLightsCount) {
|
|
62
48
|
throw new Error(`Too many lights "${lights.length}", max is "${this.maxLightsCount}".`);
|
|
63
49
|
}
|
|
64
|
-
|
|
65
50
|
const newBufferLength = LightsBuffer.computeBufferBytesLength(lights.length);
|
|
66
51
|
new Uint32Array(this.buffer.bufferCpu, 0, 1).set([lights.length]);
|
|
67
|
-
|
|
68
|
-
lights.forEach((light: Light, index: number) => {
|
|
52
|
+
lights.forEach((light, index) => {
|
|
69
53
|
new Float32Array(this.buffer.bufferCpu, LightsBuffer.structs.lightsBuffer.lights.offset + LightsBuffer.structs.lightsBuffer.lights.stride * index, 9).set([
|
|
70
54
|
...light.color,
|
|
71
55
|
light.radius,
|
|
@@ -75,24 +59,17 @@ struct LightsBuffer { // align(16)
|
|
|
75
59
|
light.attenuationExp
|
|
76
60
|
]);
|
|
77
61
|
});
|
|
78
|
-
|
|
79
62
|
this.device.queue.writeBuffer(this.buffer.bufferGpu, 0, this.buffer.bufferCpu, 0, newBufferLength);
|
|
80
63
|
this.currentLightsCount = lights.length;
|
|
81
64
|
}
|
|
82
|
-
|
|
83
|
-
public get lightsCount(): number {
|
|
65
|
+
get lightsCount() {
|
|
84
66
|
return this.currentLightsCount;
|
|
85
67
|
}
|
|
86
|
-
|
|
87
|
-
public destroy(): void {
|
|
68
|
+
destroy() {
|
|
88
69
|
this.buffer.bufferGpu.destroy();
|
|
89
70
|
}
|
|
90
|
-
|
|
91
|
-
private static computeBufferBytesLength(lightsCount: number): number {
|
|
71
|
+
static computeBufferBytesLength(lightsCount) {
|
|
92
72
|
return LightsBuffer.structs.lightsBuffer.lights.offset + LightsBuffer.structs.lightsBuffer.lights.stride * lightsCount;
|
|
93
73
|
}
|
|
94
74
|
}
|
|
95
|
-
|
|
96
|
-
export {
|
|
97
|
-
LightsBuffer
|
|
98
|
-
};
|
|
75
|
+
export { LightsBuffer };
|