@footgun/cobalt 0.7.0 → 0.7.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/esbuild.js CHANGED
@@ -12,5 +12,5 @@ esbuild.build({
12
12
  glsl({ minify: true })
13
13
  ],
14
14
  outfile: 'bundle.js',
15
- minify: false,
15
+ minify: true,
16
16
  })
@@ -15,6 +15,28 @@ async function main () {
15
15
  const viewportHeight = constants.GAME_HEIGHT
16
16
  Global.renderer = await Cobalt.init(canvas, viewportWidth, viewportHeight)
17
17
 
18
+ // pasting about:gpucrash into a chrome tab causes all the webgpu contexts to crash.
19
+ // useful for testing context loss
20
+ Global.renderer.device.lost.then(async (info) => {
21
+ console.warn("WebGPU device lost.", info);
22
+
23
+ Cobalt.reset(Global.renderer)
24
+
25
+ Global.renderer = await Cobalt.init(canvas, viewportWidth, viewportHeight)
26
+
27
+ const pNode = await Cobalt.initNode(Global.renderer, {
28
+ type: 'cobalt:primitives',
29
+ refs: {
30
+ // key is the var name defined in this node
31
+ // value is the var name in the cobalt resources dictionary
32
+ color: 'FRAME_TEXTURE_VIEW',
33
+ },
34
+ options: { }
35
+ })
36
+
37
+ resizeViewport(Global.renderer, window.innerWidth, window.innerHeight)
38
+ })
39
+
18
40
  // instantiate all resource nodes
19
41
 
20
42
  const pNode = await Cobalt.initNode(Global.renderer, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@footgun/cobalt",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "type": "module",
5
5
  "main": "bundle.js",
6
6
  "description": "A 2D WebGpu renderer",
@@ -1,31 +1,28 @@
1
- import bloomWGSL from './bloom.wgsl'
2
1
  import createTexture from '../create-texture.js'
3
-
2
+ import bloomWGSL from './bloom.wgsl'
4
3
 
5
4
  // ported from https://github.com/rledrin/WebGPU-Bloom
6
5
 
7
6
  // TODO: investigate dynamic ubo offsets again. I feel like that could be more efficient
8
7
  // good example of this: https://github.com/austinEng/webgpu-samples/blob/main/src/sample/animometer/main.ts
9
8
 
10
-
11
9
  const BLOOM_MIP_COUNT = 7
12
10
 
13
- const MODE_PREFILTER = 0
14
- const MODE_DOWNSAMPLE = 1
11
+ const MODE_PREFILTER = 0
12
+ const MODE_DOWNSAMPLE = 1
15
13
  const MODE_UPSAMPLE_FIRST = 2
16
- const MODE_UPSAMPLE = 3
17
-
14
+ const MODE_UPSAMPLE = 3
18
15
 
19
16
  export default {
20
17
  type: 'cobalt:bloom',
21
18
  refs: [
22
19
  { name: 'emissive', type: 'textureView', format: 'rgba16', access: 'read' },
23
- { name: 'hdr', type: 'textureView', format: 'rgba16', access: 'read' },
24
- { name: 'bloom', type: 'textureView', format: 'rgba16', access: 'readwrite' },
20
+ { name: 'hdr', type: 'textureView', format: 'rgba16', access: 'read' },
21
+ { name: 'bloom', type: 'textureView', format: 'rgba16', access: 'readwrite' },
25
22
  ],
26
23
  // @params Object cobalt renderer world object
27
24
  // @params Object options optional data passed when initing this node
28
- onInit: async function (cobalt, options={}) {
25
+ onInit: async function (cobalt, options = {}) {
29
26
  return init(cobalt, options)
30
27
  },
31
28
 
@@ -43,22 +40,21 @@ export default {
43
40
  // do whatever you need when the dimensions of the renderer change (resize textures, etc.)
44
41
  resize(cobalt, node)
45
42
  },
46
-
47
- onViewportPosition: function (cobalt, node) { },
48
- }
49
43
 
44
+ onViewportPosition: function (cobalt, node) {},
45
+ }
50
46
 
51
- function init (cobalt, nodeData) {
47
+ function init(cobalt, nodeData) {
52
48
  const { device } = cobalt
53
49
  const viewportWidth = cobalt.viewport.width
54
50
  const viewportHeight = cobalt.viewport.height
55
51
 
56
52
  const bloom_mat = {
57
53
  compute_pipeline: null,
58
- bind_group: [ ],
59
- bind_group_layout: [ ],
60
- bind_groups_textures: [ ],
61
- buffers: [ ], // buffers that we should destroy when cleaning up
54
+ bind_group: [],
55
+ bind_group_layout: [],
56
+ bind_groups_textures: [],
57
+ buffers: [], // buffers that we should destroy when cleaning up
62
58
  }
63
59
 
64
60
  const layout = device.createBindGroupLayout({
@@ -69,8 +65,8 @@ function init (cobalt, nodeData) {
69
65
  storageTexture: {
70
66
  access: 'write-only',
71
67
  format: 'rgba16float',
72
- viewDimension: '2d'
73
- }
68
+ viewDimension: '2d',
69
+ },
74
70
  },
75
71
  {
76
72
  binding: 1,
@@ -78,8 +74,8 @@ function init (cobalt, nodeData) {
78
74
  texture: {
79
75
  sampleType: 'float',
80
76
  viewDimension: '2d',
81
- multisampled: false
82
- }
77
+ multisampled: false,
78
+ },
83
79
  },
84
80
  {
85
81
  binding: 2,
@@ -87,13 +83,13 @@ function init (cobalt, nodeData) {
87
83
  texture: {
88
84
  sampleType: 'float',
89
85
  viewDimension: '2d',
90
- multisampled: false
91
- }
86
+ multisampled: false,
87
+ },
92
88
  },
93
89
  {
94
90
  binding: 3,
95
91
  visibility: GPUShaderStage.COMPUTE,
96
- sampler: { }
92
+ sampler: {},
97
93
  },
98
94
  {
99
95
  binding: 4,
@@ -101,7 +97,7 @@ function init (cobalt, nodeData) {
101
97
  buffer: {
102
98
  type: 'uniform',
103
99
  //minBindingSize: 24 // sizeOf(BloomParam)
104
- }
100
+ },
105
101
  },
106
102
  {
107
103
  binding: 5,
@@ -109,32 +105,36 @@ function init (cobalt, nodeData) {
109
105
  buffer: {
110
106
  type: 'uniform',
111
107
  //minBindingSize: 4 // sizeOf(lode_mode Param)
112
- }
108
+ },
113
109
  },
114
- ]
110
+ ],
115
111
  })
116
112
 
117
113
  bloom_mat.bind_group_layout.push(layout)
118
114
 
119
- bloom_mat.bind_groups_textures.push(createTexture(
120
- device,
121
- 'bloom downsampler image 0',
122
- viewportWidth / 2,
123
- viewportHeight / 2,
124
- BLOOM_MIP_COUNT,
125
- 'rgba16float',
126
- GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING,
127
- ))
128
-
129
- bloom_mat.bind_groups_textures.push(createTexture(
130
- device,
131
- 'bloom downsampler image 1',
132
- viewportWidth / 2,
133
- viewportHeight / 2,
134
- BLOOM_MIP_COUNT,
135
- 'rgba16float',
136
- GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING,
137
- ))
115
+ bloom_mat.bind_groups_textures.push(
116
+ createTexture(
117
+ device,
118
+ 'bloom downsampler image 0',
119
+ viewportWidth / 2,
120
+ viewportHeight / 2,
121
+ BLOOM_MIP_COUNT,
122
+ 'rgba16float',
123
+ GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING,
124
+ ),
125
+ )
126
+
127
+ bloom_mat.bind_groups_textures.push(
128
+ createTexture(
129
+ device,
130
+ 'bloom downsampler image 1',
131
+ viewportWidth / 2,
132
+ viewportHeight / 2,
133
+ BLOOM_MIP_COUNT,
134
+ 'rgba16float',
135
+ GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING,
136
+ ),
137
+ )
138
138
 
139
139
  // link bloom_mat.bind_groups_textures[2]) to bloom_mat.bloomTexture
140
140
  //bloom_mat.bind_groups_textures.push(bloom_mat.bloomTexture)
@@ -152,7 +152,7 @@ function init (cobalt, nodeData) {
152
152
  */
153
153
 
154
154
  const compute_pipeline_layout = device.createPipelineLayout({
155
- bindGroupLayouts: bloom_mat.bind_group_layout
155
+ bindGroupLayouts: bloom_mat.bind_group_layout,
156
156
  })
157
157
 
158
158
  const compute_pipeline = device.createComputePipeline({
@@ -173,9 +173,7 @@ function init (cobalt, nodeData) {
173
173
  return bloom_mat
174
174
  }
175
175
 
176
-
177
- function set_all_bind_group (cobalt, bloom_mat, node) {
178
-
176
+ function set_all_bind_group(cobalt, bloom_mat, node) {
179
177
  const { refs } = node
180
178
 
181
179
  const { device } = cobalt
@@ -185,20 +183,23 @@ function set_all_bind_group (cobalt, bloom_mat, node) {
185
183
  const bloom_knee = node.options.bloom_knee ?? 0.2
186
184
  const combine_constant = node.options.bloom_combine_constant ?? 0.68
187
185
 
188
- const dat = new Float32Array([ bloom_threshold,
189
- bloom_threshold - bloom_knee,
190
- bloom_knee * 2.0,
191
- 0.25 / bloom_knee,
192
- combine_constant,
193
- // required byte alignment bs
194
- 0, 0, 0
195
- ])
186
+ const dat = new Float32Array([
187
+ bloom_threshold,
188
+ bloom_threshold - bloom_knee,
189
+ bloom_knee * 2.0,
190
+ 0.25 / bloom_knee,
191
+ combine_constant,
192
+ // required byte alignment bs
193
+ 0,
194
+ 0,
195
+ 0,
196
+ ])
196
197
 
197
198
  const params_buf = device.createBuffer({
198
199
  label: 'bloom static parameters buffer',
199
200
  size: dat.byteLength, // vec4<f32> and f32 and u32 with 4 bytes per float32 and 4 bytes per u32
200
201
  mappedAtCreation: true,
201
- usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
202
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
202
203
  })
203
204
 
204
205
  bloom_mat.buffers.push(params_buf)
@@ -211,98 +212,117 @@ function set_all_bind_group (cobalt, bloom_mat, node) {
211
212
  bloom_mat.params_buf = params_buf
212
213
 
213
214
  // Prefilter bind group
214
- bloom_mat.bind_group.push(create_bloom_bind_group(
215
- device,
216
- bloom_mat,
217
- bloom_mat.bind_groups_textures[0].mip_view[0],
218
- refs.emissive.data.view,
219
- refs.hdr.data.view, // unused here, only for upsample passes
220
- refs.hdr.data.sampler,
221
- params_buf,
222
- MODE_PREFILTER << 16 | 0, // mode_lod value
223
- ));
224
-
225
- // Downsample bind groups
226
- for ( let i=1; i < BLOOM_MIP_COUNT; i++) {
227
- // Ping
228
- bloom_mat.bind_group.push(create_bloom_bind_group(
215
+ bloom_mat.bind_group.push(
216
+ create_bloom_bind_group(
229
217
  device,
230
218
  bloom_mat,
231
- bloom_mat.bind_groups_textures[1].mip_view[i],
232
- bloom_mat.bind_groups_textures[0].view,
219
+ bloom_mat.bind_groups_textures[0].mip_view[0],
220
+ refs.emissive.data.view,
233
221
  refs.hdr.data.view, // unused here, only for upsample passes
234
222
  refs.hdr.data.sampler,
235
223
  params_buf,
236
- MODE_DOWNSAMPLE << 16 | (i - 1), // mode_lod value
237
- ))
224
+ (MODE_PREFILTER << 16) | 0, // mode_lod value
225
+ ),
226
+ )
227
+
228
+ // Downsample bind groups
229
+ for (let i = 1; i < BLOOM_MIP_COUNT; i++) {
230
+ // Ping
231
+ bloom_mat.bind_group.push(
232
+ create_bloom_bind_group(
233
+ device,
234
+ bloom_mat,
235
+ bloom_mat.bind_groups_textures[1].mip_view[i],
236
+ bloom_mat.bind_groups_textures[0].view,
237
+ refs.hdr.data.view, // unused here, only for upsample passes
238
+ refs.hdr.data.sampler,
239
+ params_buf,
240
+ (MODE_DOWNSAMPLE << 16) | (i - 1), // mode_lod value
241
+ ),
242
+ )
238
243
 
239
244
  // Pong
240
- bloom_mat.bind_group.push(create_bloom_bind_group(
245
+ bloom_mat.bind_group.push(
246
+ create_bloom_bind_group(
247
+ device,
248
+ bloom_mat,
249
+ bloom_mat.bind_groups_textures[0].mip_view[i],
250
+ bloom_mat.bind_groups_textures[1].view,
251
+ refs.hdr.data.view, // unused here, only for upsample passes
252
+ refs.hdr.data.sampler,
253
+ params_buf,
254
+ (MODE_DOWNSAMPLE << 16) | i, // mode_lod value
255
+ ),
256
+ )
257
+ }
258
+
259
+ // First Upsample
260
+ bloom_mat.bind_group.push(
261
+ create_bloom_bind_group(
241
262
  device,
242
263
  bloom_mat,
243
- bloom_mat.bind_groups_textures[0].mip_view[i],
244
- bloom_mat.bind_groups_textures[1].view,
264
+ bloom_mat.bind_groups_textures[2].mip_view[BLOOM_MIP_COUNT - 1],
265
+ bloom_mat.bind_groups_textures[0].view,
245
266
  refs.hdr.data.view, // unused here, only for upsample passes
246
267
  refs.hdr.data.sampler,
247
268
  params_buf,
248
- MODE_DOWNSAMPLE << 16 | i, // mode_lod value
249
- ))
250
- }
251
-
252
- // First Upsample
253
- bloom_mat.bind_group.push(create_bloom_bind_group(
254
- device,
255
- bloom_mat,
256
- bloom_mat.bind_groups_textures[2].mip_view[BLOOM_MIP_COUNT - 1],
257
- bloom_mat.bind_groups_textures[0].view,
258
- refs.hdr.data.view, // unused here, only for upsample passes
259
- refs.hdr.data.sampler,
260
- params_buf,
261
- MODE_UPSAMPLE_FIRST << 16 | (BLOOM_MIP_COUNT - 2), // mode_lod value
262
- ))
269
+ (MODE_UPSAMPLE_FIRST << 16) | (BLOOM_MIP_COUNT - 2), // mode_lod value
270
+ ),
271
+ )
263
272
 
264
273
  let o = true
265
274
 
266
275
  // Upsample
267
- for (let i = BLOOM_MIP_COUNT-2; i >= 0; i--) {
276
+ for (let i = BLOOM_MIP_COUNT - 2; i >= 0; i--) {
268
277
  if (o) {
269
- bloom_mat.bind_group.push(create_bloom_bind_group(
270
- device,
271
- bloom_mat,
272
- bloom_mat.bind_groups_textures[1].mip_view[i],
273
- bloom_mat.bind_groups_textures[0].view,
274
- bloom_mat.bind_groups_textures[2].view,
275
- refs.hdr.data.sampler,
276
- params_buf,
277
- MODE_UPSAMPLE << 16 | i, // mode_lod value
278
- ))
278
+ bloom_mat.bind_group.push(
279
+ create_bloom_bind_group(
280
+ device,
281
+ bloom_mat,
282
+ bloom_mat.bind_groups_textures[1].mip_view[i],
283
+ bloom_mat.bind_groups_textures[0].view,
284
+ bloom_mat.bind_groups_textures[2].view,
285
+ refs.hdr.data.sampler,
286
+ params_buf,
287
+ (MODE_UPSAMPLE << 16) | i, // mode_lod value
288
+ ),
289
+ )
279
290
  o = false
280
291
  } else {
281
- bloom_mat.bind_group.push(create_bloom_bind_group(
282
- device,
283
- bloom_mat,
284
- bloom_mat.bind_groups_textures[2].mip_view[i],
285
- bloom_mat.bind_groups_textures[0].view,
286
- bloom_mat.bind_groups_textures[1].view,
287
- refs.hdr.data.sampler,
288
- params_buf,
289
- MODE_UPSAMPLE << 16 | i, // mode_lod value
290
- ))
292
+ bloom_mat.bind_group.push(
293
+ create_bloom_bind_group(
294
+ device,
295
+ bloom_mat,
296
+ bloom_mat.bind_groups_textures[2].mip_view[i],
297
+ bloom_mat.bind_groups_textures[0].view,
298
+ bloom_mat.bind_groups_textures[1].view,
299
+ refs.hdr.data.sampler,
300
+ params_buf,
301
+ (MODE_UPSAMPLE << 16) | i, // mode_lod value
302
+ ),
303
+ )
291
304
  o = true
292
305
  }
293
306
  }
294
307
  }
295
308
 
296
-
297
- function create_bloom_bind_group (device, bloom_mat, output_image, input_image, bloom_image, sampler, params_buf, mode_lod) {
298
-
299
- const dat2 = new Uint32Array([ mode_lod ])
309
+ function create_bloom_bind_group(
310
+ device,
311
+ bloom_mat,
312
+ output_image,
313
+ input_image,
314
+ bloom_image,
315
+ sampler,
316
+ params_buf,
317
+ mode_lod,
318
+ ) {
319
+ const dat2 = new Uint32Array([mode_lod])
300
320
 
301
321
  const lod_buf = device.createBuffer({
302
322
  label: 'bloom static mode_lod buffer',
303
323
  size: dat2.byteLength,
304
324
  mappedAtCreation: true,
305
- usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
325
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
306
326
  })
307
327
 
308
328
  bloom_mat.buffers.push(lod_buf)
@@ -317,43 +337,42 @@ function create_bloom_bind_group (device, bloom_mat, output_image, input_image,
317
337
  entries: [
318
338
  {
319
339
  binding: 0,
320
- resource: output_image
340
+ resource: output_image,
321
341
  },
322
342
  {
323
343
  binding: 1,
324
- resource: input_image
344
+ resource: input_image,
325
345
  },
326
346
  {
327
347
  binding: 2,
328
- resource: bloom_image
348
+ resource: bloom_image,
329
349
  },
330
350
  {
331
351
  binding: 3,
332
- resource: sampler
352
+ resource: sampler,
333
353
  },
334
354
  {
335
355
  binding: 4,
336
356
  resource: {
337
- buffer: params_buf
338
- }
357
+ buffer: params_buf,
358
+ },
339
359
  },
340
360
  {
341
361
  binding: 5,
342
362
  resource: {
343
- buffer: lod_buf
344
- }
345
- }
346
- ]
363
+ buffer: lod_buf,
364
+ },
365
+ },
366
+ ],
347
367
  })
348
368
  }
349
369
 
350
-
351
- function draw (cobalt, bloom_mat, commandEncoder) {
370
+ function draw(cobalt, bloom_mat, commandEncoder) {
352
371
  const MODE_PREFILTER = 0
353
372
  const MODE_DOWNSAMPLE = 1
354
373
  const MODE_UPSAMPLE_FIRST = 2
355
374
  const MODE_UPSAMPLE = 3
356
-
375
+
357
376
  let bind_group_index = 0
358
377
 
359
378
  const compute_pass = commandEncoder.beginComputePass({
@@ -362,7 +381,6 @@ function draw (cobalt, bloom_mat, commandEncoder) {
362
381
 
363
382
  compute_pass.setPipeline(bloom_mat.compute_pipeline)
364
383
 
365
-
366
384
  // PreFilter
367
385
  compute_pass.setBindGroup(0, bloom_mat.bind_group[bind_group_index])
368
386
  bind_group_index += 1
@@ -372,9 +390,9 @@ function draw (cobalt, bloom_mat, commandEncoder) {
372
390
  compute_pass.dispatchWorkgroups(mip_size.width / 8 + 1, mip_size.height / 4 + 1, 1)
373
391
 
374
392
  // Downsample
375
- for (let i=1; i < BLOOM_MIP_COUNT; i++) {
393
+ for (let i = 1; i < BLOOM_MIP_COUNT; i++) {
376
394
  mip_size = get_mip_size(i, bloom_mat.bind_groups_textures[0])
377
-
395
+
378
396
  // Ping
379
397
  compute_pass.setBindGroup(0, bloom_mat.bind_group[bind_group_index])
380
398
  bind_group_index += 1
@@ -386,33 +404,29 @@ function draw (cobalt, bloom_mat, commandEncoder) {
386
404
  compute_pass.dispatchWorkgroups(mip_size.width / 8 + 1, mip_size.height / 4 + 1, 1)
387
405
  }
388
406
 
389
-
390
407
  // First Upsample
391
408
  compute_pass.setBindGroup(0, bloom_mat.bind_group[bind_group_index])
392
409
  bind_group_index += 1
393
410
  mip_size = get_mip_size(BLOOM_MIP_COUNT - 1, bloom_mat.bind_groups_textures[2])
394
411
  compute_pass.dispatchWorkgroups(mip_size.width / 8 + 1, mip_size.height / 4 + 1, 1)
395
412
 
396
-
397
413
  // Upsample
398
- for (let i=BLOOM_MIP_COUNT - 2; i >= 0; i--) {
414
+ for (let i = BLOOM_MIP_COUNT - 2; i >= 0; i--) {
399
415
  mip_size = get_mip_size(i, bloom_mat.bind_groups_textures[2])
400
-
416
+
401
417
  compute_pass.setBindGroup(0, bloom_mat.bind_group[bind_group_index])
402
418
  bind_group_index += 1
403
419
  compute_pass.dispatchWorkgroups(mip_size.width / 8 + 1, mip_size.height / 4 + 1, 1)
404
420
  }
405
421
 
406
-
407
422
  compute_pass.end()
408
423
  }
409
424
 
410
-
411
- function get_mip_size (current_mip, texture) {
425
+ function get_mip_size(current_mip, texture) {
412
426
  let width = texture.size.width
413
427
  let height = texture.size.height
414
428
 
415
- for (let i =0; i < current_mip; i++) {
429
+ for (let i = 0; i < current_mip; i++) {
416
430
  width /= 2
417
431
  height /= 2
418
432
  }
@@ -420,31 +434,34 @@ function get_mip_size (current_mip, texture) {
420
434
  return { width, height, depthOrArrayLayers: 1 }
421
435
  }
422
436
 
423
-
424
- function resize (cobalt, nodeData) {
437
+ function resize(cobalt, nodeData) {
425
438
  const { device } = cobalt
426
439
  const bloom_mat = nodeData.data
427
440
  destroy(bloom_mat)
428
441
 
429
- bloom_mat.bind_groups_textures.push(createTexture(
430
- device,
431
- 'bloom downsampler image 0',
432
- cobalt.viewport.width / 2,
433
- cobalt.viewport.height / 2,
434
- BLOOM_MIP_COUNT,
435
- 'rgba16float',
436
- GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING,
437
- ))
438
-
439
- bloom_mat.bind_groups_textures.push(createTexture(
440
- device,
441
- 'bloom downsampler image 1',
442
- cobalt.viewport.width / 2,
443
- cobalt.viewport.height / 2,
444
- BLOOM_MIP_COUNT,
445
- 'rgba16float',
446
- GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING,
447
- ))
442
+ bloom_mat.bind_groups_textures.push(
443
+ createTexture(
444
+ device,
445
+ 'bloom downsampler image 0',
446
+ cobalt.viewport.width / 2,
447
+ cobalt.viewport.height / 2,
448
+ BLOOM_MIP_COUNT,
449
+ 'rgba16float',
450
+ GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING,
451
+ ),
452
+ )
453
+
454
+ bloom_mat.bind_groups_textures.push(
455
+ createTexture(
456
+ device,
457
+ 'bloom downsampler image 1',
458
+ cobalt.viewport.width / 2,
459
+ cobalt.viewport.height / 2,
460
+ BLOOM_MIP_COUNT,
461
+ 'rgba16float',
462
+ GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING,
463
+ ),
464
+ )
448
465
 
449
466
  // link bloom_mat.bind_groups_textures[2]) to bloom_mat.bloomTexture
450
467
  bloom_mat.bind_groups_textures.push(nodeData.refs.bloom.data)
@@ -463,13 +480,10 @@ function resize (cobalt, nodeData) {
463
480
  set_all_bind_group(cobalt, bloom_mat, nodeData)
464
481
  }
465
482
 
483
+ function destroy(bloom_mat) {
484
+ for (const t of bloom_mat.bind_groups_textures) t.texture.destroy()
466
485
 
467
- function destroy (bloom_mat) {
468
- for (const t of bloom_mat.bind_groups_textures)
469
- t.texture.destroy()
470
-
471
- for (const b of bloom_mat.buffers)
472
- b.destroy()
486
+ for (const b of bloom_mat.buffers) b.destroy()
473
487
 
474
488
  bloom_mat.buffers.length = 0
475
489