@footgun/cobalt 0.6.14 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/bundle.js +1318 -1304
  3. package/examples/01-primitives/index.html +1 -1
  4. package/examples/02-sprites/entity-sprite.js +10 -15
  5. package/examples/02-sprites/hdr.html +321 -0
  6. package/examples/02-sprites/index.html +21 -120
  7. package/examples/02-sprites/system-renderer.js +2 -2
  8. package/examples/03-tiles/index.html +87 -32
  9. package/examples/03-tiles/system-renderer.js +2 -2
  10. package/examples/04-overlay/index.html +178 -21
  11. package/examples/05-bloom/index.html +23 -23
  12. package/examples/05-bloom/system-renderer.js +2 -2
  13. package/examples/06-displacement/index.html +20 -112
  14. package/examples/06-displacement/system-renderer.js +2 -2
  15. package/examples/08-light/index.html +51 -123
  16. package/package.json +1 -1
  17. package/src/cobalt.js +8 -8
  18. package/src/sprite/public-api.js +57 -177
  19. package/src/sprite/sprite.js +301 -177
  20. package/src/sprite/sprite.wgsl +68 -87
  21. package/src/sprite-hdr/public-api.js +95 -0
  22. package/src/sprite-hdr/sprite.js +414 -0
  23. package/src/sprite-hdr/sprite.wgsl +101 -0
  24. package/src/{sprite → spritesheet}/create-sprite-quads.js +11 -11
  25. package/src/{sprite → spritesheet}/read-spritesheet.js +62 -28
  26. package/src/spritesheet/spritesheet.js +75 -0
  27. package/src/{tile → tile-hdr}/atlas.js +5 -3
  28. package/src/{tile → tile-hdr}/tile.js +15 -6
  29. package/examples/04-overlay/deps.js +0 -1
  30. package/src/overlay/constants.js +0 -1
  31. package/src/overlay/overlay.js +0 -343
  32. package/src/overlay/overlay.wgsl +0 -88
  33. package/src/sprite/constants.js +0 -1
  34. package/src/sprite/sorted-binary-insert.js +0 -45
  35. package/src/sprite/spritesheet.js +0 -215
  36. /package/examples/02-sprites/{Game.js → Global.js} +0 -0
  37. /package/examples/03-tiles/{Game.js → Global.js} +0 -0
  38. /package/examples/05-bloom/{Game.js → Global.js} +0 -0
  39. /package/examples/06-displacement/{Game.js → Global.js} +0 -0
  40. /package/examples/08-light/{Game.js → Global.js} +0 -0
  41. /package/src/{tile → tile-hdr}/tile.wgsl +0 -0
package/bundle.js CHANGED
@@ -7852,13 +7852,12 @@ function resize2(cobalt, node) {
7852
7852
  });
7853
7853
  }
7854
7854
 
7855
- // src/sprite/public-api.js
7855
+ // src/sprite-hdr/public-api.js
7856
7856
  var public_api_exports = {};
