@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.
- package/CHANGELOG.md +19 -0
- package/bundle.js +1318 -1304
- package/examples/01-primitives/index.html +1 -1
- package/examples/02-sprites/entity-sprite.js +10 -15
- package/examples/02-sprites/hdr.html +321 -0
- package/examples/02-sprites/index.html +21 -120
- package/examples/02-sprites/system-renderer.js +2 -2
- package/examples/03-tiles/index.html +87 -32
- package/examples/03-tiles/system-renderer.js +2 -2
- package/examples/04-overlay/index.html +178 -21
- package/examples/05-bloom/index.html +23 -23
- package/examples/05-bloom/system-renderer.js +2 -2
- package/examples/06-displacement/index.html +20 -112
- package/examples/06-displacement/system-renderer.js +2 -2
- package/examples/08-light/index.html +51 -123
- package/package.json +1 -1
- package/src/cobalt.js +8 -8
- package/src/sprite/public-api.js +57 -177
- package/src/sprite/sprite.js +301 -177
- package/src/sprite/sprite.wgsl +68 -87
- package/src/sprite-hdr/public-api.js +95 -0
- package/src/sprite-hdr/sprite.js +414 -0
- package/src/sprite-hdr/sprite.wgsl +101 -0
- package/src/{sprite → spritesheet}/create-sprite-quads.js +11 -11
- package/src/{sprite → spritesheet}/read-spritesheet.js +62 -28
- package/src/spritesheet/spritesheet.js +75 -0
- package/src/{tile → tile-hdr}/atlas.js +5 -3
- package/src/{tile → tile-hdr}/tile.js +15 -6
- package/examples/04-overlay/deps.js +0 -1
- package/src/overlay/constants.js +0 -1
- package/src/overlay/overlay.js +0 -343
- package/src/overlay/overlay.wgsl +0 -88
- package/src/sprite/constants.js +0 -1
- package/src/sprite/sorted-binary-insert.js +0 -45
- package/src/sprite/spritesheet.js +0 -215
- /package/examples/02-sprites/{Game.js → Global.js} +0 -0
- /package/examples/03-tiles/{Game.js → Global.js} +0 -0
- /package/examples/05-bloom/{Game.js → Global.js} +0 -0
- /package/examples/06-displacement/{Game.js → Global.js} +0 -0
- /package/examples/08-light/{Game.js → Global.js} +0 -0
- /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
|
-
//
|
|
7905
|
-
function
|
|
7906
|
-
|
|
7907
|
-
|
|
7908
|
-
|
|
7909
|
-
|
|
7910
|
-
|
|
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
|
-
|
|
8133
|
-
|
|
8134
|
-
|
|
8135
|
-
|
|
8136
|
-
|
|
8137
|
-
|
|
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
|
-
|
|
8140
|
-
|
|
8141
|
-
|
|
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
|
-
|
|
8144
|
-
|
|
8145
|
-
|
|
8146
|
-
|
|
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
|
-
|
|
8174
|
-
|
|
8175
|
-
|
|
8176
|
-
|
|
8177
|
-
|
|
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
|
-
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
|
|
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
|
-
|
|
8267
|
-
|
|
8268
|
-
|
|
8269
|
-
|
|
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
|
-
|
|
8276
|
-
|
|
8277
|
-
|
|
8278
|
-
|
|
8279
|
-
|
|
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
|
-
|
|
8350
|
-
|
|
8351
|
-
|
|
8352
|
-
|
|
8353
|
-
|
|
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
|
-
|
|
8357
|
-
|
|
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
|
-
|
|
8360
|
-
|
|
8361
|
-
|
|
8362
|
-
|
|
8363
|
-
|
|
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
|
-
|
|
8371
|
-
|
|
8372
|
-
|
|
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
|
-
|
|
8381
|
-
|
|
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
|
-
|
|
8388
|
-
|
|
8389
|
-
|
|
8390
|
-
|
|
8391
|
-
|
|
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
|
-
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
|
|
8399
|
-
|
|
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
|
-
|
|
8408
|
-
|
|
8409
|
-
|
|
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
|
-
|
|
8422
|
-
|
|
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
|
-
|
|
8425
|
-
|
|
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
|
-
|
|
8430
|
-
|
|
8431
|
-
|
|
8432
|
-
|
|
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
|
-
|
|
8494
|
-
|
|
8495
|
-
|
|
8496
|
-
|
|
8497
|
-
return
|
|
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
|
-
|
|
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
|
-
|
|
8502
|
-
|
|
8503
|
-
this.renderBundle = null;
|
|
8015
|
+
function dot(a, b) {
|
|
8016
|
+
return a[0] * b[0] + a[1] * b[1];
|
|
8504
8017
|
}
|
|
8505
|
-
|
|
8506
|
-
|
|
8507
|
-
|
|
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
|
-
|
|
8510
|
-
|
|
8511
|
-
|
|
8512
|
-
|
|
8513
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
12409
|
+
return init6(cobalt, options);
|
|
12637
12410
|
},
|
|
12638
12411
|
onRun: function(cobalt, node, webGpuCommandEncoder) {
|
|
12639
|
-
|
|
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
|
|
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
|
|
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
|
|
12845
|
+
return init7(cobalt, options);
|
|
13080
12846
|
},
|
|
13081
12847
|
onRun: function(cobalt, node, webGpuCommandEncoder) {
|
|
13082
|
-
|
|
12848
|
+
draw7(cobalt, node, webGpuCommandEncoder);
|
|
13083
12849
|
},
|
|
13084
12850
|
onDestroy: function(cobalt, node) {
|
|
13085
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
13907
|
+
return init8(cobalt, options);
|
|
14142
13908
|
},
|
|
14143
13909
|
onRun: function(cobalt, node, webGpuCommandEncoder) {
|
|
14144
|
-
|
|
13910
|
+
draw8(cobalt, node, webGpuCommandEncoder);
|
|
14145
13911
|
},
|
|
14146
13912
|
onDestroy: function(cobalt, node) {
|
|
14147
|
-
|
|
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
|
|
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
|
|
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
|
|
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/
|
|
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
|
-
|
|
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:
|
|
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
|
|
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/
|
|
14404
|
-
function
|
|
14405
|
-
const
|
|
14406
|
-
const
|
|
14407
|
-
const
|
|
14408
|
-
const
|
|
14409
|
-
|
|
14410
|
-
|
|
14411
|
-
|
|
14412
|
-
const
|
|
14413
|
-
|
|
14414
|
-
|
|
14415
|
-
const
|
|
14416
|
-
const
|
|
14417
|
-
const
|
|
14418
|
-
|
|
14419
|
-
|
|
14420
|
-
|
|
14421
|
-
|
|
14422
|
-
|
|
14423
|
-
|
|
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/
|
|
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
|
-
|
|
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
|
|
14484
|
-
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 =
|
|
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
|
|
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
|
-
|
|
14581
|
-
|
|
14609
|
+
spritesheet,
|
|
14610
|
+
idByName
|
|
14582
14611
|
};
|
|
14583
14612
|
}
|
|
14584
|
-
function
|
|
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
|
-
|
|
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
|
|
14645
|
+
function destroy8(node) {
|
|
14632
14646
|
node.data.texture.destroy();
|
|
14633
14647
|
}
|
|
14634
14648
|
function resize5(cobalt, node) {
|
|
14635
14649
|
const { device } = cobalt;
|
|
14636
|
-
|
|
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:
|
|
14679
|
-
"cobalt:
|
|
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
|