7857
7857
  __export(public_api_exports, {
7858
7858
  addSprite: () => addSprite,
7859
7859
  clear: () => clear,
7860
7860
  removeSprite: () => removeSprite,
7861
- setSprite: () => setSprite,
7862
7861
  setSpriteName: () => setSpriteName,
7863
7862
  setSpriteOpacity: () => setSpriteOpacity,
7864
7863
  setSpritePosition: () => setSpritePosition,
@@ -7867,848 +7866,165 @@ __export(public_api_exports, {
7867
7866
  setSpriteTint: () => setSpriteTint
7868
7867
  });
7869
7868
 
7870
- // src/sprite/constants.js
7871
- var FLOAT32S_PER_SPRITE = 12;
7872
-
7873
- // src/sprite/sorted-binary-insert.js
7874
- function sortedBinaryInsert(spriteZIndex, spriteType, renderPass) {
7875
- if (renderPass.spriteCount === 0)
7876
- return 0;
7877
- let low = 0;
7878
- let high = renderPass.spriteCount - 1;
7879
- const order = spriteZIndex << 16 & 16711680 | spriteType & 65535;
7880
- while (low <= high) {
7881
- const lowOrder = renderPass.spriteData[low * FLOAT32S_PER_SPRITE + 11];
7882
- if (order <= lowOrder)
7883
- return low;
7884
- const highOrder = renderPass.spriteData[high * FLOAT32S_PER_SPRITE + 11];
7885
- if (order >= highOrder)
7886
- return high + 1;
7887
- const mid = Math.floor((low + high) / 2);
7888
- const midOrder = renderPass.spriteData[mid * FLOAT32S_PER_SPRITE + 11];
7889
- if (order === midOrder)
7890
- return mid + 1;
7891
- if (order > midOrder)
7892
- low = mid + 1;
7893
- else
7894
- high = mid - 1;
7895
- }
7896
- return low;
7897
- }
7898
-
7899
7869
  // src/uuid.js
7900
7870
  function _uuid() {
7901
7871
  return Math.ceil(Math.random() * (Number.MAX_SAFE_INTEGER - 10));
7902
7872
  }
7903
7873
 
7904
- // src/sprite/public-api.js
7905
- function addSprite(cobalt, renderPass, name, position, scale, tint, opacity, rotation, zIndex) {
7906
- const spritesheet = renderPass.refs.spritesheet.data.spritesheet;
7907
- renderPass = renderPass.data;
7908
- const spriteType = spritesheet.locations.indexOf(name);
7909
- const insertIdx = sortedBinaryInsert(zIndex, spriteType, renderPass);
7910
- const offset = (insertIdx + 1) * FLOAT32S_PER_SPRITE;
7911
- renderPass.spriteData.set(
7912
- renderPass.spriteData.subarray(insertIdx * FLOAT32S_PER_SPRITE, renderPass.spriteCount * FLOAT32S_PER_SPRITE),
7913
- offset
7914
- );
7915
- copySpriteDataToBuffer(renderPass, spritesheet, insertIdx, name, position, scale, tint, opacity, rotation, zIndex);
7916
- for (const [spriteId2, idx] of renderPass.spriteIndices)
7917
- if (idx >= insertIdx)
7918
- renderPass.spriteIndices.set(spriteId2, idx + 1);
7919
- const spriteId = _uuid();
7920
- renderPass.spriteIndices.set(spriteId, insertIdx);
7921
- renderPass.spriteCount++;
7922
- renderPass.dirty = true;
7923
- return spriteId;
7924
- }
7925
- function removeSprite(cobalt, renderPass, spriteId) {
7926
- renderPass = renderPass.data;
7927
- const removeIdx = renderPass.spriteIndices.get(spriteId);
7928
- for (const [spriteId2, idx] of renderPass.spriteIndices)
7929
- if (idx > removeIdx)
7930
- renderPass.spriteIndices.set(spriteId2, idx - 1);
7931
- let offset = removeIdx * FLOAT32S_PER_SPRITE;
7932
- renderPass.spriteData.set(
7933
- renderPass.spriteData.subarray((removeIdx + 1) * FLOAT32S_PER_SPRITE, renderPass.spriteCount * FLOAT32S_PER_SPRITE),
7934
- offset
7935
- );
7936
- renderPass.spriteIndices.delete(spriteId);
7937
- renderPass.spriteCount--;
7938
- renderPass.dirty = true;
7939
- }
7940
- function clear(cobalt, renderPass) {
7941
- renderPass = renderPass.data;
7942
- renderPass.spriteIndices.clear();
7943
- renderPass.spriteCount = 0;
7944
- renderPass.instancedDrawCallCount = 0;
7945
- renderPass.dirty = true;
7946
- }
7947
- function setSpriteName(cobalt, renderPass, spriteId, name, scale) {
7948
- const spritesheet = renderPass.refs.spritesheet.data.spritesheet;
7949
- renderPass = renderPass.data;
7950
- const spriteType = spritesheet.locations.indexOf(name);
7951
- const SPRITE_WIDTH = spritesheet.spriteMeta[name].w;
7952
- const SPRITE_HEIGHT = spritesheet.spriteMeta[name].h;
7953
- const spriteIdx = renderPass.spriteIndices.get(spriteId);
7954
- const offset = spriteIdx * FLOAT32S_PER_SPRITE;
7955
- renderPass.spriteData[offset + 2] = SPRITE_WIDTH * scale[0];
7956
- renderPass.spriteData[offset + 3] = SPRITE_HEIGHT * scale[1];
7957
- const zIndex = renderPass.spriteData[offset + 11] >> 16 & 255;
7958
- const sortValue = zIndex << 16 & 16711680 | spriteType & 65535;
7959
- renderPass.spriteData[offset + 11] = sortValue;
7960
- renderPass.dirty = true;
7961
- }
7962
- function setSpritePosition(cobalt, renderPass, spriteId, position) {
7963
- renderPass = renderPass.data;
7964
- const spriteIdx = renderPass.spriteIndices.get(spriteId);
7965
- const offset = spriteIdx * FLOAT32S_PER_SPRITE;
7966
- renderPass.spriteData[offset] = position[0];
7967
- renderPass.spriteData[offset + 1] = position[1];
7968
- renderPass.dirty = true;
7969
- }
7970
- function setSpriteTint(cobalt, renderPass, spriteId, tint) {
7971
- renderPass = renderPass.data;
7972
- const spriteIdx = renderPass.spriteIndices.get(spriteId);
7973
- const offset = spriteIdx * FLOAT32S_PER_SPRITE;
7974
- renderPass.spriteData[offset + 4] = tint[0];
7975
- renderPass.spriteData[offset + 5] = tint[1];
7976
- renderPass.spriteData[offset + 6] = tint[2];
7977
- renderPass.spriteData[offset + 7] = tint[3];
7978
- renderPass.dirty = true;
7979
- }
7980
- function setSpriteOpacity(cobalt, renderPass, spriteId, opacity) {
7981
- renderPass = renderPass.data;
7982
- const spriteIdx = renderPass.spriteIndices.get(spriteId);
7983
- const offset = spriteIdx * FLOAT32S_PER_SPRITE;
7984
- renderPass.spriteData[offset + 8] = opacity;
7985
- renderPass.dirty = true;
7986
- }
7987
- function setSpriteRotation(cobalt, renderPass, spriteId, rotation) {
7988
- renderPass = renderPass.data;
7989
- const spriteIdx = renderPass.spriteIndices.get(spriteId);
7990
- const offset = spriteIdx * FLOAT32S_PER_SPRITE;
7991
- renderPass.spriteData[offset + 9] = rotation;
7992
- renderPass.dirty = true;
7993
- }
7994
- function setSpriteScale(cobalt, renderPass, spriteId, name, scale) {
7995
- const spritesheet = renderPass.refs.spritesheet.data.spritesheet;
7996
- renderPass = renderPass.data;
7997
- const spriteIdx = renderPass.spriteIndices.get(spriteId);
7998
- const offset = spriteIdx * FLOAT32S_PER_SPRITE;
7999
- const SPRITE_WIDTH = spritesheet.spriteMeta[name].w;
8000
- const SPRITE_HEIGHT = spritesheet.spriteMeta[name].h;
8001
- renderPass.spriteData[offset + 2] = SPRITE_WIDTH * scale[0];
8002
- renderPass.spriteData[offset + 3] = SPRITE_HEIGHT * scale[1];
8003
- renderPass.dirty = true;
8004
- }
8005
- function setSprite(cobalt, renderPass, spriteId, name, position, scale, tint, opacity, rotation, zIndex) {
8006
- const spritesheet = renderPass.refs.spritesheet.data.spritesheet;
8007
- renderPass = renderPass.data;
8008
- const spriteIdx = renderPass.spriteIndices.get(spriteId);
8009
- copySpriteDataToBuffer(renderPass, spritesheet, spriteIdx, name, position, scale, tint, opacity, rotation, zIndex);
8010
- renderPass.dirty = true;
8011
- }
8012
- function copySpriteDataToBuffer(renderPass, spritesheet, insertIdx, name, position, scale, tint, opacity, rotation, zIndex) {
8013
- if (!spritesheet.spriteMeta[name])
8014
- throw new Error(`Sprite name ${name} could not be found in the spritesheet metaData`);
8015
- const offset = insertIdx * FLOAT32S_PER_SPRITE;
8016
- const SPRITE_WIDTH = spritesheet.spriteMeta[name].w;
8017
- const SPRITE_HEIGHT = spritesheet.spriteMeta[name].h;
8018
- const spriteType = spritesheet.locations.indexOf(name);
8019
- const sortValue = zIndex << 16 & 16711680 | spriteType & 65535;
8020
- renderPass.spriteData[offset] = position[0];
8021
- renderPass.spriteData[offset + 1] = position[1];
8022
- renderPass.spriteData[offset + 2] = SPRITE_WIDTH * scale[0];
8023
- renderPass.spriteData[offset + 3] = SPRITE_HEIGHT * scale[1];
8024
- renderPass.spriteData[offset + 4] = tint[0];
8025
- renderPass.spriteData[offset + 5] = tint[1];
8026
- renderPass.spriteData[offset + 6] = tint[2];
8027
- renderPass.spriteData[offset + 7] = tint[3];
8028
- renderPass.spriteData[offset + 8] = opacity;
8029
- renderPass.spriteData[offset + 9] = rotation;
8030
- renderPass.spriteData[offset + 11] = sortValue;
8031
- }
8032
-
8033
- // src/sprite/sprite.js
8034
- var sprite_default = {
8035
- type: "cobalt:sprite",
8036
- refs: [
8037
- { name: "spritesheet", type: "customResource", access: "read" },
8038
- { name: "hdr", type: "textureView", format: "rgba16float", access: "write" },
8039
- { name: "emissive", type: "textureView", format: "rgba16float", access: "write" }
8040
- ],
8041
- // cobalt event handling functions
8042
- // @params Object cobalt renderer world object
8043
- // @params Object options optional data passed when initing this node
8044
- onInit: async function(cobalt, options = {}) {
8045
- return init3(cobalt, options);
8046
- },
8047
- onRun: function(cobalt, node, webGpuCommandEncoder) {
8048
- draw3(cobalt, node, webGpuCommandEncoder);
8049
- },
8050
- onDestroy: function(cobalt, node) {
8051
- destroy2(node);
8052
- },
8053
- onResize: function(cobalt, node) {
8054
- },
8055
- onViewportPosition: function(cobalt, node) {
8056
- },
8057
- // optional
8058
- customFunctions: {
8059
- ...public_api_exports
8060
- }
8061
- };
8062
- async function init3(cobalt, nodeData) {
8063
- const { device } = cobalt;
8064
- const MAX_SPRITE_COUNT = 16192;
8065
- const numInstances = MAX_SPRITE_COUNT;
8066
- const translateFloatCount = 2;
8067
- const translateSize = Float32Array.BYTES_PER_ELEMENT * translateFloatCount;
8068
- const scaleFloatCount = 2;
8069
- const scaleSize = Float32Array.BYTES_PER_ELEMENT * scaleFloatCount;
8070
- const tintFloatCount = 4;
8071
- const tintSize = Float32Array.BYTES_PER_ELEMENT * tintFloatCount;
8072
- const opacityFloatCount = 4;
8073
- const opacitySize = Float32Array.BYTES_PER_ELEMENT * opacityFloatCount;
8074
- const spriteBuffer = device.createBuffer({
8075
- size: (translateSize + scaleSize + tintSize + opacitySize) * numInstances,
8076
- // 4x4 matrix with 4 bytes per float32, per instance
8077
- usage: GPUBufferUsage.VERTEX | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
8078
- //mappedAtCreation: true,
8079
- });
8080
- const spritesheet = nodeData.refs.spritesheet.data;
8081
- const bindGroup = device.createBindGroup({
8082
- layout: nodeData.refs.spritesheet.data.bindGroupLayout,
8083
- entries: [
8084
- {
8085
- binding: 0,
8086
- resource: {
8087
- buffer: spritesheet.uniformBuffer
8088
- }
8089
- },
8090
- {
8091
- binding: 1,
8092
- resource: spritesheet.colorTexture.view
8093
- },
8094
- {
8095
- binding: 2,
8096
- resource: spritesheet.colorTexture.sampler
8097
- },
8098
- {
8099
- binding: 3,
8100
- resource: {
8101
- buffer: spriteBuffer
8102
- }
8103
- },
8104
- {
8105
- binding: 4,
8106
- resource: spritesheet.emissiveTexture.view
8107
- }
8108
- ]
8109
- });
8110
- return {
8111
- // instancedDrawCalls is used to actually perform draw calls within the render pass
8112
- // layout is interleaved with baseVtxIdx (the sprite type), and instanceCount (how many sprites)
8113
- // [
8114
- // baseVtxIdx0, instanceCount0,
8115
- // baseVtxIdx1, instanceCount1,
8116
- // ...
8117
- // ]
8118
- instancedDrawCalls: new Uint32Array(MAX_SPRITE_COUNT * 2),
8119
- instancedDrawCallCount: 0,
8120
- bindGroup,
8121
- spriteBuffer,
8122
- // actual sprite instance data. ordered by layer, then sprite type
8123
- // this is used to update the spriteBuffer.
8124
- spriteData: new Float32Array(MAX_SPRITE_COUNT * FLOAT32S_PER_SPRITE),
8125
- spriteCount: 0,
8126
- spriteIndices: /* @__PURE__ */ new Map(),
8127
- // key is spriteId, value is insert index of the sprite. e.g., 0 means 1st sprite , 1 means 2nd sprite, etc.
8128
- // when a sprite is changed the renderpass is dirty, and should have it's instance data copied to the gpu
8129
- dirty: false
7874
+ // node_modules/wgpu-matrix/dist/3.x/wgpu-matrix.module.js
7875
+ function wrapConstructor(OriginalConstructor, modifier) {
7876
+ return class extends OriginalConstructor {
7877
+ constructor(...args) {
7878
+ super(...args);
7879
+ modifier(this);
7880
+ }
8130
7881
  };
8131
7882
  }
8132
- function draw3(cobalt, node, commandEncoder) {
8133
- const { device } = cobalt;
8134
- const loadOp = node.options.loadOp || "load";
8135
- if (node.data.dirty) {
8136
- _rebuildSpriteDrawCalls(node.data);
8137
- node.data.dirty = false;
7883
+ var ZeroArray = wrapConstructor(Array, (a) => a.fill(0));
7884
+ var EPSILON = 1e-6;
7885
+ function getAPIImpl$5(Ctor) {
7886
+ function create(x = 0, y = 0) {
7887
+ const newDst = new Ctor(2);
7888
+ if (x !== void 0) {
7889
+ newDst[0] = x;
7890
+ if (y !== void 0) {
7891
+ newDst[1] = y;
7892
+ }
7893
+ }
7894
+ return newDst;
8138
7895
  }
8139
- if (node.data.spriteCount > 0) {
8140
- const writeLength = node.data.spriteCount * FLOAT32S_PER_SPRITE * Float32Array.BYTES_PER_ELEMENT;
8141
- device.queue.writeBuffer(node.data.spriteBuffer, 0, node.data.spriteData.buffer, 0, writeLength);
7896
+ const fromValues = create;
7897
+ function set(x, y, dst) {
7898
+ const newDst = dst ?? new Ctor(2);
7899
+ newDst[0] = x;
7900
+ newDst[1] = y;
7901
+ return newDst;
8142
7902
  }
8143
- const renderpass = commandEncoder.beginRenderPass({
8144
- label: "sprite",
8145
- colorAttachments: [
8146
- // color
8147
- {
8148
- view: node.refs.hdr.data.view,
8149
- clearValue: cobalt.clearValue,
8150
- loadOp,
8151
- storeOp: "store"
8152
- },
8153
- // emissive
8154
- {
8155
- view: node.refs.emissive.data.view,
8156
- clearValue: cobalt.clearValue,
8157
- loadOp: "clear",
8158
- storeOp: "store"
8159
- }
8160
- ]
8161
- });
8162
- renderpass.setPipeline(node.refs.spritesheet.data.pipeline);
8163
- renderpass.setBindGroup(0, node.data.bindGroup);
8164
- renderpass.setVertexBuffer(0, node.refs.spritesheet.data.quads.buffer);
8165
- const vertexCount = 6;
8166
- let baseInstanceIdx = 0;
8167
- for (let i = 0; i < node.data.instancedDrawCallCount; i++) {
8168
- const baseVertexIdx = node.data.instancedDrawCalls[i * 2] * vertexCount;
8169
- const instanceCount = node.data.instancedDrawCalls[i * 2 + 1];
8170
- renderpass.draw(vertexCount, instanceCount, baseVertexIdx, baseInstanceIdx);
8171
- baseInstanceIdx += instanceCount;
7903
+ function ceil(v, dst) {
7904
+ const newDst = dst ?? new Ctor(2);
7905
+ newDst[0] = Math.ceil(v[0]);
7906
+ newDst[1] = Math.ceil(v[1]);
7907
+ return newDst;
8172
7908
  }
8173
- renderpass.end();
8174
- }
8175
- function _rebuildSpriteDrawCalls(renderPass) {
8176
- let currentSpriteType = -1;
8177
- let instanceCount = 0;
8178
- renderPass.instancedDrawCallCount = 0;
8179
- for (let i = 0; i < renderPass.spriteCount; i++) {
8180
- const spriteType = renderPass.spriteData[i * FLOAT32S_PER_SPRITE + 11] & 65535;
8181
- if (spriteType !== currentSpriteType) {
8182
- if (instanceCount > 0) {
8183
- renderPass.instancedDrawCalls[renderPass.instancedDrawCallCount * 2] = currentSpriteType;
8184
- renderPass.instancedDrawCalls[renderPass.instancedDrawCallCount * 2 + 1] = instanceCount;
8185
- renderPass.instancedDrawCallCount++;
8186
- }
8187
- currentSpriteType = spriteType;
8188
- instanceCount = 0;
8189
- }
8190
- instanceCount++;
8191
- }
8192
- if (instanceCount > 0) {
8193
- renderPass.instancedDrawCalls[renderPass.instancedDrawCallCount * 2] = currentSpriteType;
8194
- renderPass.instancedDrawCalls[renderPass.instancedDrawCallCount * 2 + 1] = instanceCount;
8195
- renderPass.instancedDrawCallCount++;
7909
+ function floor(v, dst) {
7910
+ const newDst = dst ?? new Ctor(2);
7911
+ newDst[0] = Math.floor(v[0]);
7912
+ newDst[1] = Math.floor(v[1]);
7913
+ return newDst;
8196
7914
  }
8197
- }
8198
- function destroy2(node) {
8199
- node.data.instancedDrawCalls = null;
8200
- node.data.bindGroup = null;
8201
- node.data.spriteBuffer.destroy();
8202
- node.data.spriteBuffer = null;
8203
- node.data.spriteData = null;
8204
- node.data.spriteIndices.clear();
8205
- node.data.spriteIndices = null;
8206
- }
8207
-
8208
- // src/tile/tile.js
8209
- var tile_default = {
8210
- type: "cobalt:tile",
8211
- refs: [
8212
- { name: "tileAtlas", type: "textureView", format: "rgba8unorm", access: "write" }
8213
- ],
8214
- // @params Object cobalt renderer world object
8215
- // @params Object options optional data passed when initing this node
8216
- onInit: async function(cobalt, options = {}) {
8217
- return init4(cobalt, options);
8218
- },
8219
- onRun: function(cobalt, node, webGpuCommandEncoder) {
8220
- draw4(cobalt, node, webGpuCommandEncoder);
8221
- },
8222
- onDestroy: function(cobalt, node) {
8223
- destroy3(node);
8224
- },
8225
- onResize: function(cobalt, node) {
8226
- },
8227
- onViewportPosition: function(cobalt, node) {
8228
- },
8229
- // optional
8230
- customFunctions: {
8231
- setTexture: async function(cobalt, node, texture) {
8232
- const { canvas, device } = cobalt;
8233
- destroy3(node);
8234
- const format = node.options.format || "rgba8unorm";
8235
- let material;
8236
- if (canvas) {
8237
- node.options.textureUrl = texture;
8238
- material = await createTextureFromUrl(cobalt, "tile map", texture, format);
8239
- } else {
8240
- material = await createTextureFromBuffer(cobalt, "tile map", texture, format);
8241
- }
8242
- const bindGroup = device.createBindGroup({
8243
- layout: node.refs.tileAtlas.data.tileBindGroupLayout,
8244
- entries: [
8245
- {
8246
- binding: 0,
8247
- resource: {
8248
- buffer: node.data.uniformBuffer
8249
- }
8250
- },
8251
- {
8252
- binding: 1,
8253
- resource: material.view
8254
- },
8255
- {
8256
- binding: 2,
8257
- resource: material.sampler
8258
- }
8259
- ]
8260
- });
8261
- node.data.bindGroup = bindGroup;
8262
- node.data.material = material;
8263
- }
7915
+ function round2(v, dst) {
7916
+ const newDst = dst ?? new Ctor(2);
7917
+ newDst[0] = Math.round(v[0]);
7918
+ newDst[1] = Math.round(v[1]);
7919
+ return newDst;
8264
7920
  }
8265
- };
8266
- async function init4(cobalt, nodeData) {
8267
- const { canvas, device } = cobalt;
8268
- let material;
8269
- const format = nodeData.options.format || "rgba8unorm";
8270
- if (canvas) {
8271
- material = await createTextureFromUrl(cobalt, "tile map", nodeData.options.textureUrl, format);
8272
- } else {
8273
- material = await createTextureFromBuffer(cobalt, "tile map", nodeData.options.texture, format);
7921
+ function clamp(v, min2 = 0, max2 = 1, dst) {
7922
+ const newDst = dst ?? new Ctor(2);
7923
+ newDst[0] = Math.min(max2, Math.max(min2, v[0]));
7924
+ newDst[1] = Math.min(max2, Math.max(min2, v[1]));
7925
+ return newDst;
8274
7926
  }
8275
- const dat = new Float32Array([nodeData.options.scrollScale, nodeData.options.scrollScale]);
8276
- const usage = GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST;
8277
- const descriptor = {
8278
- size: dat.byteLength,
8279
- usage,
8280
- // make this memory space accessible from the CPU (host visible)
8281
- mappedAtCreation: true
8282
- };
8283
- const uniformBuffer = device.createBuffer(descriptor);
8284
- new Float32Array(uniformBuffer.getMappedRange()).set(dat);
8285
- uniformBuffer.unmap();
8286
- const bindGroup = device.createBindGroup({
8287
- layout: nodeData.refs.tileAtlas.data.tileBindGroupLayout,
8288
- entries: [
8289
- {
8290
- binding: 0,
8291
- resource: {
8292
- buffer: uniformBuffer
8293
- }
8294
- },
8295
- {
8296
- binding: 1,
8297
- resource: material.view
8298
- },
8299
- {
8300
- binding: 2,
8301
- resource: material.sampler
8302
- }
8303
- ]
8304
- });
8305
- return {
8306
- bindGroup,
8307
- material,
8308
- uniformBuffer,
8309
- scrollScale: nodeData.options.scrollScale
8310
- };
8311
- }
8312
- function draw4(cobalt, nodeData, commandEncoder) {
8313
- const { device } = cobalt;
8314
- const loadOp = nodeData.options.loadOp || "load";
8315
- const renderpass = commandEncoder.beginRenderPass({
8316
- label: "tile",
8317
- colorAttachments: [
8318
- {
8319
- view: nodeData.refs.hdr.data.view,
8320
- clearValue: cobalt.clearValue,
8321
- loadOp,
8322
- storeOp: "store"
8323
- }
8324
- ]
8325
- });
8326
- const tileAtlas = nodeData.refs.tileAtlas.data;
8327
- renderpass.setPipeline(tileAtlas.pipeline);
8328
- renderpass.setBindGroup(0, nodeData.data.bindGroup);
8329
- renderpass.setBindGroup(1, tileAtlas.atlasBindGroup);
8330
- renderpass.draw(3);
8331
- renderpass.end();
8332
- }
8333
- function destroy3(nodeData) {
8334
- nodeData.data.material.texture.destroy();
8335
- nodeData.data.material.texture = void 0;
8336
- }
8337
-
8338
- // src/displacement/triangles-buffer.ts
8339
- var TrianglesBuffer = class {
8340
- device;
8341
- floatsPerSprite = 6;
8342
- // vec2(translate) + vec2(scale) + rotation + opacity
8343
- bufferGpu;
8344
- bufferNeedsUpdate = false;
8345
- sprites = /* @__PURE__ */ new Map();
8346
- get spriteCount() {
8347
- return this.sprites.size;
7927
+ function add(a, b, dst) {
7928
+ const newDst = dst ?? new Ctor(2);
7929
+ newDst[0] = a[0] + b[0];
7930
+ newDst[1] = a[1] + b[1];
7931
+ return newDst;
8348
7932
  }
8349
- constructor(params) {
8350
- this.device = params.device;
8351
- this.bufferGpu = this.device.createBuffer({
8352
- size: params.maxSpriteCount * this.floatsPerSprite * Float32Array.BYTES_PER_ELEMENT,
8353
- usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
8354
- });
7933
+ function addScaled(a, b, scale2, dst) {
7934
+ const newDst = dst ?? new Ctor(2);
7935
+ newDst[0] = a[0] + b[0] * scale2;
7936
+ newDst[1] = a[1] + b[1] * scale2;
7937
+ return newDst;
8355
7938
  }
8356
- destroy() {
8357
- this.bufferGpu.destroy;
7939
+ function angle(a, b) {
7940
+ const ax = a[0];
7941
+ const ay = a[1];
7942
+ const bx = b[0];
7943
+ const by = b[1];
7944
+ const mag1 = Math.sqrt(ax * ax + ay * ay);
7945
+ const mag2 = Math.sqrt(bx * bx + by * by);
7946
+ const mag = mag1 * mag2;
7947
+ const cosine = mag && dot(a, b) / mag;
7948
+ return Math.acos(cosine);
8358
7949
  }
8359
- update() {
8360
- if (this.bufferNeedsUpdate) {
8361
- const bufferData = [];
8362
- for (const sprite of this.sprites.values()) {
8363
- bufferData.push(...sprite);
8364
- }
8365
- ;
8366
- const buffer = new Float32Array(bufferData);
8367
- this.device.queue.writeBuffer(this.bufferGpu, 0, buffer);
8368
- }
7950
+ function subtract(a, b, dst) {
7951
+ const newDst = dst ?? new Ctor(2);
7952
+ newDst[0] = a[0] - b[0];
7953
+ newDst[1] = a[1] - b[1];
7954
+ return newDst;
8369
7955
  }
8370
- addTriangle(triangleVertices) {
8371
- const triangleId = _uuid();
8372
- if (this.sprites.has(triangleId)) {
8373
- throw new Error(`Duplicate triangle "${triangleId}".`);
8374
- }
8375
- const triangleData = this.buildTriangleData(triangleVertices);
8376
- this.sprites.set(triangleId, triangleData);
8377
- this.bufferNeedsUpdate = true;
8378
- return triangleId;
7956
+ const sub = subtract;
7957
+ function equalsApproximately(a, b) {
7958
+ return Math.abs(a[0] - b[0]) < EPSILON && Math.abs(a[1] - b[1]) < EPSILON;
8379
7959
  }
8380
- removeTriangle(triangleId) {
8381
- if (!this.sprites.has(triangleId)) {
8382
- throw new Error(`Unknown triangle "${triangleId}".`);
8383
- }
8384
- this.sprites.delete(triangleId);
8385
- this.bufferNeedsUpdate = true;
7960
+ function equals(a, b) {
7961
+ return a[0] === b[0] && a[1] === b[1];
8386
7962
  }
8387
- setTriangle(triangleId, triangleVertices) {
8388
- if (!this.sprites.has(triangleId)) {
8389
- throw new Error(`Unknown triangle "${triangleId}".`);
8390
- }
8391
- const triangleData = this.buildTriangleData(triangleVertices);
8392
- this.sprites.set(triangleId, triangleData);
8393
- this.bufferNeedsUpdate = true;
7963
+ function lerp(a, b, t, dst) {
7964
+ const newDst = dst ?? new Ctor(2);
7965
+ newDst[0] = a[0] + t * (b[0] - a[0]);
7966
+ newDst[1] = a[1] + t * (b[1] - a[1]);
7967
+ return newDst;
8394
7968
  }
8395
- buildTriangleData(triangleVertices) {
8396
- return [
8397
- triangleVertices[0][0],
8398
- triangleVertices[0][1],
8399
- triangleVertices[1][0],
8400
- triangleVertices[1][1],
8401
- triangleVertices[2][0],
8402
- triangleVertices[2][1]
8403
- ];
7969
+ function lerpV(a, b, t, dst) {
7970
+ const newDst = dst ?? new Ctor(2);
7971
+ newDst[0] = a[0] + t[0] * (b[0] - a[0]);
7972
+ newDst[1] = a[1] + t[1] * (b[1] - a[1]);
7973
+ return newDst;
8404
7974
  }
8405
- };
8406
-
8407
- // src/displacement/displacement-parameters-buffer.ts
8408
- var DisplacementParametersBuffer = class {
8409
- device;
8410
- bufferGpu;
8411
- needsUpdate = true;
8412
- constructor(params) {
8413
- this.device = params.device;
8414
- this.bufferGpu = this.device.createBuffer({
8415
- label: "DisplacementParametersBuffer buffer",
8416
- size: 16,
8417
- usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
8418
- });
8419
- this.setParameters(params.initialParameters);
7975
+ function max(a, b, dst) {
7976
+ const newDst = dst ?? new Ctor(2);
7977
+ newDst[0] = Math.max(a[0], b[0]);
7978
+ newDst[1] = Math.max(a[1], b[1]);
7979
+ return newDst;
8420
7980
  }
8421
- setParameters(params) {
8422
- this.device.queue.writeBuffer(this.bufferGpu, 0, new Float32Array([params.offsetX, params.offsetY, params.scale]));
7981
+ function min(a, b, dst) {
7982
+ const newDst = dst ?? new Ctor(2);
7983
+ newDst[0] = Math.min(a[0], b[0]);
7984
+ newDst[1] = Math.min(a[1], b[1]);
7985
+ return newDst;
8423
7986
  }
8424
- destroy() {
8425
- this.bufferGpu.destroy();
7987
+ function mulScalar(v, k, dst) {
7988
+ const newDst = dst ?? new Ctor(2);
7989
+ newDst[0] = v[0] * k;
7990
+ newDst[1] = v[1] * k;
7991
+ return newDst;
8426
7992
  }
8427
- };
8428
-
8429
- // src/displacement/composition.wgsl
8430
- var composition_default = `struct DisplacementParameters{offset:vec2<f32>,scale:f32,};@group(0)@binding(0)var<uniform> uniforms:DisplacementParameters;@group(0)@binding(1)var colorTexture:texture_2d<f32>;@group(0)@binding(2)var colorSampler:sampler;@group(0)@binding(3)var noiseTexture:texture_2d<f32>;@group(0)@binding(4)var noiseSampler:sampler;@group(0)@binding(5)var displacementTexture:texture_2d<f32>;struct VertexIn{@builtin(vertex_index)vertexIndex:u32,};struct VertexOut{@builtin(position)position:vec4<f32>,@location(0)uv:vec2<f32>,};@vertex fn main_vertex(in:VertexIn)->VertexOut{const corners=array<vec2<f32>,4>(vec2<f32>(-1,-1),vec2<f32>(1,-1),vec2<f32>(-1,1),vec2<f32>(1,1),);let screenPosition=corners[in.vertexIndex];var out:VertexOut;out.position=vec4<f32>(screenPosition,0,1);out.uv=(0.5+0.5*screenPosition*vec2<f32>(1,-1));return out;}struct FragmentOut{@location(0)color:vec4<f32>,};@fragment fn main_fragment(in:VertexOut)->FragmentOut{let noiseTextureDimensions=vec2<f32>(textureDimensions(noiseTexture,0));let noiseUv=in.uv+uniforms.offset/noiseTextureDimensions;var noise=textureSample(noiseTexture,noiseSampler,noiseUv).rg;noise-=0.5;noise*=uniforms.scale/noiseTextureDimensions;let displacement=textureSample(displacementTexture,colorSampler,in.uv).r;noise*=displacement;let colorUv=in.uv+noise;var out:FragmentOut;out.color=textureSample(colorTexture,colorSampler,colorUv);return out;}`;
8431
-
8432
- // src/displacement/displacement-composition.ts
8433
- var DisplacementComposition = class {
8434
- device;
8435
- targetFormat;
8436
- renderPipeline;
8437
- colorSampler;
8438
- noiseSampler;
8439
- displacementParametersBuffer;
8440
- renderBundle = null;
8441
- colorTextureView;
8442
- noiseMapTextureView;
8443
- displacementTextureView;
8444
- constructor(params) {
8445
- this.device = params.device;
8446
- this.targetFormat = params.targetFormat;
8447
- this.colorTextureView = params.colorTextureView;
8448
- this.noiseMapTextureView = params.noiseMapTextureView;
8449
- this.displacementTextureView = params.displacementTextureView;
8450
- this.displacementParametersBuffer = params.displacementParametersBuffer;
8451
- const shaderModule = this.device.createShaderModule({
8452
- label: "DisplacementComposition shader module",
8453
- code: composition_default
8454
- });
8455
- this.renderPipeline = this.device.createRenderPipeline({
8456
- label: "DisplacementComposition renderpipeline",
8457
- layout: "auto",
8458
- vertex: {
8459
- module: shaderModule,
8460
- entryPoint: "main_vertex"
8461
- },
8462
- fragment: {
8463
- module: shaderModule,
8464
- entryPoint: "main_fragment",
8465
- targets: [{
8466
- format: params.targetFormat
8467
- }]
8468
- },
8469
- primitive: {
8470
- cullMode: "none",
8471
- topology: "triangle-strip"
8472
- }
8473
- });
8474
- this.noiseSampler = this.device.createSampler({
8475
- label: "DisplacementComposition noisesampler",
8476
- addressModeU: "repeat",
8477
- addressModeV: "repeat",
8478
- addressModeW: "repeat",
8479
- magFilter: "linear",
8480
- minFilter: "linear",
8481
- mipmapFilter: "linear"
8482
- });
8483
- this.colorSampler = this.device.createSampler({
8484
- label: "DisplacementComposition colorSampler",
8485
- addressModeU: "clamp-to-edge",
8486
- addressModeV: "clamp-to-edge",
8487
- addressModeW: "clamp-to-edge",
8488
- magFilter: "linear",
8489
- minFilter: "linear",
8490
- mipmapFilter: "linear"
8491
- });
7993
+ const scale = mulScalar;
7994
+ function divScalar(v, k, dst) {
7995
+ const newDst = dst ?? new Ctor(2);
7996
+ newDst[0] = v[0] / k;
7997
+ newDst[1] = v[1] / k;
7998
+ return newDst;
8492
7999
  }
8493
- getRenderBundle() {
8494
- if (!this.renderBundle) {
8495
- this.renderBundle = this.buildRenderBundle();
8496
- }
8497
- return this.renderBundle;
8000
+ function inverse(v, dst) {
8001
+ const newDst = dst ?? new Ctor(2);
8002
+ newDst[0] = 1 / v[0];
8003
+ newDst[1] = 1 / v[1];
8004
+ return newDst;
8498
8005
  }
8499
- destroy() {
8006
+ const invert = inverse;
8007
+ function cross(a, b, dst) {
8008
+ const newDst = dst ?? new Ctor(3);
8009
+ const z = a[0] * b[1] - a[1] * b[0];
8010
+ newDst[0] = 0;
8011
+ newDst[1] = 0;
8012
+ newDst[2] = z;
8013
+ return newDst;
8500
8014
  }
8501
- setColorTextureView(textureView) {
8502
- this.colorTextureView = textureView;
8503
- this.renderBundle = null;
8015
+ function dot(a, b) {
8016
+ return a[0] * b[0] + a[1] * b[1];
8504
8017
  }
8505
- setNoiseMapTextureView(textureView) {
8506
- this.noiseMapTextureView = textureView;
8507
- this.renderBundle = null;
8018
+ function length(v) {
8019
+ const v0 = v[0];
8020
+ const v1 = v[1];
8021
+ return Math.sqrt(v0 * v0 + v1 * v1);
8508
8022
  }
8509
- setDisplacementTextureView(textureView) {
8510
- this.displacementTextureView = textureView;
8511
- this.renderBundle = null;
8512
- }
8513
- buildRenderBundle() {
8514
- const bindgroup = this.device.createBindGroup({
8515
- label: "DisplacementComposition bindgroup 0",
8516
- layout: this.renderPipeline.getBindGroupLayout(0),
8517
- entries: [
8518
- {
8519
- binding: 0,
8520
- resource: { buffer: this.displacementParametersBuffer.bufferGpu }
8521
- },
8522
- {
8523
- binding: 1,
8524
- resource: this.colorTextureView
8525
- },
8526
- {
8527
- binding: 2,
8528
- resource: this.colorSampler
8529
- },
8530
- {
8531
- binding: 3,
8532
- resource: this.noiseMapTextureView
8533
- },
8534
- {
8535
- binding: 4,
8536
- resource: this.noiseSampler
8537
- },
8538
- {
8539
- binding: 5,
8540
- resource: this.displacementTextureView
8541
- }
8542
- ]
8543
- });
8544
- const renderBundleEncoder = this.device.createRenderBundleEncoder({
8545
- label: "DisplacementComposition renderbundle encoder",
8546
- colorFormats: [this.targetFormat]
8547
- });
8548
- renderBundleEncoder.setPipeline(this.renderPipeline);
8549
- renderBundleEncoder.setBindGroup(0, bindgroup);
8550
- renderBundleEncoder.draw(4);
8551
- return renderBundleEncoder.finish({ label: "DisplacementComposition renderbundle" });
8552
- }
8553
- };
8554
-
8555
- // src/displacement/displacement.wgsl
8556
- var displacement_default = `struct TransformData{mvpMatrix:mat4x4<f32>,};@group(0)@binding(0)var<uniform> transformUBO:TransformData;struct VertexIn{@location(0)position:vec2<f32>,};struct VertexOut{@builtin(position)position:vec4<f32>,};@vertex fn main_vertex(in:VertexIn)->VertexOut{var output:VertexOut;output.position=transformUBO.mvpMatrix*vec4<f32>(in.position,0.0,1.0);return output;}struct FragmentOut{@location(0)color:vec4<f32>,};@fragment fn main_fragment()->FragmentOut{var out:FragmentOut;out.color=vec4<f32>(1.0,1.0,1.0,1.0);return out;}`;
8557
-
8558
- // node_modules/wgpu-matrix/dist/3.x/wgpu-matrix.module.js
8559
- function wrapConstructor(OriginalConstructor, modifier) {
8560
- return class extends OriginalConstructor {
8561
- constructor(...args) {
8562
- super(...args);
8563
- modifier(this);
8564
- }
8565
- };
8566
- }
8567
- var ZeroArray = wrapConstructor(Array, (a) => a.fill(0));
8568
- var EPSILON = 1e-6;
8569
- function getAPIImpl$5(Ctor) {
8570
- function create(x = 0, y = 0) {
8571
- const newDst = new Ctor(2);
8572
- if (x !== void 0) {
8573
- newDst[0] = x;
8574
- if (y !== void 0) {
8575
- newDst[1] = y;
8576
- }
8577
- }
8578
- return newDst;
8579
- }
8580
- const fromValues = create;
8581
- function set(x, y, dst) {
8582
- const newDst = dst ?? new Ctor(2);
8583
- newDst[0] = x;
8584
- newDst[1] = y;
8585
- return newDst;
8586
- }
8587
- function ceil(v, dst) {
8588
- const newDst = dst ?? new Ctor(2);
8589
- newDst[0] = Math.ceil(v[0]);
8590
- newDst[1] = Math.ceil(v[1]);
8591
- return newDst;
8592
- }
8593
- function floor(v, dst) {
8594
- const newDst = dst ?? new Ctor(2);
8595
- newDst[0] = Math.floor(v[0]);
8596
- newDst[1] = Math.floor(v[1]);
8597
- return newDst;
8598
- }
8599
- function round2(v, dst) {
8600
- const newDst = dst ?? new Ctor(2);
8601
- newDst[0] = Math.round(v[0]);
8602
- newDst[1] = Math.round(v[1]);
8603
- return newDst;
8604
- }
8605
- function clamp(v, min2 = 0, max2 = 1, dst) {
8606
- const newDst = dst ?? new Ctor(2);
8607
- newDst[0] = Math.min(max2, Math.max(min2, v[0]));
8608
- newDst[1] = Math.min(max2, Math.max(min2, v[1]));
8609
- return newDst;
8610
- }
8611
- function add(a, b, dst) {
8612
- const newDst = dst ?? new Ctor(2);
8613
- newDst[0] = a[0] + b[0];
8614
- newDst[1] = a[1] + b[1];
8615
- return newDst;
8616
- }
8617
- function addScaled(a, b, scale2, dst) {
8618
- const newDst = dst ?? new Ctor(2);
8619
- newDst[0] = a[0] + b[0] * scale2;
8620
- newDst[1] = a[1] + b[1] * scale2;
8621
- return newDst;
8622
- }
8623
- function angle(a, b) {
8624
- const ax = a[0];
8625
- const ay = a[1];
8626
- const bx = b[0];
8627
- const by = b[1];
8628
- const mag1 = Math.sqrt(ax * ax + ay * ay);
8629
- const mag2 = Math.sqrt(bx * bx + by * by);
8630
- const mag = mag1 * mag2;
8631
- const cosine = mag && dot(a, b) / mag;
8632
- return Math.acos(cosine);
8633
- }
8634
- function subtract(a, b, dst) {
8635
- const newDst = dst ?? new Ctor(2);
8636
- newDst[0] = a[0] - b[0];
8637
- newDst[1] = a[1] - b[1];
8638
- return newDst;
8639
- }
8640
- const sub = subtract;
8641
- function equalsApproximately(a, b) {
8642
- return Math.abs(a[0] - b[0]) < EPSILON && Math.abs(a[1] - b[1]) < EPSILON;
8643
- }
8644
- function equals(a, b) {
8645
- return a[0] === b[0] && a[1] === b[1];
8646
- }
8647
- function lerp(a, b, t, dst) {
8648
- const newDst = dst ?? new Ctor(2);
8649
- newDst[0] = a[0] + t * (b[0] - a[0]);
8650
- newDst[1] = a[1] + t * (b[1] - a[1]);
8651
- return newDst;
8652
- }
8653
- function lerpV(a, b, t, dst) {
8654
- const newDst = dst ?? new Ctor(2);
8655
- newDst[0] = a[0] + t[0] * (b[0] - a[0]);
8656
- newDst[1] = a[1] + t[1] * (b[1] - a[1]);
8657
- return newDst;
8658
- }
8659
- function max(a, b, dst) {
8660
- const newDst = dst ?? new Ctor(2);
8661
- newDst[0] = Math.max(a[0], b[0]);
8662
- newDst[1] = Math.max(a[1], b[1]);
8663
- return newDst;
8664
- }
8665
- function min(a, b, dst) {
8666
- const newDst = dst ?? new Ctor(2);
8667
- newDst[0] = Math.min(a[0], b[0]);
8668
- newDst[1] = Math.min(a[1], b[1]);
8669
- return newDst;
8670
- }
8671
- function mulScalar(v, k, dst) {
8672
- const newDst = dst ?? new Ctor(2);
8673
- newDst[0] = v[0] * k;
8674
- newDst[1] = v[1] * k;
8675
- return newDst;
8676
- }
8677
- const scale = mulScalar;
8678
- function divScalar(v, k, dst) {
8679
- const newDst = dst ?? new Ctor(2);
8680
- newDst[0] = v[0] / k;
8681
- newDst[1] = v[1] / k;
8682
- return newDst;
8683
- }
8684
- function inverse(v, dst) {
8685
- const newDst = dst ?? new Ctor(2);
8686
- newDst[0] = 1 / v[0];
8687
- newDst[1] = 1 / v[1];
8688
- return newDst;
8689
- }
8690
- const invert = inverse;
8691
- function cross(a, b, dst) {
8692
- const newDst = dst ?? new Ctor(3);
8693
- const z = a[0] * b[1] - a[1] * b[0];
8694
- newDst[0] = 0;
8695
- newDst[1] = 0;
8696
- newDst[2] = z;
8697
- return newDst;
8698
- }
8699
- function dot(a, b) {
8700
- return a[0] * b[0] + a[1] * b[1];
8701
- }
8702
- function length(v) {
8703
- const v0 = v[0];
8704
- const v1 = v[1];
8705
- return Math.sqrt(v0 * v0 + v1 * v1);
8706
- }
8707
- const len = length;
8708
- function lengthSq(v) {
8709
- const v0 = v[0];
8710
- const v1 = v[1];
8711
- return v0 * v0 + v1 * v1;
8023
+ const len = length;
8024
+ function lengthSq(v) {
8025
+ const v0 = v[0];
8026
+ const v1 = v[1];
8027
+ return v0 * v0 + v1 * v1;
8712
8028
  }
8713
8029
  const lenSq = lengthSq;
8714
8030
  function distance(a, b) {
@@ -12057,6 +11373,754 @@ var {
12057
11373
  vec4: vec4n
12058
11374
  } = wgpuMatrixAPI(ZeroArray, Array, Array, Array, Array, Array);
12059
11375
 
11376
+ // src/sprite-hdr/public-api.js
11377
+ function addSprite(cobalt, renderPass, name, position, scale, tint, opacity, rotation) {
11378
+ const { idByName } = renderPass.refs.spritesheet.data;
11379
+ renderPass.data.sprites.push({
11380
+ position: vec2.clone(position),
11381
+ sizeX: 1,
11382
+ sizeY: 1,
11383
+ scale: vec2.clone(scale),
11384
+ rotation,
11385
+ opacity,
11386
+ tint: vec4.clone(tint),
11387
+ spriteID: idByName.get(name),
11388
+ id: _uuid()
11389
+ });
11390
+ return renderPass.data.sprites.at(-1).id;
11391
+ }
11392
+ function removeSprite(cobalt, renderPass, id) {
11393
+ for (let i = 0; i < renderPass.data.sprites.length; i++) {
11394
+ if (renderPass.data.sprites[i].id === id) {
11395
+ renderPass.data.sprites.splice(i, 1);
11396
+ return;
11397
+ }
11398
+ }
11399
+ }
11400
+ function clear(cobalt, renderPass) {
11401
+ renderPass.data.sprites.length = 0;
11402
+ }
11403
+ function setSpriteName(cobalt, renderPass, id, name) {
11404
+ const sprite = renderPass.data.sprites.find((s) => s.id === id);
11405
+ if (!sprite)
11406
+ return;
11407
+ const { idByName } = renderPass.refs.spritesheet.data;
11408
+ sprite.spriteID = idByName.get(name);
11409
+ }
11410
+ function setSpritePosition(cobalt, renderPass, id, position) {
11411
+ const sprite = renderPass.data.sprites.find((s) => s.id === id);
11412
+ if (!sprite)
11413
+ return;
11414
+ vec2.copy(position, sprite.position);
11415
+ }
11416
+ function setSpriteTint(cobalt, renderPass, id, tint) {
11417
+ const sprite = renderPass.data.sprites.find((s) => s.id === id);
11418
+ if (!sprite)
11419
+ return;
11420
+ vec4.copy(tint, sprite.tint);
11421
+ }
11422
+ function setSpriteOpacity(cobalt, renderPass, id, opacity) {
11423
+ const sprite = renderPass.data.sprites.find((s) => s.id === id);
11424
+ if (!sprite)
11425
+ return;
11426
+ sprite.opacity = opacity;
11427
+ }
11428
+ function setSpriteRotation(cobalt, renderPass, id, rotation) {
11429
+ const sprite = renderPass.data.sprites.find((s) => s.id === id);
11430
+ if (!sprite)
11431
+ return;
11432
+ sprite.rotation = rotation;
11433
+ }
11434
+ function setSpriteScale(cobalt, renderPass, id, scale) {
11435
+ const sprite = renderPass.data.sprites.find((s) => s.id === id);
11436
+ if (!sprite)
11437
+ return;
11438
+ vec2.copy(scale, sprite.scale);
11439
+ }
11440
+
11441
+ // src/sprite-hdr/sprite.wgsl
11442
+ var sprite_default = `struct ViewParams{view:mat4x4<f32>,proj:mat4x4<f32>};@group(0)@binding(0)var<uniform> uView:ViewParams;@group(0)@binding(1)var uSampler:sampler;@group(0)@binding(2)var uTex:texture_2d<f32>;struct SpriteDesc{uvOrigin:vec2<f32>,uvSpan:vec2<f32>,frameSize:vec2<f32>,centerOffset:vec2<f32>,};@group(0)@binding(3)var<storage,read>Sprites:array<SpriteDesc>;@group(0)@binding(4)var emissiveTexture:texture_2d<f32>;struct VSOut{@builtin(position)pos:vec4<f32>,@location(0)uv:vec2<f32>,@location(1)tint:vec4<f32>,@location(2)opacity:f32,};const corners=array<vec2<f32>,4>(vec2<f32>(-0.5,-0.5),vec2<f32>(0.5,-0.5),vec2<f32>(-0.5,0.5),vec2<f32>(0.5,0.5),);const uvBase=array<vec2<f32>,4>(vec2<f32>(0.0,0.0),vec2<f32>(1.0,0.0),vec2<f32>(0.0,1.0),vec2<f32>(1.0,1.0),);struct GBufferOutput{@location(0)color:vec4<f32>,@location(1)emissive:vec4<f32>,}@vertex fn vs_main(@builtin(vertex_index)vid:u32,@location(0)i_pos:vec2<f32>,@location(1)i_size:vec2<f32>,@location(2)i_scale:vec2<f32>,@location(3)i_tint:vec4<f32>,@location(4)i_spriteId:u32,@location(5)i_opacity:f32,@location(6)i_rotation:f32)->VSOut{let rot=i_rotation;let c=cos(rot);let s=sin(rot);let d=Sprites[i_spriteId];let corner=corners[vid];let sizePx=d.frameSize*i_size*i_scale;var local=corner*sizePx;local+=d.centerOffset*i_scale;let rotated=vec2<f32>(local.x*c-local.y*s,local.x*s+local.y*c);let world=vec4<f32>(rotated+i_pos,0.0,1.0);var out:VSOut;out.pos=uView.proj*uView.view*world;out.uv=d.uvOrigin+d.uvSpan*uvBase[vid];out.tint=i_tint;out.opacity=i_opacity;return out;}@fragment fn fs_main(in:VSOut)->GBufferOutput{var output:GBufferOutput;let texel=textureSample(uTex,uSampler,in.uv);output.color=vec4<f32>(texel.rgb*(1.0-in.tint.a)+(in.tint.rgb*in.tint.a),texel.a*in.opacity);let emissive=textureSample(emissiveTexture,uSampler,in.uv);output.emissive=vec4(emissive.rgb,1.0)*emissive.a;return output;}`;
11443
+
11444
+ // node_modules/round-half-up-symmetric/index.js
11445
+ function round(value) {
11446
+ if (value >= 0)
11447
+ return Math.round(value);
11448
+ return value % 0.5 === 0 ? Math.floor(value) : Math.round(value);
11449
+ }
11450
+
11451
+ // src/sprite-hdr/sprite.js
11452
+ var _tmpVec3 = vec3.create(0, 0, 0);
11453
+ var INSTANCE_STRIDE = 64;
11454
+ var OFF_POS = 0;
11455
+ var OFF_SIZE = 8;
11456
+ var OFF_SCALE = 16;
11457
+ var OFF_TINT = 24;
11458
+ var OFF_SPRITEID = 40;
11459
+ var OFF_OPACITY = 44;
11460
+ var OFF_ROT = 48;
11461
+ var sprite_default2 = {
11462
+ type: "cobalt:spriteHDR",
11463
+ refs: [
11464
+ { name: "spritesheet", type: "customResource", access: "read" },
11465
+ {
11466
+ name: "color",
11467
+ type: "textureView",
11468
+ format: "rgba16float",
11469
+ access: "write"
11470
+ },
11471
+ {
11472
+ name: "emissive",
11473
+ type: "textureView",
11474
+ format: "rgba16float",
11475
+ access: "write"
11476
+ }
11477
+ ],
11478
+ // cobalt event handling functions
11479
+ // @params Object cobalt renderer world object
11480
+ // @params Object options optional data passed when initing this node
11481
+ onInit: async function(cobalt, options = {}) {
11482
+ return init3(cobalt, options);
11483
+ },
11484
+ onRun: function(cobalt, node, webGpuCommandEncoder) {
11485
+ draw3(cobalt, node, webGpuCommandEncoder);
11486
+ },
11487
+ // Clean up GPU resources. Most WebGPU objects are GC-managed and don't
11488
+ // expose destroy(); buffers/textures/query-sets do.
11489
+ onDestroy: function(cobalt, node) {
11490
+ try {
11491
+ node.data.instanceBuf?.destroy();
11492
+ } catch {
11493
+ }
11494
+ try {
11495
+ node.data.spriteBuf?.destroy();
11496
+ } catch {
11497
+ }
11498
+ try {
11499
+ node.data.uniformBuffer?.destroy();
11500
+ } catch {
11501
+ }
11502
+ node.data.pipeline = null;
11503
+ node.data.bindGroup = null;
11504
+ node.data.bindGroupLayout = null;
11505
+ node.data.instanceStaging = null;
11506
+ node.data.instanceView = null;
11507
+ node.data.sprites.length = 0;
11508
+ node.data.visible.length = 0;
11509
+ },
11510
+ onResize: function(cobalt, node) {
11511
+ _writeSpriteBuffer(cobalt, node);
11512
+ },
11513
+ onViewportPosition: function(cobalt, node) {
11514
+ _writeSpriteBuffer(cobalt, node);
11515
+ },
11516
+ // optional
11517
+ customFunctions: {
11518
+ ...public_api_exports
11519
+ }
11520
+ };
11521
+ async function init3(cobalt, nodeData) {
11522
+ const { device } = cobalt;
11523
+ const { descs, names } = nodeData.refs.spritesheet.data.spritesheet;
11524
+ const uniformBuffer = device.createBuffer({
11525
+ size: 64 * 2,
11526
+ // 4x4 matrix with 4 bytes per float32, times 2 matrices (view, projection)
11527
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
11528
+ });
11529
+ const BYTES_PER_DESC = 8 * 4;
11530
+ const buf = new ArrayBuffer(BYTES_PER_DESC * descs.length);
11531
+ const f32 = new Float32Array(buf);
11532
+ for (let i = 0; i < descs.length; i++) {
11533
+ const d = descs[i];
11534
+ const base = i * 8;
11535
+ f32[base + 0] = d.UvOrigin[0];
11536
+ f32[base + 1] = d.UvOrigin[1];
11537
+ f32[base + 2] = d.UvSpan[0];
11538
+ f32[base + 3] = d.UvSpan[1];
11539
+ f32[base + 4] = d.FrameSize[0];
11540
+ f32[base + 5] = d.FrameSize[1];
11541
+ f32[base + 6] = d.CenterOffset[0];
11542
+ f32[base + 7] = d.CenterOffset[1];
11543
+ }
11544
+ const spriteBuf = device.createBuffer({
11545
+ label: "spriteHDR desc table",
11546
+ size: Math.max(16, buf.byteLength),
11547
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
11548
+ });
11549
+ device.queue.writeBuffer(spriteBuf, 0, buf);
11550
+ const instanceCap = 1024;
11551
+ const instanceBuf = device.createBuffer({
11552
+ label: "spriteHDR instances",
11553
+ size: INSTANCE_STRIDE * instanceCap,
11554
+ usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
11555
+ });
11556
+ const instanceStaging = new ArrayBuffer(INSTANCE_STRIDE * instanceCap);
11557
+ const instanceView = new DataView(instanceStaging);
11558
+ const shader = device.createShaderModule({ code: sprite_default });
11559
+ const bgl = device.createBindGroupLayout({
11560
+ entries: [
11561
+ {
11562
+ binding: 0,
11563
+ visibility: GPUShaderStage.VERTEX,
11564
+ buffer: { type: "uniform" }
11565
+ },
11566
+ {
11567
+ binding: 1,
11568
+ visibility: GPUShaderStage.FRAGMENT,
11569
+ sampler: { type: "filtering" }
11570
+ },
11571
+ {
11572
+ binding: 2,
11573
+ visibility: GPUShaderStage.FRAGMENT,
11574
+ texture: { sampleType: "float" }
11575
+ },
11576
+ {
11577
+ binding: 3,
11578
+ visibility: GPUShaderStage.VERTEX,
11579
+ buffer: { type: "read-only-storage" }
11580
+ },
11581
+ {
11582
+ binding: 4,
11583
+ visibility: GPUShaderStage.FRAGMENT,
11584
+ texture: { sampleType: "float" }
11585
+ }
11586
+ ]
11587
+ });
11588
+ const pipelineLayout = device.createPipelineLayout({
11589
+ bindGroupLayouts: [bgl]
11590
+ });
11591
+ const instLayout = {
11592
+ arrayStride: INSTANCE_STRIDE,
11593
+ stepMode: "instance",
11594
+ attributes: [
11595
+ { shaderLocation: 0, offset: OFF_POS, format: "float32x2" },
11596
+ { shaderLocation: 1, offset: OFF_SIZE, format: "float32x2" },
11597
+ { shaderLocation: 2, offset: OFF_SCALE, format: "float32x2" },
11598
+ { shaderLocation: 3, offset: OFF_TINT, format: "float32x4" },
11599
+ { shaderLocation: 4, offset: OFF_SPRITEID, format: "uint32" },
11600
+ { shaderLocation: 5, offset: OFF_OPACITY, format: "float32" },
11601
+ { shaderLocation: 6, offset: OFF_ROT, format: "float32" }
11602
+ ]
11603
+ };
11604
+ const pipeline = device.createRenderPipeline({
11605
+ layout: pipelineLayout,
11606
+ vertex: {
11607
+ module: shader,
11608
+ entryPoint: "vs_main",
11609
+ buffers: [instLayout]
11610
+ },
11611
+ fragment: {
11612
+ module: shader,
11613
+ entryPoint: "fs_main",
11614
+ targets: [
11615
+ // color
11616
+ {
11617
+ format: "rgba16float",
11618
+ blend: {
11619
+ color: {
11620
+ srcFactor: "src-alpha",
11621
+ dstFactor: "one-minus-src-alpha"
11622
+ },
11623
+ alpha: {
11624
+ srcFactor: "zero",
11625
+ dstFactor: "one"
11626
+ }
11627
+ }
11628
+ },
11629
+ // emissive
11630
+ {
11631
+ format: "rgba16float"
11632
+ }
11633
+ ]
11634
+ },
11635
+ primitive: { topology: "triangle-strip", cullMode: "none" },
11636
+ multisample: { count: 1 }
11637
+ });
11638
+ const bindGroupLayout = bgl;
11639
+ const bindGroup = device.createBindGroup({
11640
+ layout: bgl,
11641
+ entries: [
11642
+ // Uniform buffer (view + proj matrices)
11643
+ { binding: 0, resource: { buffer: uniformBuffer } },
11644
+ { binding: 1, resource: nodeData.refs.spritesheet.data.colorTexture.sampler },
11645
+ { binding: 2, resource: nodeData.refs.spritesheet.data.colorTexture.view },
11646
+ { binding: 3, resource: { buffer: spriteBuf } },
11647
+ { binding: 4, resource: nodeData.refs.spritesheet.data.emissiveTexture.view }
11648
+ ]
11649
+ });
11650
+ return {
11651
+ sprites: [],
11652
+ visible: [],
11653
+ visibleCount: 0,
11654
+ viewRect: { x: 0, y: 0, w: 0, h: 0 },
11655
+ spriteBuf,
11656
+ uniformBuffer,
11657
+ instanceCap,
11658
+ instanceView,
11659
+ instanceBuf,
11660
+ instanceStaging,
11661
+ pipeline,
11662
+ bindGroup
11663
+ };
11664
+ }
11665
+ function ensureCapacity(cobalt, node, nInstances) {
11666
+ const { instanceCap } = node.data;
11667
+ if (nInstances <= instanceCap)
11668
+ return;
11669
+ let newCap = instanceCap;
11670
+ if (newCap === 0)
11671
+ newCap = 1024;
11672
+ while (newCap < nInstances)
11673
+ newCap *= 2;
11674
+ node.data.instanceBuf.destroy();
11675
+ node.data.instanceBuf = cobalt.device.createBuffer({
11676
+ size: INSTANCE_STRIDE * newCap,
11677
+ usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
11678
+ });
11679
+ node.data.instanceStaging = new ArrayBuffer(INSTANCE_STRIDE * newCap);
11680
+ node.data.instanceView = new DataView(node.data.instanceStaging);
11681
+ node.data.instanceCap = newCap;
11682
+ }
11683
+ function draw3(cobalt, node, commandEncoder) {
11684
+ const { device, context } = cobalt;
11685
+ const { instanceView, instanceBuf, instanceStaging, pipeline, bindGroup } = node.data;
11686
+ const { descs } = node.refs.spritesheet.data.spritesheet;
11687
+ const viewRect = node.data.viewRect;
11688
+ viewRect.x = cobalt.viewport.position[0];
11689
+ viewRect.y = cobalt.viewport.position[1];
11690
+ viewRect.w = cobalt.viewport.width;
11691
+ viewRect.h = cobalt.viewport.height;
11692
+ node.data.visibleCount = 0;
11693
+ for (const s of node.data.sprites) {
11694
+ const d = descs[s.spriteID];
11695
+ if (!d)
11696
+ continue;
11697
+ if (!node.options.isScreenSpace) {
11698
+ const sx = d.FrameSize[0] * s.sizeX * s.scale[0] * 0.5;
11699
+ const sy = d.FrameSize[1] * s.sizeY * s.scale[1] * 0.5;
11700
+ const rad = Math.hypot(sx, sy);
11701
+ const x = s.position[0], y = s.position[1];
11702
+ if (x + rad < viewRect.x || x - rad > viewRect.x + viewRect.w || y + rad < viewRect.y || y - rad > viewRect.y + viewRect.h)
11703
+ continue;
11704
+ }
11705
+ node.data.visible[node.data.visibleCount] = s;
11706
+ node.data.visibleCount++;
11707
+ }
11708
+ ensureCapacity(cobalt, node, node.data.visibleCount);
11709
+ for (let i = 0; i < node.data.visibleCount; i++) {
11710
+ const base = i * INSTANCE_STRIDE;
11711
+ const s = node.data.visible[i];
11712
+ const tint = s.tint;
11713
+ instanceView.setFloat32(base + OFF_POS + 0, s.position[0], true);
11714
+ instanceView.setFloat32(base + OFF_POS + 4, s.position[1], true);
11715
+ instanceView.setFloat32(base + OFF_SIZE + 0, s.sizeX, true);
11716
+ instanceView.setFloat32(base + OFF_SIZE + 4, s.sizeY, true);
11717
+ instanceView.setFloat32(base + OFF_SCALE + 0, s.scale[0], true);
11718
+ instanceView.setFloat32(base + OFF_SCALE + 4, s.scale[1], true);
11719
+ instanceView.setFloat32(base + OFF_TINT + 0, tint[0], true);
11720
+ instanceView.setFloat32(base + OFF_TINT + 4, tint[1], true);
11721
+ instanceView.setFloat32(base + OFF_TINT + 8, tint[2], true);
11722
+ instanceView.setFloat32(base + OFF_TINT + 12, tint[3], true);
11723
+ instanceView.setUint32(base + OFF_SPRITEID, s.spriteID >>> 0, true);
11724
+ instanceView.setFloat32(base + OFF_OPACITY, s.opacity, true);
11725
+ instanceView.setFloat32(base + OFF_ROT, s.rotation, true);
11726
+ }
11727
+ device.queue.writeBuffer(instanceBuf, 0, instanceStaging, 0, node.data.visibleCount * INSTANCE_STRIDE);
11728
+ const loadOp = node.options.loadOp || "load";
11729
+ const pass = commandEncoder.beginRenderPass({
11730
+ label: "spriteHDR renderpass",
11731
+ colorAttachments: [
11732
+ // color
11733
+ {
11734
+ view: node.refs.color.data.view,
11735
+ clearValue: cobalt.clearValue,
11736
+ loadOp,
11737
+ storeOp: "store"
11738
+ },
11739
+ // emissive
11740
+ {
11741
+ view: node.refs.emissive.data.view,
11742
+ clearValue: cobalt.clearValue,
11743
+ loadOp: "clear",
11744
+ storeOp: "store"
11745
+ }
11746
+ ]
11747
+ });
11748
+ pass.setPipeline(pipeline);
11749
+ pass.setBindGroup(0, bindGroup);
11750
+ pass.setVertexBuffer(0, instanceBuf);
11751
+ if (node.data.visibleCount)
11752
+ pass.draw(4, node.data.visibleCount, 0, 0);
11753
+ pass.end();
11754
+ }
11755
+ function _writeSpriteBuffer(cobalt, node) {
11756
+ const { device, viewport } = cobalt;
11757
+ const GAME_WIDTH = viewport.width / viewport.zoom;
11758
+ const GAME_HEIGHT = viewport.height / viewport.zoom;
11759
+ const projection = mat4.ortho(0, GAME_WIDTH, GAME_HEIGHT, 0, -10, 10);
11760
+ if (!!node.options.isScreenSpace) {
11761
+ vec3.set(0, 0, 0, _tmpVec3);
11762
+ } else {
11763
+ vec3.set(-round(viewport.position[0]), -round(viewport.position[1]), 0, _tmpVec3);
11764
+ }
11765
+ const view = mat4.translation(_tmpVec3);
11766
+ device.queue.writeBuffer(node.data.uniformBuffer, 0, view.buffer);
11767
+ device.queue.writeBuffer(node.data.uniformBuffer, 64, projection.buffer);
11768
+ }
11769
+
11770
+ // src/tile-hdr/tile.js
11771
+ var tile_default = {
11772
+ type: "cobalt:tileHDR",
11773
+ refs: [
11774
+ { name: "tileAtlas", type: "textureView", format: "rgba8unorm", access: "read" },
11775
+ { name: "hdr", type: "textureView", format: "rgba16float", access: "write" }
11776
+ ],
11777
+ // @params Object cobalt renderer world object
11778
+ // @params Object options optional data passed when initing this node
11779
+ onInit: async function(cobalt, options = {}) {
11780
+ return init4(cobalt, options);
11781
+ },
11782
+ onRun: function(cobalt, node, webGpuCommandEncoder) {
11783
+ draw4(cobalt, node, webGpuCommandEncoder);
11784
+ },
11785
+ onDestroy: function(cobalt, node) {
11786
+ destroy2(node);
11787
+ },
11788
+ onResize: function(cobalt, node) {
11789
+ },
11790
+ onViewportPosition: function(cobalt, node) {
11791
+ },
11792
+ // optional
11793
+ customFunctions: {
11794
+ setTexture: async function(cobalt, node, texture) {
11795
+ const { canvas, device } = cobalt;
11796
+ destroy2(node);
11797
+ const format = node.options.format || getPreferredFormat(cobalt);
11798
+ let material;
11799
+ if (canvas) {
11800
+ node.options.textureUrl = texture;
11801
+ material = await createTextureFromUrl(cobalt, "tile map", texture, format);
11802
+ } else {
11803
+ material = await createTextureFromBuffer(cobalt, "tile map", texture, format);
11804
+ }
11805
+ const bindGroup = device.createBindGroup({
11806
+ layout: node.refs.tileAtlas.data.tileBindGroupLayout,
11807
+ entries: [
11808
+ {
11809
+ binding: 0,
11810
+ resource: {
11811
+ buffer: node.data.uniformBuffer
11812
+ }
11813
+ },
11814
+ {
11815
+ binding: 1,
11816
+ resource: material.view
11817
+ },
11818
+ {
11819
+ binding: 2,
11820
+ resource: material.sampler
11821
+ }
11822
+ ]
11823
+ });
11824
+ node.data.bindGroup = bindGroup;
11825
+ node.data.material = material;
11826
+ }
11827
+ }
11828
+ };
11829
+ async function init4(cobalt, nodeData) {
11830
+ const { canvas, device } = cobalt;
11831
+ let material;
11832
+ const format = nodeData.options.format || getPreferredFormat(cobalt);
11833
+ if (canvas) {
11834
+ material = await createTextureFromUrl(cobalt, "tile map", nodeData.options.textureUrl, format);
11835
+ } else {
11836
+ material = await createTextureFromBuffer(cobalt, "tile map", nodeData.options.texture, format);
11837
+ }
11838
+ const dat = new Float32Array([nodeData.options.scrollScale, nodeData.options.scrollScale]);
11839
+ const usage = GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST;
11840
+ const descriptor = {
11841
+ size: dat.byteLength,
11842
+ usage,
11843
+ // make this memory space accessible from the CPU (host visible)
11844
+ mappedAtCreation: true
11845
+ };
11846
+ const uniformBuffer = device.createBuffer(descriptor);
11847
+ new Float32Array(uniformBuffer.getMappedRange()).set(dat);
11848
+ uniformBuffer.unmap();
11849
+ const bindGroup = device.createBindGroup({
11850
+ layout: nodeData.refs.tileAtlas.data.tileBindGroupLayout,
11851
+ entries: [
11852
+ {
11853
+ binding: 0,
11854
+ resource: {
11855
+ buffer: uniformBuffer
11856
+ }
11857
+ },
11858
+ {
11859
+ binding: 1,
11860
+ resource: material.view
11861
+ },
11862
+ {
11863
+ binding: 2,
11864
+ resource: material.sampler
11865
+ }
11866
+ ]
11867
+ });
11868
+ return {
11869
+ bindGroup,
11870
+ material,
11871
+ uniformBuffer,
11872
+ scrollScale: nodeData.options.scrollScale
11873
+ };
11874
+ }
11875
+ function draw4(cobalt, nodeData, commandEncoder) {
11876
+ if (!nodeData.data.material.texture)
11877
+ return;
11878
+ const { device } = cobalt;
11879
+ const loadOp = nodeData.options.loadOp || "load";
11880
+ const renderpass = commandEncoder.beginRenderPass({
11881
+ label: "tile",
11882
+ colorAttachments: [
11883
+ {
11884
+ // hdr is passsed as a node || FRAME_TEXTURE_VIEW
11885
+ view: nodeData.refs.hdr.data?.view || nodeData.refs.hdr,
11886
+ clearValue: cobalt.clearValue,
11887
+ loadOp,
11888
+ storeOp: "store"
11889
+ }
11890
+ ]
11891
+ });
11892
+ const tileAtlas = nodeData.refs.tileAtlas.data;
11893
+ renderpass.setPipeline(tileAtlas.pipeline);
11894
+ renderpass.setBindGroup(0, nodeData.data.bindGroup);
11895
+ renderpass.setBindGroup(1, tileAtlas.atlasBindGroup);
11896
+ renderpass.draw(3);
11897
+ renderpass.end();
11898
+ }
11899
+ function destroy2(nodeData) {
11900
+ nodeData.data.material.texture.destroy();
11901
+ nodeData.data.material.texture = void 0;
11902
+ }
11903
+
11904
+ // src/displacement/triangles-buffer.ts
11905
+ var TrianglesBuffer = class {
11906
+ device;
11907
+ floatsPerSprite = 6;
11908
+ // vec2(translate) + vec2(scale) + rotation + opacity
11909
+ bufferGpu;
11910
+ bufferNeedsUpdate = false;
11911
+ sprites = /* @__PURE__ */ new Map();
11912
+ get spriteCount() {
11913
+ return this.sprites.size;
11914
+ }
11915
+ constructor(params) {
11916
+ this.device = params.device;
11917
+ this.bufferGpu = this.device.createBuffer({
11918
+ size: params.maxSpriteCount * this.floatsPerSprite * Float32Array.BYTES_PER_ELEMENT,
11919
+ usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
11920
+ });
11921
+ }
11922
+ destroy() {
11923
+ this.bufferGpu.destroy;
11924
+ }
11925
+ update() {
11926
+ if (this.bufferNeedsUpdate) {
11927
+ const bufferData = [];
11928
+ for (const sprite of this.sprites.values()) {
11929
+ bufferData.push(...sprite);
11930
+ }
11931
+ ;
11932
+ const buffer = new Float32Array(bufferData);
11933
+ this.device.queue.writeBuffer(this.bufferGpu, 0, buffer);
11934
+ }
11935
+ }
11936
+ addTriangle(triangleVertices) {
11937
+ const triangleId = _uuid();
11938
+ if (this.sprites.has(triangleId)) {
11939
+ throw new Error(`Duplicate triangle "${triangleId}".`);
11940
+ }
11941
+ const triangleData = this.buildTriangleData(triangleVertices);
11942
+ this.sprites.set(triangleId, triangleData);
11943
+ this.bufferNeedsUpdate = true;
11944
+ return triangleId;
11945
+ }
11946
+ removeTriangle(triangleId) {
11947
+ if (!this.sprites.has(triangleId)) {
11948
+ throw new Error(`Unknown triangle "${triangleId}".`);
11949
+ }
11950
+ this.sprites.delete(triangleId);
11951
+ this.bufferNeedsUpdate = true;
11952
+ }
11953
+ setTriangle(triangleId, triangleVertices) {
11954
+ if (!this.sprites.has(triangleId)) {
11955
+ throw new Error(`Unknown triangle "${triangleId}".`);
11956
+ }
11957
+ const triangleData = this.buildTriangleData(triangleVertices);
11958
+ this.sprites.set(triangleId, triangleData);
11959
+ this.bufferNeedsUpdate = true;
11960
+ }
11961
+ buildTriangleData(triangleVertices) {
11962
+ return [
11963
+ triangleVertices[0][0],
11964
+ triangleVertices[0][1],
11965
+ triangleVertices[1][0],
11966
+ triangleVertices[1][1],
11967
+ triangleVertices[2][0],
11968
+ triangleVertices[2][1]
11969
+ ];
11970
+ }
11971
+ };
11972
+
11973
+ // src/displacement/displacement-parameters-buffer.ts
11974
+ var DisplacementParametersBuffer = class {
11975
+ device;
11976
+ bufferGpu;
11977
+ needsUpdate = true;
11978
+ constructor(params) {
11979
+ this.device = params.device;
11980
+ this.bufferGpu = this.device.createBuffer({
11981
+ label: "DisplacementParametersBuffer buffer",
11982
+ size: 16,
11983
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
11984
+ });
11985
+ this.setParameters(params.initialParameters);
11986
+ }
11987
+ setParameters(params) {
11988
+ this.device.queue.writeBuffer(this.bufferGpu, 0, new Float32Array([params.offsetX, params.offsetY, params.scale]));
11989
+ }
11990
+ destroy() {
11991
+ this.bufferGpu.destroy();
11992
+ }
11993
+ };
11994
+
11995
+ // src/displacement/composition.wgsl
11996
+ var composition_default = `struct DisplacementParameters{offset:vec2<f32>,scale:f32,};@group(0)@binding(0)var<uniform> uniforms:DisplacementParameters;@group(0)@binding(1)var colorTexture:texture_2d<f32>;@group(0)@binding(2)var colorSampler:sampler;@group(0)@binding(3)var noiseTexture:texture_2d<f32>;@group(0)@binding(4)var noiseSampler:sampler;@group(0)@binding(5)var displacementTexture:texture_2d<f32>;struct VertexIn{@builtin(vertex_index)vertexIndex:u32,};struct VertexOut{@builtin(position)position:vec4<f32>,@location(0)uv:vec2<f32>,};@vertex fn main_vertex(in:VertexIn)->VertexOut{const corners=array<vec2<f32>,4>(vec2<f32>(-1,-1),vec2<f32>(1,-1),vec2<f32>(-1,1),vec2<f32>(1,1),);let screenPosition=corners[in.vertexIndex];var out:VertexOut;out.position=vec4<f32>(screenPosition,0,1);out.uv=(0.5+0.5*screenPosition*vec2<f32>(1,-1));return out;}struct FragmentOut{@location(0)color:vec4<f32>,};@fragment fn main_fragment(in:VertexOut)->FragmentOut{let noiseTextureDimensions=vec2<f32>(textureDimensions(noiseTexture,0));let noiseUv=in.uv+uniforms.offset/noiseTextureDimensions;var noise=textureSample(noiseTexture,noiseSampler,noiseUv).rg;noise-=0.5;noise*=uniforms.scale/noiseTextureDimensions;let displacement=textureSample(displacementTexture,colorSampler,in.uv).r;noise*=displacement;let colorUv=in.uv+noise;var out:FragmentOut;out.color=textureSample(colorTexture,colorSampler,colorUv);return out;}`;
11997
+
11998
+ // src/displacement/displacement-composition.ts
11999
+ var DisplacementComposition = class {
12000
+ device;
12001
+ targetFormat;
12002
+ renderPipeline;
12003
+ colorSampler;
12004
+ noiseSampler;
12005
+ displacementParametersBuffer;
12006
+ renderBundle = null;
12007
+ colorTextureView;
12008
+ noiseMapTextureView;
12009
+ displacementTextureView;
12010
+ constructor(params) {
12011
+ this.device = params.device;
12012
+ this.targetFormat = params.targetFormat;
12013
+ this.colorTextureView = params.colorTextureView;
12014
+ this.noiseMapTextureView = params.noiseMapTextureView;
12015
+ this.displacementTextureView = params.displacementTextureView;
12016
+ this.displacementParametersBuffer = params.displacementParametersBuffer;
12017
+ const shaderModule = this.device.createShaderModule({
12018
+ label: "DisplacementComposition shader module",
12019
+ code: composition_default
12020
+ });
12021
+ this.renderPipeline = this.device.createRenderPipeline({
12022
+ label: "DisplacementComposition renderpipeline",
12023
+ layout: "auto",
12024
+ vertex: {
12025
+ module: shaderModule,
12026
+ entryPoint: "main_vertex"
12027
+ },
12028
+ fragment: {
12029
+ module: shaderModule,
12030
+ entryPoint: "main_fragment",
12031
+ targets: [{
12032
+ format: params.targetFormat
12033
+ }]
12034
+ },
12035
+ primitive: {
12036
+ cullMode: "none",
12037
+ topology: "triangle-strip"
12038
+ }
12039
+ });
12040
+ this.noiseSampler = this.device.createSampler({
12041
+ label: "DisplacementComposition noisesampler",
12042
+ addressModeU: "repeat",
12043
+ addressModeV: "repeat",
12044
+ addressModeW: "repeat",
12045
+ magFilter: "linear",
12046
+ minFilter: "linear",
12047
+ mipmapFilter: "linear"
12048
+ });
12049
+ this.colorSampler = this.device.createSampler({
12050
+ label: "DisplacementComposition colorSampler",
12051
+ addressModeU: "clamp-to-edge",
12052
+ addressModeV: "clamp-to-edge",
12053
+ addressModeW: "clamp-to-edge",
12054
+ magFilter: "linear",
12055
+ minFilter: "linear",
12056
+ mipmapFilter: "linear"
12057
+ });
12058
+ }
12059
+ getRenderBundle() {
12060
+ if (!this.renderBundle) {
12061
+ this.renderBundle = this.buildRenderBundle();
12062
+ }
12063
+ return this.renderBundle;
12064
+ }
12065
+ destroy() {
12066
+ }
12067
+ setColorTextureView(textureView) {
12068
+ this.colorTextureView = textureView;
12069
+ this.renderBundle = null;
12070
+ }
12071
+ setNoiseMapTextureView(textureView) {
12072
+ this.noiseMapTextureView = textureView;
12073
+ this.renderBundle = null;
12074
+ }
12075
+ setDisplacementTextureView(textureView) {
12076
+ this.displacementTextureView = textureView;
12077
+ this.renderBundle = null;
12078
+ }
12079
+ buildRenderBundle() {
12080
+ const bindgroup = this.device.createBindGroup({
12081
+ label: "DisplacementComposition bindgroup 0",
12082
+ layout: this.renderPipeline.getBindGroupLayout(0),
12083
+ entries: [
12084
+ {
12085
+ binding: 0,
12086
+ resource: { buffer: this.displacementParametersBuffer.bufferGpu }
12087
+ },
12088
+ {
12089
+ binding: 1,
12090
+ resource: this.colorTextureView
12091
+ },
12092
+ {
12093
+ binding: 2,
12094
+ resource: this.colorSampler
12095
+ },
12096
+ {
12097
+ binding: 3,
12098
+ resource: this.noiseMapTextureView
12099
+ },
12100
+ {
12101
+ binding: 4,
12102
+ resource: this.noiseSampler
12103
+ },
12104
+ {
12105
+ binding: 5,
12106
+ resource: this.displacementTextureView
12107
+ }
12108
+ ]
12109
+ });
12110
+ const renderBundleEncoder = this.device.createRenderBundleEncoder({
12111
+ label: "DisplacementComposition renderbundle encoder",
12112
+ colorFormats: [this.targetFormat]
12113
+ });
12114
+ renderBundleEncoder.setPipeline(this.renderPipeline);
12115
+ renderBundleEncoder.setBindGroup(0, bindgroup);
12116
+ renderBundleEncoder.draw(4);
12117
+ return renderBundleEncoder.finish({ label: "DisplacementComposition renderbundle" });
12118
+ }
12119
+ };
12120
+
12121
+ // src/displacement/displacement.wgsl
12122
+ var displacement_default = `struct TransformData{mvpMatrix:mat4x4<f32>,};@group(0)@binding(0)var<uniform> transformUBO:TransformData;struct VertexIn{@location(0)position:vec2<f32>,};struct VertexOut{@builtin(position)position:vec4<f32>,};@vertex fn main_vertex(in:VertexIn)->VertexOut{var output:VertexOut;output.position=transformUBO.mvpMatrix*vec4<f32>(in.position,0.0,1.0);return output;}struct FragmentOut{@location(0)color:vec4<f32>,};@fragment fn main_fragment()->FragmentOut{var out:FragmentOut;out.color=vec4<f32>(1.0,1.0,1.0,1.0);return out;}`;
12123
+
12060
12124
  // src/displacement/displacement-texture.ts
12061
12125
  var DisplacementTexture = class {
12062
12126
  device;
@@ -12237,7 +12301,7 @@ var displacement_default2 = {
12237
12301
  draw5(cobalt, node, webGpuCommandEncoder);
12238
12302
  },
12239
12303
  onDestroy: function(cobalt, node) {
12240
- destroy4(node);
12304
+ destroy3(node);
12241
12305
  },
12242
12306
  onResize: function(cobalt, node) {
12243
12307
  node.data.displacementTexture.resize(cobalt.viewport.width, cobalt.viewport.height);
@@ -12318,7 +12382,7 @@ function draw5(cobalt, node, commandEncoder) {
12318
12382
  renderpass.executeBundles([node.data.displacementComposition.getRenderBundle()]);
12319
12383
  renderpass.end();
12320
12384
  }
12321
- function destroy4(node) {
12385
+ function destroy3(node) {
12322
12386
  node.data.trianglesBuffer.destroy();
12323
12387
  node.data.trianglesBuffer = null;
12324
12388
  node.data.displacementParameters.destroy();
@@ -12329,297 +12393,6 @@ function destroy4(node) {
12329
12393
  node.data.displacementComposition = null;
12330
12394
  }
12331
12395
 
12332
- // src/sprite/create-sprite-quads.js
12333
- function createSpriteQuads(device, spritesheet) {
12334
- const vertices = spritesheet.vertices;
12335
- const usage = GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST;
12336
- const descriptor = {
12337
- size: vertices.byteLength,
12338
- usage,
12339
- // make this memory space accessible from the CPU (host visible)
12340
- mappedAtCreation: true
12341
- };
12342
- const buffer = device.createBuffer(descriptor);
12343
- new Float32Array(buffer.getMappedRange()).set(vertices);
12344
- buffer.unmap();
12345
- const bufferLayout = {
12346
- arrayStride: 20,
12347
- stepMode: "vertex",
12348
- attributes: [
12349
- // position
12350
- {
12351
- shaderLocation: 0,
12352
- format: "float32x3",
12353
- offset: 0
12354
- },
12355
- // uv
12356
- {
12357
- shaderLocation: 1,
12358
- format: "float32x2",
12359
- offset: 12
12360
- }
12361
- ]
12362
- };
12363
- return {
12364
- buffer,
12365
- bufferLayout
12366
- };
12367
- }
12368
-
12369
- // src/overlay/overlay.wgsl
12370
- var overlay_default = `struct TransformData{view:mat4x4<f32>,projection:mat4x4<f32>};struct Sprite{translate:vec2<f32>,scale:vec2<f32>,tint:vec4<f32>,opacity:f32,rotation:f32,};struct SpritesBuffer{models:array<Sprite>,};@binding(0)@group(0)var<uniform> transformUBO:TransformData;@binding(1)@group(0)var myTexture:texture_2d<f32>;@binding(2)@group(0)var mySampler:sampler;@binding(3)@group(0)var<storage,read>sprites:SpritesBuffer;struct Fragment{@builtin(position)Position:vec4<f32>,@location(0)TexCoord:vec2<f32>,@location(1)Tint:vec4<f32>,@location(2)Opacity:f32,};@vertex fn vs_main(@builtin(instance_index)i_id:u32,@location(0)vertexPosition:vec3<f32>,@location(1)vertexTexCoord:vec2<f32>)->Fragment{var output:Fragment;var sx:f32=sprites.models[i_id].scale.x;var sy:f32=sprites.models[i_id].scale.y;var sz:f32=1.0;var rot:f32=sprites.models[i_id].rotation;var tx:f32=sprites.models[i_id].translate.x;var ty:f32=sprites.models[i_id].translate.y;var tz:f32=0;var s=sin(rot);var c=cos(rot);var scaleM:mat4x4<f32>=mat4x4<f32>(sx,0.0,0.0,0.0,0.0,sy,0.0,0.0,0.0,0.0,sz,0.0,0,0,0,1.0);var modelM:mat4x4<f32>=mat4x4<f32>(c,s,0.0,0.0,-s,c,0.0,0.0,0.0,0.0,1.0,0.0,tx,ty,tz,1.0)*scaleM;output.Position=transformUBO.projection*transformUBO.view*modelM*vec4<f32>(vertexPosition,1.0);output.TexCoord=vertexTexCoord;output.Tint=sprites.models[i_id].tint;output.Opacity=sprites.models[i_id].opacity;return output;}@fragment fn fs_main(@location(0)TexCoord:vec2<f32>,@location(1)Tint:vec4<f32>,@location(2)Opacity:f32)->@location(0)vec4<f32>{var outColor:vec4<f32>=textureSample(myTexture,mySampler,TexCoord);var output=vec4<f32>(outColor.rgb*(1.0-Tint.a)+(Tint.rgb*Tint.a),outColor.a*Opacity);return output;}`;
12371
-
12372
- // src/overlay/constants.js
12373
- var FLOAT32S_PER_SPRITE2 = 12;
12374
-
12375
- // src/overlay/overlay.js
12376
- var _tmpVec4 = vec4.create();
12377
- var _tmpVec3 = vec3.create();
12378
- var overlay_default2 = {
12379
- type: "cobalt:overlay",
12380
- refs: [
12381
- { name: "spritesheet", type: "customResource", access: "read" },
12382
- { name: "color", type: "textView", format: "rgba8unorm", access: "write" }
12383
- ],
12384
- // cobalt event handling functions
12385
- // @params Object cobalt renderer world object
12386
- // @params Object options optional data passed when initing this node
12387
- onInit: async function(cobalt, options = {}) {
12388
- return init6(cobalt, options);
12389
- },
12390
- onRun: function(cobalt, node, webGpuCommandEncoder) {
12391
- draw6(cobalt, node, webGpuCommandEncoder);
12392
- },
12393
- onDestroy: function(cobalt, node) {
12394
- destroy5(node);
12395
- },
12396
- onResize: function(cobalt, node) {
12397
- _writeOverlayBuffer(cobalt, node);
12398
- },
12399
- onViewportPosition: function(cobalt, node) {
12400
- _writeOverlayBuffer(cobalt, node);
12401
- },
12402
- // optional
12403
- customFunctions: { ...public_api_exports }
12404
- };
12405
- async function init6(cobalt, nodeData) {
12406
- const { device } = cobalt;
12407
- const MAX_SPRITE_COUNT = 16192;
12408
- const numInstances = MAX_SPRITE_COUNT;
12409
- const translateFloatCount = 2;
12410
- const translateSize = Float32Array.BYTES_PER_ELEMENT * translateFloatCount;
12411
- const scaleFloatCount = 2;
12412
- const scaleSize = Float32Array.BYTES_PER_ELEMENT * scaleFloatCount;
12413
- const tintFloatCount = 4;
12414
- const tintSize = Float32Array.BYTES_PER_ELEMENT * tintFloatCount;
12415
- const opacityFloatCount = 4;
12416
- const opacitySize = Float32Array.BYTES_PER_ELEMENT * opacityFloatCount;
12417
- const spriteBuffer = device.createBuffer({
12418
- size: (translateSize + scaleSize + tintSize + opacitySize) * numInstances,
12419
- // 4x4 matrix with 4 bytes per float32, per instance
12420
- usage: GPUBufferUsage.VERTEX | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
12421
- });
12422
- const uniformBuffer = device.createBuffer({
12423
- size: 64 * 2,
12424
- // 4x4 matrix with 4 bytes per float32, times 2 matrices (view, projection)
12425
- usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
12426
- });
12427
- const bindGroupLayout = device.createBindGroupLayout({
12428
- entries: [
12429
- {
12430
- binding: 0,
12431
- visibility: GPUShaderStage.VERTEX,
12432
- buffer: {}
12433
- },
12434
- {
12435
- binding: 1,
12436
- visibility: GPUShaderStage.FRAGMENT,
12437
- texture: {}
12438
- },
12439
- {
12440
- binding: 2,
12441
- visibility: GPUShaderStage.FRAGMENT,
12442
- sampler: {}
12443
- },
12444
- {
12445
- binding: 3,
12446
- visibility: GPUShaderStage.VERTEX,
12447
- buffer: {
12448
- type: "read-only-storage"
12449
- }
12450
- }
12451
- ]
12452
- });
12453
- const bindGroup = device.createBindGroup({
12454
- layout: bindGroupLayout,
12455
- entries: [
12456
- {
12457
- binding: 0,
12458
- resource: {
12459
- buffer: uniformBuffer
12460
- }
12461
- },
12462
- {
12463
- binding: 1,
12464
- resource: nodeData.refs.spritesheet.data.colorTexture.view
12465
- },
12466
- {
12467
- binding: 2,
12468
- resource: nodeData.refs.spritesheet.data.colorTexture.sampler
12469
- },
12470
- {
12471
- binding: 3,
12472
- resource: {
12473
- buffer: spriteBuffer
12474
- }
12475
- }
12476
- ]
12477
- });
12478
- const pipelineLayout = device.createPipelineLayout({
12479
- bindGroupLayouts: [bindGroupLayout]
12480
- });
12481
- const pipeline = device.createRenderPipeline({
12482
- label: "overlaysprite",
12483
- vertex: {
12484
- module: device.createShaderModule({
12485
- code: overlay_default
12486
- }),
12487
- entryPoint: "vs_main",
12488
- buffers: [nodeData.refs.spritesheet.data.quads.bufferLayout]
12489
- },
12490
- fragment: {
12491
- module: device.createShaderModule({
12492
- code: overlay_default
12493
- }),
12494
- entryPoint: "fs_main",
12495
- targets: [
12496
- // color
12497
- {
12498
- format: getPreferredFormat(cobalt),
12499
- blend: {
12500
- color: {
12501
- srcFactor: "src-alpha",
12502
- dstFactor: "one-minus-src-alpha"
12503
- },
12504
- alpha: {
12505
- srcFactor: "zero",
12506
- dstFactor: "one"
12507
- }
12508
- }
12509
- }
12510
- ]
12511
- },
12512
- primitive: {
12513
- topology: "triangle-list"
12514
- },
12515
- layout: pipelineLayout
12516
- });
12517
- return {
12518
- // instancedDrawCalls is used to actually perform draw calls within the render pass
12519
- // layout is interleaved with baseVtxIdx (the sprite type), and instanceCount (how many sprites)
12520
- // [
12521
- // baseVtxIdx0, instanceCount0,
12522
- // baseVtxIdx1, instanceCount1,
12523
- // ...
12524
- // ]
12525
- instancedDrawCalls: new Uint32Array(MAX_SPRITE_COUNT * 2),
12526
- instancedDrawCallCount: 0,
12527
- spriteBuffer,
12528
- uniformBuffer,
12529
- pipeline,
12530
- bindGroupLayout,
12531
- bindGroup,
12532
- // actual sprite instance data. ordered by layer, then sprite type
12533
- // this is used to update the spriteBuffer.
12534
- spriteData: new Float32Array(MAX_SPRITE_COUNT * FLOAT32S_PER_SPRITE2),
12535
- spriteCount: 0,
12536
- spriteIndices: /* @__PURE__ */ new Map(),
12537
- // key is spriteId, value is insert index of the sprite. e.g., 0 means 1st sprite , 1 means 2nd sprite, etc.
12538
- // when a sprite is changed the renderpass is dirty, and should have it's instance data copied to the gpu
12539
- dirty: false
12540
- };
12541
- }
12542
- function draw6(cobalt, node, commandEncoder) {
12543
- const { device } = cobalt;
12544
- const loadOp = node.options.loadOp || "load";
12545
- if (node.data.dirty) {
12546
- _rebuildSpriteDrawCalls2(node.data);
12547
- node.data.dirty = false;
12548
- }
12549
- if (node.data.spriteCount > 0) {
12550
- const writeLength = node.data.spriteCount * FLOAT32S_PER_SPRITE2 * Float32Array.BYTES_PER_ELEMENT;
12551
- device.queue.writeBuffer(node.data.spriteBuffer, 0, node.data.spriteData.buffer, 0, writeLength);
12552
- }
12553
- const renderpass = commandEncoder.beginRenderPass({
12554
- label: "overlay",
12555
- colorAttachments: [
12556
- // color
12557
- {
12558
- view: node.refs.color,
12559
- clearValue: cobalt.clearValue,
12560
- loadOp,
12561
- storeOp: "store"
12562
- }
12563
- ]
12564
- });
12565
- renderpass.setPipeline(node.data.pipeline);
12566
- renderpass.setBindGroup(0, node.data.bindGroup);
12567
- renderpass.setVertexBuffer(0, node.refs.spritesheet.data.quads.buffer);
12568
- const vertexCount = 6;
12569
- let baseInstanceIdx = 0;
12570
- for (let i = 0; i < node.data.instancedDrawCallCount; i++) {
12571
- const baseVertexIdx = node.data.instancedDrawCalls[i * 2] * vertexCount;
12572
- const instanceCount = node.data.instancedDrawCalls[i * 2 + 1];
12573
- renderpass.draw(vertexCount, instanceCount, baseVertexIdx, baseInstanceIdx);
12574
- baseInstanceIdx += instanceCount;
12575
- }
12576
- renderpass.end();
12577
- }
12578
- function _rebuildSpriteDrawCalls2(renderPass) {
12579
- let currentSpriteType = -1;
12580
- let instanceCount = 0;
12581
- renderPass.instancedDrawCallCount = 0;
12582
- for (let i = 0; i < renderPass.spriteCount; i++) {
12583
- const spriteType = renderPass.spriteData[i * FLOAT32S_PER_SPRITE2 + 11] & 65535;
12584
- if (spriteType !== currentSpriteType) {
12585
- if (instanceCount > 0) {
12586
- renderPass.instancedDrawCalls[renderPass.instancedDrawCallCount * 2] = currentSpriteType;
12587
- renderPass.instancedDrawCalls[renderPass.instancedDrawCallCount * 2 + 1] = instanceCount;
12588
- renderPass.instancedDrawCallCount++;
12589
- }
12590
- currentSpriteType = spriteType;
12591
- instanceCount = 0;
12592
- }
12593
- instanceCount++;
12594
- }
12595
- if (instanceCount > 0) {
12596
- renderPass.instancedDrawCalls[renderPass.instancedDrawCallCount * 2] = currentSpriteType;
12597
- renderPass.instancedDrawCalls[renderPass.instancedDrawCallCount * 2 + 1] = instanceCount;
12598
- renderPass.instancedDrawCallCount++;
12599
- }
12600
- }
12601
- function _writeOverlayBuffer(cobalt, nodeData) {
12602
- const zoom = 1;
12603
- const GAME_WIDTH = Math.round(cobalt.viewport.width / zoom);
12604
- const GAME_HEIGHT = Math.round(cobalt.viewport.height / zoom);
12605
- const projection = mat4.ortho(0, GAME_WIDTH, GAME_HEIGHT, 0, -10, 10);
12606
- vec3.set(0, 0, 0, _tmpVec3);
12607
- const view = mat4.translation(_tmpVec3);
12608
- cobalt.device.queue.writeBuffer(nodeData.data.uniformBuffer, 0, view.buffer);
12609
- cobalt.device.queue.writeBuffer(nodeData.data.uniformBuffer, 64, projection.buffer);
12610
- }
12611
- function destroy5(nodeData) {
12612
- nodeData.data.instancedDrawCalls = null;
12613
- nodeData.data.bindGroup = null;
12614
- nodeData.data.spriteBuffer.destroy();
12615
- nodeData.data.spriteBuffer = null;
12616
- nodeData.data.uniformBuffer.destroy();
12617
- nodeData.data.uniformBuffer = null;
12618
- nodeData.data.spriteData = null;
12619
- nodeData.data.spriteIndices.clear();
12620
- nodeData.data.spriteIndices = null;
12621
- }
12622
-
12623
12396
  // src/fb-blit/fb-blit.wgsl
12624
12397
  var fb_blit_default = `@binding(0)@group(0)var tileTexture:texture_2d<f32>;@binding(1)@group(0)var tileSampler:sampler;struct Fragment{@builtin(position)Position:vec4<f32>,@location(0)TexCoord:vec2<f32>};const positions=array<vec2<f32>,3>(vec2<f32>(-1.0,-3.0),vec2<f32>(3.0,1.0),vec2<f32>(-1.0,1.0));const uvs=array<vec2<f32>,3>(vec2<f32>(0.0,2.0),vec2<f32>(2.0,0.0),vec2<f32>(0.0,0.0));@vertex fn vs_main(@builtin(vertex_index)VertexIndex:u32)->Fragment{var output:Fragment;output.Position=vec4<f32>(positions[VertexIndex],0.0,1.0);output.TexCoord=vec2<f32>(uvs[VertexIndex]);return output;}@fragment fn fs_main(@location(0)TexCoord:vec2<f32>)->@location(0)vec4<f32>{var col=textureSample(tileTexture,tileSampler,TexCoord);return vec4<f32>(col.rgb,1.0);}`;
12625
12398
 
@@ -12633,10 +12406,10 @@ var fb_blit_default2 = {
12633
12406
  // @params Object cobalt renderer world object
12634
12407
  // @params Object options optional data passed when initing this node
12635
12408
  onInit: async function(cobalt, options = {}) {
12636
- return init7(cobalt, options);
12409
+ return init6(cobalt, options);
12637
12410
  },
12638
12411
  onRun: function(cobalt, node, webGpuCommandEncoder) {
12639
- draw7(cobalt, node, webGpuCommandEncoder);
12412
+ draw6(cobalt, node, webGpuCommandEncoder);
12640
12413
  },
12641
12414
  onDestroy: function(cobalt, node) {
12642
12415
  },
@@ -12646,7 +12419,7 @@ var fb_blit_default2 = {
12646
12419
  onViewportPosition: function(cobalt, node) {
12647
12420
  }
12648
12421
  };
12649
- async function init7(cobalt, node) {
12422
+ async function init6(cobalt, node) {
12650
12423
  const { device } = cobalt;
12651
12424
  const bindGroupLayout = device.createBindGroupLayout({
12652
12425
  entries: [
@@ -12721,7 +12494,7 @@ async function init7(cobalt, node) {
12721
12494
  pipeline
12722
12495
  };
12723
12496
  }
12724
- function draw7(cobalt, node, commandEncoder) {
12497
+ function draw6(cobalt, node, commandEncoder) {
12725
12498
  const { device } = cobalt;
12726
12499
  const renderpass = commandEncoder.beginRenderPass({
12727
12500
  label: "fb-blit",
@@ -13058,13 +12831,6 @@ function perpendicularComponent(inp) {
13058
12831
  return [-inp[1], inp[0]];
13059
12832
  }
13060
12833
 
13061
- // node_modules/round-half-up-symmetric/index.js
13062
- function round(value) {
13063
- if (value >= 0)
13064
- return Math.round(value);
13065
- return value % 0.5 === 0 ? Math.floor(value) : Math.round(value);
13066
- }
13067
-
13068
12834
  // src/primitives/primitives.js
13069
12835
  var _tmpVec32 = vec3.create(0, 0, 0);
13070
12836
  var primitives_default2 = {
@@ -13076,13 +12842,13 @@ var primitives_default2 = {
13076
12842
  // @params Object cobalt renderer world object
13077
12843
  // @params Object options optional data passed when initing this node
13078
12844
  onInit: async function(cobalt, options = {}) {
13079
- return init8(cobalt, options);
12845
+ return init7(cobalt, options);
13080
12846
  },
13081
12847
  onRun: function(cobalt, node, webGpuCommandEncoder) {
13082
- draw8(cobalt, node, webGpuCommandEncoder);
12848
+ draw7(cobalt, node, webGpuCommandEncoder);
13083
12849
  },
13084
12850
  onDestroy: function(cobalt, node) {
13085
- destroy6(node);
12851
+ destroy4(node);
13086
12852
  },
13087
12853
  onResize: function(cobalt, node) {
13088
12854
  _writeMatricesBuffer(cobalt, node);
@@ -13093,7 +12859,7 @@ var primitives_default2 = {
13093
12859
  // optional
13094
12860
  customFunctions: public_api_default
13095
12861
  };
13096
- async function init8(cobalt, node) {
12862
+ async function init7(cobalt, node) {
13097
12863
  const { device } = cobalt;
13098
12864
  const vertices = new Float32Array(1024);
13099
12865
  const vertexBuffer = device.createBuffer({
@@ -13199,7 +12965,7 @@ async function init8(cobalt, node) {
13199
12965
  transforms: [mat3.identity()]
13200
12966
  };
13201
12967
  }
13202
- function draw8(cobalt, node, commandEncoder) {
12968
+ function draw7(cobalt, node, commandEncoder) {
13203
12969
  if (node.data.vertexCount === 0)
13204
12970
  return;
13205
12971
  const { device } = cobalt;
@@ -13240,7 +13006,7 @@ function draw8(cobalt, node, commandEncoder) {
13240
13006
  renderpass.draw(node.data.vertexCount);
13241
13007
  renderpass.end();
13242
13008
  }
13243
- function destroy6(node) {
13009
+ function destroy4(node) {
13244
13010
  node.data.vertexBuffer.destroy();
13245
13011
  node.data.vertexBuffer = null;
13246
13012
  node.data.uniformBuffer.destroy();
@@ -14138,13 +13904,13 @@ var light_default = {
14138
13904
  // @params Object cobalt renderer world object
14139
13905
  // @params Object options optional data passed when initing this node
14140
13906
  onInit: async function(cobalt, options = {}) {
14141
- return init9(cobalt, options);
13907
+ return init8(cobalt, options);
14142
13908
  },
14143
13909
  onRun: function(cobalt, node, webGpuCommandEncoder) {
14144
- draw9(cobalt, node, webGpuCommandEncoder);
13910
+ draw8(cobalt, node, webGpuCommandEncoder);
14145
13911
  },
14146
13912
  onDestroy: function(cobalt, node) {
14147
- destroy7(node);
13913
+ destroy5(node);
14148
13914
  },
14149
13915
  onResize: function(cobalt, node) {
14150
13916
  resize4(cobalt, node);
@@ -14157,7 +13923,7 @@ var light_default = {
14157
13923
  ...public_api_exports2
14158
13924
  }
14159
13925
  };
14160
- async function init9(cobalt, node) {
13926
+ async function init8(cobalt, node) {
14161
13927
  const { device } = cobalt;
14162
13928
  const MAX_LIGHT_COUNT = 256;
14163
13929
  const MAX_LIGHT_SIZE = 256;
@@ -14195,7 +13961,7 @@ async function init9(cobalt, node) {
14195
13961
  lights: []
14196
13962
  };
14197
13963
  }
14198
- function draw9(cobalt, node, commandEncoder) {
13964
+ function draw8(cobalt, node, commandEncoder) {
14199
13965
  if (node.data.lightsBufferNeedsUpdate) {
14200
13966
  const lightsBuffer = node.data.lightsBuffer;
14201
13967
  lightsBuffer.setLights(node.data.lights);
@@ -14223,7 +13989,7 @@ function draw9(cobalt, node, commandEncoder) {
14223
13989
  lightsRenderer.render(renderpass, invertVpMatrix);
14224
13990
  renderpass.end();
14225
13991
  }
14226
- function destroy7(node) {
13992
+ function destroy5(node) {
14227
13993
  node.data.lightsBuffer.destroy();
14228
13994
  node.data.lightsRenderer.destroy();
14229
13995
  }
@@ -14235,10 +14001,386 @@ function resize4(cobalt, node) {
14235
14001
  node.data.viewport.setViewportSize(cobalt.viewport.width, cobalt.viewport.height);
14236
14002
  }
14237
14003
 
14238
- // src/tile/tile.wgsl
14004
+ // src/sprite/public-api.js
14005
+ var public_api_exports3 = {};
14006
+ __export(public_api_exports3, {
14007
+ addSprite: () => addSprite2,
14008
+ clear: () => clear2,
14009
+ removeSprite: () => removeSprite2,
14010
+ setSpriteName: () => setSpriteName2,
14011
+ setSpriteOpacity: () => setSpriteOpacity2,
14012
+ setSpritePosition: () => setSpritePosition2,
14013
+ setSpriteRotation: () => setSpriteRotation2,
14014
+ setSpriteScale: () => setSpriteScale2,
14015
+ setSpriteTint: () => setSpriteTint2
14016
+ });
14017
+ function addSprite2(cobalt, renderPass, name, position, scale, tint, opacity, rotation) {
14018
+ const { idByName } = renderPass.refs.spritesheet.data;
14019
+ renderPass.data.sprites.push({
14020
+ position: vec2.clone(position),
14021
+ sizeX: 1,
14022
+ sizeY: 1,
14023
+ scale: vec2.clone(scale),
14024
+ rotation,
14025
+ opacity,
14026
+ tint: vec4.clone(tint),
14027
+ spriteID: idByName.get(name),
14028
+ id: _uuid()
14029
+ });
14030
+ return renderPass.data.sprites.at(-1).id;
14031
+ }
14032
+ function removeSprite2(cobalt, renderPass, id) {
14033
+ for (let i = 0; i < renderPass.data.sprites.length; i++) {
14034
+ if (renderPass.data.sprites[i].id === id) {
14035
+ renderPass.data.sprites.splice(i, 1);
14036
+ return;
14037
+ }
14038
+ }
14039
+ }
14040
+ function clear2(cobalt, renderPass) {
14041
+ renderPass.data.sprites.length = 0;
14042
+ }
14043
+ function setSpriteName2(cobalt, renderPass, id, name) {
14044
+ const sprite = renderPass.data.sprites.find((s) => s.id === id);
14045
+ if (!sprite)
14046
+ return;
14047
+ const { idByName } = renderPass.refs.spritesheet.data;
14048
+ sprite.spriteID = idByName.get(name);
14049
+ }
14050
+ function setSpritePosition2(cobalt, renderPass, id, position) {
14051
+ const sprite = renderPass.data.sprites.find((s) => s.id === id);
14052
+ if (!sprite)
14053
+ return;
14054
+ vec2.copy(position, sprite.position);
14055
+ }
14056
+ function setSpriteTint2(cobalt, renderPass, id, tint) {
14057
+ const sprite = renderPass.data.sprites.find((s) => s.id === id);
14058
+ if (!sprite)
14059
+ return;
14060
+ vec4.copy(tint, sprite.tint);
14061
+ }
14062
+ function setSpriteOpacity2(cobalt, renderPass, id, opacity) {
14063
+ const sprite = renderPass.data.sprites.find((s) => s.id === id);
14064
+ if (!sprite)
14065
+ return;
14066
+ sprite.opacity = opacity;
14067
+ }
14068
+ function setSpriteRotation2(cobalt, renderPass, id, rotation) {
14069
+ const sprite = renderPass.data.sprites.find((s) => s.id === id);
14070
+ if (!sprite)
14071
+ return;
14072
+ sprite.rotation = rotation;
14073
+ }
14074
+ function setSpriteScale2(cobalt, renderPass, id, scale) {
14075
+ const sprite = renderPass.data.sprites.find((s) => s.id === id);
14076
+ if (!sprite)
14077
+ return;
14078
+ vec2.copy(scale, sprite.scale);
14079
+ }
14080
+
14081
+ // src/sprite/sprite.wgsl
14082
+ var sprite_default3 = `struct ViewParams{view:mat4x4<f32>,proj:mat4x4<f32>};@group(0)@binding(0)var<uniform> uView:ViewParams;@group(0)@binding(1)var uSampler:sampler;@group(0)@binding(2)var uTex:texture_2d<f32>;struct SpriteDesc{uvOrigin:vec2<f32>,uvSpan:vec2<f32>,frameSize:vec2<f32>,centerOffset:vec2<f32>,};@group(0)@binding(3)var<storage,read>Sprites:array<SpriteDesc>;struct VSOut{@builtin(position)pos:vec4<f32>,@location(0)uv:vec2<f32>,@location(1)tint:vec4<f32>,@location(2)opacity:f32,};const corners=array<vec2<f32>,4>(vec2<f32>(-0.5,-0.5),vec2<f32>(0.5,-0.5),vec2<f32>(-0.5,0.5),vec2<f32>(0.5,0.5),);const uvBase=array<vec2<f32>,4>(vec2<f32>(0.0,0.0),vec2<f32>(1.0,0.0),vec2<f32>(0.0,1.0),vec2<f32>(1.0,1.0),);@vertex fn vs_main(@builtin(vertex_index)vid:u32,@location(0)i_pos:vec2<f32>,@location(1)i_size:vec2<f32>,@location(2)i_scale:vec2<f32>,@location(3)i_tint:vec4<f32>,@location(4)i_spriteId:u32,@location(5)i_opacity:f32,@location(6)i_rotation:f32)->VSOut{let rot=i_rotation;let c=cos(rot);let s=sin(rot);let d=Sprites[i_spriteId];let corner=corners[vid];let sizePx=d.frameSize*i_size*i_scale;var local=corner*sizePx;local+=d.centerOffset*i_scale;let rotated=vec2<f32>(local.x*c-local.y*s,local.x*s+local.y*c);let world=vec4<f32>(rotated+i_pos,0.0,1.0);var out:VSOut;out.pos=uView.proj*uView.view*world;out.uv=d.uvOrigin+d.uvSpan*uvBase[vid];out.tint=i_tint;out.opacity=i_opacity;return out;}@fragment fn fs_main(in:VSOut)->@location(0)vec4<f32>{let texel=textureSample(uTex,uSampler,in.uv);return vec4<f32>(texel.rgb*(1.0-in.tint.a)+(in.tint.rgb*in.tint.a),texel.a*in.opacity);}`;
14083
+
14084
+ // src/sprite/sprite.js
14085
+ var _tmpVec33 = vec3.create(0, 0, 0);
14086
+ var INSTANCE_STRIDE2 = 64;
14087
+ var OFF_POS2 = 0;
14088
+ var OFF_SIZE2 = 8;
14089
+ var OFF_SCALE2 = 16;
14090
+ var OFF_TINT2 = 24;
14091
+ var OFF_SPRITEID2 = 40;
14092
+ var OFF_OPACITY2 = 44;
14093
+ var OFF_ROT2 = 48;
14094
+ var sprite_default4 = {
14095
+ type: "cobalt:sprite",
14096
+ refs: [
14097
+ { name: "spritesheet", type: "customResource", access: "read" },
14098
+ {
14099
+ name: "color",
14100
+ type: "textureView",
14101
+ format: "rgba8unorm",
14102
+ access: "write"
14103
+ }
14104
+ ],
14105
+ // cobalt event handling functions
14106
+ // @params Object cobalt renderer world object
14107
+ // @params Object options optional data passed when initing this node
14108
+ onInit: async function(cobalt, options = {}) {
14109
+ return init9(cobalt, options);
14110
+ },
14111
+ onRun: function(cobalt, node, webGpuCommandEncoder) {
14112
+ draw9(cobalt, node, webGpuCommandEncoder);
14113
+ },
14114
+ // Clean up GPU resources. Most WebGPU objects are GC-managed and don't
14115
+ // expose destroy(); buffers/textures/query-sets do.
14116
+ onDestroy: function(cobalt, node) {
14117
+ try {
14118
+ node.data.instanceBuf?.destroy();
14119
+ } catch {
14120
+ }
14121
+ try {
14122
+ node.data.spriteBuf?.destroy();
14123
+ } catch {
14124
+ }
14125
+ try {
14126
+ node.data.uniformBuffer?.destroy();
14127
+ } catch {
14128
+ }
14129
+ node.data.pipeline = null;
14130
+ node.data.bindGroup = null;
14131
+ node.data.bindGroupLayout = null;
14132
+ node.data.instanceStaging = null;
14133
+ node.data.instanceView = null;
14134
+ node.data.sprites.length = 0;
14135
+ node.data.visible.length = 0;
14136
+ },
14137
+ onResize: function(cobalt, node) {
14138
+ _writeSpriteBuffer2(cobalt, node);
14139
+ },
14140
+ onViewportPosition: function(cobalt, node) {
14141
+ _writeSpriteBuffer2(cobalt, node);
14142
+ },
14143
+ // optional
14144
+ customFunctions: {
14145
+ ...public_api_exports3
14146
+ }
14147
+ };
14148
+ async function init9(cobalt, nodeData) {
14149
+ const { device } = cobalt;
14150
+ const { descs, names } = nodeData.refs.spritesheet.data.spritesheet;
14151
+ const uniformBuffer = device.createBuffer({
14152
+ size: 64 * 2,
14153
+ // 4x4 matrix with 4 bytes per float32, times 2 matrices (view, projection)
14154
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
14155
+ });
14156
+ const BYTES_PER_DESC = 8 * 4;
14157
+ const buf = new ArrayBuffer(BYTES_PER_DESC * descs.length);
14158
+ const f32 = new Float32Array(buf);
14159
+ for (let i = 0; i < descs.length; i++) {
14160
+ const d = descs[i];
14161
+ const base = i * 8;
14162
+ f32[base + 0] = d.UvOrigin[0];
14163
+ f32[base + 1] = d.UvOrigin[1];
14164
+ f32[base + 2] = d.UvSpan[0];
14165
+ f32[base + 3] = d.UvSpan[1];
14166
+ f32[base + 4] = d.FrameSize[0];
14167
+ f32[base + 5] = d.FrameSize[1];
14168
+ f32[base + 6] = d.CenterOffset[0];
14169
+ f32[base + 7] = d.CenterOffset[1];
14170
+ }
14171
+ const spriteBuf = device.createBuffer({
14172
+ label: "sprite desc table",
14173
+ size: Math.max(16, buf.byteLength),
14174
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
14175
+ });
14176
+ device.queue.writeBuffer(spriteBuf, 0, buf);
14177
+ const instanceCap = 1024;
14178
+ const instanceBuf = device.createBuffer({
14179
+ label: "sprite instances",
14180
+ size: INSTANCE_STRIDE2 * instanceCap,
14181
+ usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
14182
+ });
14183
+ const instanceStaging = new ArrayBuffer(INSTANCE_STRIDE2 * instanceCap);
14184
+ const instanceView = new DataView(instanceStaging);
14185
+ const shader = device.createShaderModule({ code: sprite_default3 });
14186
+ const bgl = device.createBindGroupLayout({
14187
+ entries: [
14188
+ {
14189
+ binding: 0,
14190
+ visibility: GPUShaderStage.VERTEX,
14191
+ buffer: { type: "uniform" }
14192
+ },
14193
+ {
14194
+ binding: 1,
14195
+ visibility: GPUShaderStage.FRAGMENT,
14196
+ sampler: { type: "filtering" }
14197
+ },
14198
+ {
14199
+ binding: 2,
14200
+ visibility: GPUShaderStage.FRAGMENT,
14201
+ texture: { sampleType: "float" }
14202
+ },
14203
+ {
14204
+ binding: 3,
14205
+ visibility: GPUShaderStage.VERTEX,
14206
+ buffer: { type: "read-only-storage" }
14207
+ }
14208
+ ]
14209
+ });
14210
+ const pipelineLayout = device.createPipelineLayout({
14211
+ bindGroupLayouts: [bgl]
14212
+ });
14213
+ const instLayout = {
14214
+ arrayStride: INSTANCE_STRIDE2,
14215
+ stepMode: "instance",
14216
+ attributes: [
14217
+ { shaderLocation: 0, offset: OFF_POS2, format: "float32x2" },
14218
+ { shaderLocation: 1, offset: OFF_SIZE2, format: "float32x2" },
14219
+ { shaderLocation: 2, offset: OFF_SCALE2, format: "float32x2" },
14220
+ { shaderLocation: 3, offset: OFF_TINT2, format: "float32x4" },
14221
+ { shaderLocation: 4, offset: OFF_SPRITEID2, format: "uint32" },
14222
+ { shaderLocation: 5, offset: OFF_OPACITY2, format: "float32" },
14223
+ { shaderLocation: 6, offset: OFF_ROT2, format: "float32" }
14224
+ ]
14225
+ };
14226
+ const pipeline = device.createRenderPipeline({
14227
+ layout: pipelineLayout,
14228
+ vertex: {
14229
+ module: shader,
14230
+ entryPoint: "vs_main",
14231
+ buffers: [instLayout]
14232
+ },
14233
+ fragment: {
14234
+ module: shader,
14235
+ entryPoint: "fs_main",
14236
+ targets: [
14237
+ // color
14238
+ {
14239
+ format: getPreferredFormat(cobalt),
14240
+ blend: {
14241
+ color: {
14242
+ srcFactor: "src-alpha",
14243
+ dstFactor: "one-minus-src-alpha"
14244
+ },
14245
+ alpha: {
14246
+ srcFactor: "zero",
14247
+ dstFactor: "one"
14248
+ }
14249
+ }
14250
+ }
14251
+ ]
14252
+ },
14253
+ primitive: { topology: "triangle-strip", cullMode: "none" },
14254
+ multisample: { count: 1 }
14255
+ });
14256
+ const bindGroupLayout = bgl;
14257
+ const bindGroup = device.createBindGroup({
14258
+ layout: bgl,
14259
+ entries: [
14260
+ // Uniform buffer (view + proj matrices)
14261
+ { binding: 0, resource: { buffer: uniformBuffer } },
14262
+ { binding: 1, resource: nodeData.refs.spritesheet.data.colorTexture.sampler },
14263
+ { binding: 2, resource: nodeData.refs.spritesheet.data.colorTexture.view },
14264
+ { binding: 3, resource: { buffer: spriteBuf } }
14265
+ ]
14266
+ });
14267
+ return {
14268
+ sprites: [],
14269
+ visible: [],
14270
+ visibleCount: 0,
14271
+ viewRect: { x: 0, y: 0, w: 0, h: 0 },
14272
+ spriteBuf,
14273
+ uniformBuffer,
14274
+ instanceCap,
14275
+ instanceView,
14276
+ instanceBuf,
14277
+ instanceStaging,
14278
+ pipeline,
14279
+ bindGroup
14280
+ };
14281
+ }
14282
+ function ensureCapacity2(cobalt, node, nInstances) {
14283
+ const { instanceCap } = node.data;
14284
+ if (nInstances <= instanceCap)
14285
+ return;
14286
+ let newCap = instanceCap;
14287
+ if (newCap === 0)
14288
+ newCap = 1024;
14289
+ while (newCap < nInstances)
14290
+ newCap *= 2;
14291
+ node.data.instanceBuf.destroy();
14292
+ node.data.instanceBuf = cobalt.device.createBuffer({
14293
+ size: INSTANCE_STRIDE2 * newCap,
14294
+ usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
14295
+ });
14296
+ node.data.instanceStaging = new ArrayBuffer(INSTANCE_STRIDE2 * newCap);
14297
+ node.data.instanceView = new DataView(node.data.instanceStaging);
14298
+ node.data.instanceCap = newCap;
14299
+ }
14300
+ function draw9(cobalt, node, commandEncoder) {
14301
+ const { device, context } = cobalt;
14302
+ const { instanceView, instanceBuf, instanceStaging, pipeline, bindGroup } = node.data;
14303
+ const { descs } = node.refs.spritesheet.data.spritesheet;
14304
+ const viewRect = node.data.viewRect;
14305
+ viewRect.x = cobalt.viewport.position[0];
14306
+ viewRect.y = cobalt.viewport.position[1];
14307
+ viewRect.w = cobalt.viewport.width;
14308
+ viewRect.h = cobalt.viewport.height;
14309
+ node.data.visibleCount = 0;
14310
+ for (const s of node.data.sprites) {
14311
+ const d = descs[s.spriteID];
14312
+ if (!d)
14313
+ continue;
14314
+ if (!node.options.isScreenSpace) {
14315
+ const sx = d.FrameSize[0] * s.sizeX * s.scale[0] * 0.5;
14316
+ const sy = d.FrameSize[1] * s.sizeY * s.scale[1] * 0.5;
14317
+ const rad = Math.hypot(sx, sy);
14318
+ const x = s.position[0], y = s.position[1];
14319
+ if (x + rad < viewRect.x || x - rad > viewRect.x + viewRect.w || y + rad < viewRect.y || y - rad > viewRect.y + viewRect.h)
14320
+ continue;
14321
+ }
14322
+ node.data.visible[node.data.visibleCount] = s;
14323
+ node.data.visibleCount++;
14324
+ }
14325
+ ensureCapacity2(cobalt, node, node.data.visibleCount);
14326
+ for (let i = 0; i < node.data.visibleCount; i++) {
14327
+ const base = i * INSTANCE_STRIDE2;
14328
+ const s = node.data.visible[i];
14329
+ const tint = s.tint;
14330
+ instanceView.setFloat32(base + OFF_POS2 + 0, s.position[0], true);
14331
+ instanceView.setFloat32(base + OFF_POS2 + 4, s.position[1], true);
14332
+ instanceView.setFloat32(base + OFF_SIZE2 + 0, s.sizeX, true);
14333
+ instanceView.setFloat32(base + OFF_SIZE2 + 4, s.sizeY, true);
14334
+ instanceView.setFloat32(base + OFF_SCALE2 + 0, s.scale[0], true);
14335
+ instanceView.setFloat32(base + OFF_SCALE2 + 4, s.scale[1], true);
14336
+ instanceView.setFloat32(base + OFF_TINT2 + 0, tint[0], true);
14337
+ instanceView.setFloat32(base + OFF_TINT2 + 4, tint[1], true);
14338
+ instanceView.setFloat32(base + OFF_TINT2 + 8, tint[2], true);
14339
+ instanceView.setFloat32(base + OFF_TINT2 + 12, tint[3], true);
14340
+ instanceView.setUint32(base + OFF_SPRITEID2, s.spriteID >>> 0, true);
14341
+ instanceView.setFloat32(base + OFF_OPACITY2, s.opacity, true);
14342
+ instanceView.setFloat32(base + OFF_ROT2, s.rotation, true);
14343
+ }
14344
+ device.queue.writeBuffer(instanceBuf, 0, instanceStaging, 0, node.data.visibleCount * INSTANCE_STRIDE2);
14345
+ const loadOp = node.options.loadOp || "load";
14346
+ const pass = commandEncoder.beginRenderPass({
14347
+ label: "sprite renderpass",
14348
+ colorAttachments: [
14349
+ // color
14350
+ {
14351
+ view: node.refs.color,
14352
+ clearValue: cobalt.clearValue,
14353
+ loadOp,
14354
+ storeOp: "store"
14355
+ }
14356
+ ]
14357
+ });
14358
+ pass.setPipeline(pipeline);
14359
+ pass.setBindGroup(0, bindGroup);
14360
+ pass.setVertexBuffer(0, instanceBuf);
14361
+ if (node.data.visibleCount)
14362
+ pass.draw(4, node.data.visibleCount, 0, 0);
14363
+ pass.end();
14364
+ }
14365
+ function _writeSpriteBuffer2(cobalt, node) {
14366
+ const { device, viewport } = cobalt;
14367
+ const GAME_WIDTH = viewport.width / viewport.zoom;
14368
+ const GAME_HEIGHT = viewport.height / viewport.zoom;
14369
+ const projection = mat4.ortho(0, GAME_WIDTH, GAME_HEIGHT, 0, -10, 10);
14370
+ if (!!node.options.isScreenSpace) {
14371
+ vec3.set(0, 0, 0, _tmpVec33);
14372
+ } else {
14373
+ vec3.set(-round(viewport.position[0]), -round(viewport.position[1]), 0, _tmpVec33);
14374
+ }
14375
+ const view = mat4.translation(_tmpVec33);
14376
+ device.queue.writeBuffer(node.data.uniformBuffer, 0, view.buffer);
14377
+ device.queue.writeBuffer(node.data.uniformBuffer, 64, projection.buffer);
14378
+ }
14379
+
14380
+ // src/tile-hdr/tile.wgsl
14239
14381
  var tile_default2 = `struct TransformData{viewOffset:vec2<f32>,viewportSize:vec2<f32>,inverseAtlasTextureSize:vec2<f32>,tileSize:f32,inverseTileSize:f32,};struct TileScroll{scrollScale:vec2<f32>};const positions=array<vec2<f32>,3>(vec2<f32>(-1.0,-3.0),vec2<f32>(3.0,1.0),vec2<f32>(-1.0,1.0));const uvs=array<vec2<f32>,3>(vec2<f32>(0.0,2.0),vec2<f32>(2.0,0.0),vec2<f32>(0.0,0.0));@binding(0)@group(0)var<uniform> myScroll:TileScroll;@binding(1)@group(0)var tileTexture:texture_2d<f32>;@binding(2)@group(0)var tileSampler:sampler;@binding(0)@group(1)var<uniform> transformUBO:TransformData;@binding(1)@group(1)var atlasTexture:texture_2d<f32>;@binding(2)@group(1)var atlasSampler:sampler;struct Fragment{@builtin(position)Position:vec4<f32>,@location(0)TexCoord:vec2<f32>};@vertex fn vs_main(@builtin(instance_index)i_id:u32,@builtin(vertex_index)VertexIndex:u32)->Fragment{var vertexPosition=vec2<f32>(positions[VertexIndex]);var vertexTexCoord=vec2<f32>(uvs[VertexIndex]);var output:Fragment;let inverseTileTextureSize=1/vec2<f32>(textureDimensions(tileTexture,0));var scrollScale=myScroll.scrollScale;var viewOffset:vec2<f32>=transformUBO.viewOffset*scrollScale;let PixelCoord=(vertexTexCoord*transformUBO.viewportSize)+viewOffset;output.TexCoord=PixelCoord/transformUBO.tileSize;output.Position=vec4<f32>(vertexPosition,0.0,1.0);return output;}@fragment fn fs_main(@location(0)TexCoord:vec2<f32>)->@location(0)vec4<f32>{var tilemapCoord=floor(TexCoord);var u_tilemapSize=vec2<f32>(textureDimensions(tileTexture,0));var tileFoo=fract((tilemapCoord+vec2<f32>(0.5,0.5))/u_tilemapSize);var tile=floor(textureSample(tileTexture,tileSampler,tileFoo)*255.0);if(tile.x==255&&tile.y==255){discard;}var u_tilesetSize=vec2<f32>(textureDimensions(atlasTexture,0))/transformUBO.tileSize;let u_tileUVMinBounds=vec2<f32>(0.5/transformUBO.tileSize,0.5/transformUBO.tileSize);let u_tileUVMaxBounds=vec2<f32>((transformUBO.tileSize-0.5)/transformUBO.tileSize,(transformUBO.tileSize-0.5)/transformUBO.tileSize);var texcoord=clamp(fract(TexCoord),u_tileUVMinBounds,u_tileUVMaxBounds);var tileCoord=(tile.xy+texcoord)/u_tilesetSize;var color=textureSample(atlasTexture,atlasSampler,tileCoord);if(color.a<=0.1){discard;}return color;}`;
14240
14382
 
14241
- // src/tile/atlas.js
14383
+ // src/tile-hdr/atlas.js
14242
14384
  var _buf = new Float32Array(8);
14243
14385
  var atlas_default = {
14244
14386
  type: "cobalt:tileAtlas",
@@ -14251,7 +14393,7 @@ var atlas_default = {
14251
14393
  onRun: function(cobalt, node, webGpuCommandEncoder) {
14252
14394
  },
14253
14395
  onDestroy: function(cobalt, node) {
14254
- destroy8(data);
14396
+ destroy6(data);
14255
14397
  },
14256
14398
  onResize: function(cobalt, node) {
14257
14399
  _writeTileBuffer(cobalt, node);
@@ -14350,7 +14492,7 @@ async function init10(cobalt, nodeData) {
14350
14492
  entryPoint: "fs_main",
14351
14493
  targets: [
14352
14494
  {
14353
- format: "rgba16float",
14495
+ format: nodeData.options.outputFormat || getPreferredFormat(cobalt),
14354
14496
  blend: {
14355
14497
  color: {
14356
14498
  srcFactor: "src-alpha",
@@ -14380,13 +14522,13 @@ async function init10(cobalt, nodeData) {
14380
14522
  tileScale: nodeData.options.tileScale
14381
14523
  };
14382
14524
  }
14383
- function destroy8(data2) {
14525
+ function destroy6(data2) {
14384
14526
  data2.atlasMaterial.texture.destroy();
14385
14527
  data2.atlasMaterial.texture = void 0;
14386
14528
  }
14387
14529
  function _writeTileBuffer(c, nodeData) {
14388
- _buf[0] = c.viewport.position[0];
14389
- _buf[1] = c.viewport.position[1];
14530
+ _buf[0] = round(c.viewport.position[0]);
14531
+ _buf[1] = round(c.viewport.position[1]);
14390
14532
  const tile = nodeData.data;
14391
14533
  const { tileScale, tileSize } = tile;
14392
14534
  const GAME_WIDTH = c.viewport.width / c.viewport.zoom;
@@ -14400,61 +14542,32 @@ function _writeTileBuffer(c, nodeData) {
14400
14542
  c.device.queue.writeBuffer(tile.uniformBuffer, 0, _buf, 0, 8);
14401
14543
  }
14402
14544
 
14403
- // src/sprite/read-spritesheet.js
14404
- function readSpriteSheet(spritesheetJson) {
14405
- const spriteFloatCount = 5 * 6;
14406
- const spriteCount = Object.keys(spritesheetJson.frames).length;
14407
- const vertices = new Float32Array(spriteCount * spriteFloatCount);
14408
- const locations = [];
14409
- const spriteMeta = {};
14410
- let i = 0;
14411
- for (const frameName in spritesheetJson.frames) {
14412
- const frame = spritesheetJson.frames[frameName];
14413
- locations.push(frameName);
14414
- spriteMeta[frameName] = frame.sourceSize;
14415
- const minX = -0.5 + frame.spriteSourceSize.x / frame.sourceSize.w;
14416
- const minY = -0.5 + frame.spriteSourceSize.y / frame.sourceSize.h;
14417
- const maxX = -0.5 + (frame.spriteSourceSize.x + frame.spriteSourceSize.w) / frame.sourceSize.w;
14418
- const maxY = -0.5 + (frame.spriteSourceSize.y + frame.spriteSourceSize.h) / frame.sourceSize.h;
14419
- const p0 = [minX, minY, 0];
14420
- const p1 = [minX, maxY, 0];
14421
- const p2 = [maxX, maxY, 0];
14422
- const p3 = [maxX, minY, 0];
14423
- const minU = 0 + frame.frame.x / spritesheetJson.meta.size.w;
14424
- const minV = 0 + frame.frame.y / spritesheetJson.meta.size.h;
14425
- const maxU = 0 + (frame.frame.x + frame.frame.w) / spritesheetJson.meta.size.w;
14426
- const maxV = 0 + (frame.frame.y + frame.frame.h) / spritesheetJson.meta.size.h;
14427
- const uv0 = [minU, minV];
14428
- const uv1 = [minU, maxV];
14429
- const uv2 = [maxU, maxV];
14430
- const uv3 = [maxU, minV];
14431
- vertices.set(p0, i);
14432
- vertices.set(uv0, i + 3);
14433
- vertices.set(p1, i + 5);
14434
- vertices.set(uv1, i + 8);
14435
- vertices.set(p2, i + 10);
14436
- vertices.set(uv2, i + 13);
14437
- vertices.set(p0, i + 15);
14438
- vertices.set(uv0, i + 18);
14439
- vertices.set(p2, i + 20);
14440
- vertices.set(uv2, i + 23);
14441
- vertices.set(p3, i + 25);
14442
- vertices.set(uv3, i + 28);
14443
- i += spriteFloatCount;
14545
+ // src/spritesheet/read-spritesheet.js
14546
+ function buildSpriteTableFromTexturePacker(doc) {
14547
+ const atlasW = doc.meta.size.w;
14548
+ const atlasH = doc.meta.size.h;
14549
+ const names = Object.keys(doc.frames).sort();
14550
+ const descs = new Array(names.length);
14551
+ for (let i = 0; i < names.length; i++) {
14552
+ const fr = doc.frames[names[i]];
14553
+ const fx = fr.frame.x, fy = fr.frame.y, fw = fr.frame.w, fh = fr.frame.h;
14554
+ const offX = fx / atlasW, offY = fy / atlasH;
14555
+ const spanX = fw / atlasW, spanY = fh / atlasH;
14556
+ const sw = fr.sourceSize.w, sh = fr.sourceSize.h;
14557
+ const ox = fr.spriteSourceSize.x, oy = fr.spriteSourceSize.y;
14558
+ const cx = ox + fw * 0.5 - sw * 0.5;
14559
+ const cy = oy + fh * 0.5 - sh * 0.5;
14560
+ descs[i] = {
14561
+ UvOrigin: [offX, offY],
14562
+ UvSpan: [spanX, spanY],
14563
+ FrameSize: [fw, fh],
14564
+ CenterOffset: [cx, cy]
14565
+ };
14444
14566
  }
14445
- return {
14446
- /*spriteCount, */
14447
- spriteMeta,
14448
- locations,
14449
- vertices
14450
- };
14567
+ return { descs, names };
14451
14568
  }
14452
14569
 
14453
- // src/sprite/sprite.wgsl
14454
- var sprite_default2 = `struct TransformData{view:mat4x4<f32>,projection:mat4x4<f32>};struct Sprite{translate:vec2<f32>,scale:vec2<f32>,tint:vec4<f32>,opacity:f32,rotation:f32,emissiveIntensity:f32,sortValue:f32,};struct SpritesBuffer{models:array<Sprite>,};@binding(0)@group(0)var<uniform> transformUBO:TransformData;@binding(1)@group(0)var myTexture:texture_2d<f32>;@binding(2)@group(0)var mySampler:sampler;@binding(3)@group(0)var<storage,read>sprites:SpritesBuffer;@binding(4)@group(0)var emissiveTexture:texture_2d<f32>;struct Fragment{@builtin(position)Position:vec4<f32>,@location(0)TexCoord:vec2<f32>,@location(1)Tint:vec4<f32>,@location(2)Opacity:f32,};struct GBufferOutput{@location(0)color:vec4<f32>,@location(1)emissive:vec4<f32>,}@vertex fn vs_main(@builtin(instance_index)i_id:u32,@location(0)vertexPosition:vec3<f32>,@location(1)vertexTexCoord:vec2<f32>)->Fragment{var output:Fragment;var sx:f32=sprites.models[i_id].scale.x;var sy:f32=sprites.models[i_id].scale.y;var sz:f32=1.0;var rot:f32=sprites.models[i_id].rotation;var tx:f32=sprites.models[i_id].translate.x;var ty:f32=sprites.models[i_id].translate.y;var tz:f32=0;var s=sin(rot);var c=cos(rot);var scaleM:mat4x4<f32>=mat4x4<f32>(sx,0.0,0.0,0.0,0.0,sy,0.0,0.0,0.0,0.0,sz,0.0,0,0,0,1.0);var modelM:mat4x4<f32>=mat4x4<f32>(c,s,0.0,0.0,-s,c,0.0,0.0,0.0,0.0,1.0,0.0,tx,ty,tz,1.0)*scaleM;output.Position=transformUBO.projection*transformUBO.view*modelM*vec4<f32>(vertexPosition,1.0);output.TexCoord=vertexTexCoord;output.Tint=sprites.models[i_id].tint;output.Opacity=sprites.models[i_id].opacity;return output;}@fragment fn fs_main(@location(0)TexCoord:vec2<f32>,@location(1)Tint:vec4<f32>,@location(2)Opacity:f32)->GBufferOutput{var output:GBufferOutput;var outColor:vec4<f32>=textureSample(myTexture,mySampler,TexCoord);output.color=vec4<f32>(outColor.rgb*(1.0-Tint.a)+(Tint.rgb*Tint.a),outColor.a*Opacity);let emissive=textureSample(emissiveTexture,mySampler,TexCoord);output.emissive=vec4(emissive.rgb,1.0)*emissive.a;return output;}`;
14455
-
14456
- // src/sprite/spritesheet.js
14457
- var _tmpVec33 = vec3.create(0, 0, 0);
14570
+ // src/spritesheet/spritesheet.js
14458
14571
  var spritesheet_default = {
14459
14572
  type: "cobalt:spritesheet",
14460
14573
  refs: [],
@@ -14466,13 +14579,11 @@ var spritesheet_default = {
14466
14579
  onRun: function(cobalt, node, webGpuCommandEncoder) {
14467
14580
  },
14468
14581
  onDestroy: function(cobalt, node) {
14469
- destroy9(node);
14582
+ destroy7(node);
14470
14583
  },
14471
14584
  onResize: function(cobalt, node) {
14472
- _writeSpriteBuffer(cobalt, node);
14473
14585
  },
14474
14586
  onViewportPosition: function(cobalt, node) {
14475
- _writeSpriteBuffer(cobalt, node);
14476
14587
  }
14477
14588
  };
14478
14589
  async function init11(cobalt, node) {
@@ -14480,127 +14591,30 @@ async function init11(cobalt, node) {
14480
14591
  let spritesheet, colorTexture, emissiveTexture;
14481
14592
  const format = node.options.format || "rgba8unorm";
14482
14593
  if (canvas) {
14483
- spritesheet = await fetchJson(node.options.spriteSheetJsonUrl);
14484
- spritesheet = readSpriteSheet(spritesheet);
14594
+ spritesheet = await fetch(node.options.spriteSheetJsonUrl);
14595
+ spritesheet = await spritesheet.json();
14596
+ spritesheet = buildSpriteTableFromTexturePacker(spritesheet);
14485
14597
  colorTexture = await createTextureFromUrl(cobalt, "sprite", node.options.colorTextureUrl, format);
14486
14598
  emissiveTexture = await createTextureFromUrl(cobalt, "emissive sprite", node.options.emissiveTextureUrl, format);
14487
14599
  canvas.style.imageRendering = "pixelated";
14488
14600
  } else {
14489
- spritesheet = readSpriteSheet(node.options.spriteSheetJson);
14601
+ spritesheet = buildSpriteTableFromTexturePacker(node.options.spriteSheetJson);
14490
14602
  colorTexture = await createTextureFromBuffer(cobalt, "sprite", node.options.colorTexture, format);
14491
14603
  emissiveTexture = await createTextureFromBuffer(cobalt, "emissive sprite", node.options.emissiveTexture, format);
14492
14604
  }
14493
- const quads = createSpriteQuads(device, spritesheet);
14494
- const uniformBuffer = device.createBuffer({
14495
- size: 64 * 2,
14496
- // 4x4 matrix with 4 bytes per float32, times 2 matrices (view, projection)
14497
- usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
14498
- });
14499
- const bindGroupLayout = device.createBindGroupLayout({
14500
- entries: [
14501
- {
14502
- binding: 0,
14503
- visibility: GPUShaderStage.VERTEX,
14504
- buffer: {}
14505
- },
14506
- {
14507
- binding: 1,
14508
- visibility: GPUShaderStage.FRAGMENT,
14509
- texture: {}
14510
- },
14511
- {
14512
- binding: 2,
14513
- visibility: GPUShaderStage.FRAGMENT,
14514
- sampler: {}
14515
- },
14516
- {
14517
- binding: 3,
14518
- visibility: GPUShaderStage.VERTEX,
14519
- buffer: {
14520
- type: "read-only-storage"
14521
- }
14522
- },
14523
- {
14524
- binding: 4,
14525
- visibility: GPUShaderStage.FRAGMENT,
14526
- texture: {}
14527
- }
14528
- ]
14529
- });
14530
- const pipelineLayout = device.createPipelineLayout({
14531
- bindGroupLayouts: [bindGroupLayout]
14532
- });
14533
- const pipeline = device.createRenderPipeline({
14534
- label: "spritesheet",
14535
- vertex: {
14536
- module: device.createShaderModule({
14537
- code: sprite_default2
14538
- }),
14539
- entryPoint: "vs_main",
14540
- buffers: [quads.bufferLayout]
14541
- },
14542
- fragment: {
14543
- module: device.createShaderModule({
14544
- code: sprite_default2
14545
- }),
14546
- entryPoint: "fs_main",
14547
- targets: [
14548
- // color
14549
- {
14550
- format: "rgba16float",
14551
- blend: {
14552
- color: {
14553
- srcFactor: "src-alpha",
14554
- dstFactor: "one-minus-src-alpha"
14555
- },
14556
- alpha: {
14557
- srcFactor: "zero",
14558
- dstFactor: "one"
14559
- }
14560
- }
14561
- },
14562
- // emissive
14563
- {
14564
- format: "rgba16float"
14565
- }
14566
- ]
14567
- },
14568
- primitive: {
14569
- topology: "triangle-list"
14570
- },
14571
- layout: pipelineLayout
14572
- });
14605
+ const idByName = new Map(spritesheet.names.map((n, i) => [n, i]));
14573
14606
  return {
14574
- pipeline,
14575
- uniformBuffer,
14576
- // perspective and view matrices for the camera
14577
- quads,
14578
14607
  colorTexture,
14579
14608
  emissiveTexture,
14580
- bindGroupLayout,
14581
- spritesheet
14609
+ spritesheet,
14610
+ idByName
14582
14611
  };
14583
14612
  }
14584
- function destroy9(node) {
14613
+ function destroy7(node) {
14585
14614
  node.data.quads.buffer.destroy();
14586
14615
  node.data.colorTexture.buffer.destroy();
14587
- node.data.uniformBuffer.destroy();
14588
14616
  node.data.emissiveTexture.texture.destroy();
14589
14617
  }
14590
- async function fetchJson(url) {
14591
- const raw = await fetch(url);
14592
- return raw.json();
14593
- }
14594
- function _writeSpriteBuffer(cobalt, node) {
14595
- const { device, viewport } = cobalt;
14596
- const GAME_WIDTH = viewport.width / viewport.zoom;
14597
- const GAME_HEIGHT = viewport.height / viewport.zoom;
14598
- const projection = mat4.ortho(0, GAME_WIDTH, GAME_HEIGHT, 0, -10, 10);
14599
- vec3.set(-round(viewport.position[0]), -round(viewport.position[1]), 0, _tmpVec33);
14600
- const view = mat4.translation(_tmpVec33);
14601
- device.queue.writeBuffer(node.data.uniformBuffer, 0, view.buffer);
14602
- device.queue.writeBuffer(node.data.uniformBuffer, 64, projection.buffer);
14603
- }
14604
14618
 
14605
14619
  // src/fb-texture/fb-texture.js
14606
14620
  var fb_texture_default = {
@@ -14614,7 +14628,7 @@ var fb_texture_default = {
14614
14628
  onRun: function(cobalt, node, webGpuCommandEncoder) {
14615
14629
  },
14616
14630
  onDestroy: function(cobalt, node) {
14617
- destroy10(data);
14631
+ destroy8(data);
14618
14632
  },
14619
14633
  onResize: function(cobalt, node) {
14620
14634
  resize5(cobalt, node);
@@ -14628,12 +14642,12 @@ async function init12(cobalt, node) {
14628
14642
  const { format, label, mip_count, usage, viewportScale } = node.options;
14629
14643
  return createTexture(device, label, cobalt.viewport.width * viewportScale, cobalt.viewport.height * viewportScale, mip_count, format, usage);
14630
14644
  }
14631
- function destroy10(node) {
14645
+ function destroy8(node) {
14632
14646
  node.data.texture.destroy();
14633
14647
  }
14634
14648
  function resize5(cobalt, node) {
14635
14649
  const { device } = cobalt;
14636
- destroy10(node);
14650
+ destroy8(node);
14637
14651
  const { width, height } = cobalt.viewport;
14638
14652
  const { options } = node;
14639
14653
  const scale = node.options.viewportScale;
@@ -14673,12 +14687,12 @@ async function init13(ctx, viewportWidth, viewportHeight) {
14673
14687
  "cobalt:spritesheet": spritesheet_default,
14674
14688
  "cobalt:fbTexture": fb_texture_default,
14675
14689
  // builtin run nodes
14690
+ "cobalt:sprite": sprite_default4,
14676
14691
  "cobalt:bloom": bloom_default2,
14677
14692
  "cobalt:composite": scene_composite_default2,
14678
- "cobalt:sprite": sprite_default,
14679
- "cobalt:tile": tile_default,
14693
+ "cobalt:spriteHDR": sprite_default2,
14694
+ "cobalt:tileHDR": tile_default,
14680
14695
  "cobalt:displacement": displacement_default2,
14681
- "cobalt:overlay": overlay_default2,
14682
14696
  "cobalt:fbBlit": fb_blit_default2,
14683
14697
  "cobalt:primitives": primitives_default2,
14684
14698
  "cobalt:light": light_default