@footgun/cobalt 0.6.15 → 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 +16 -0
- package/bundle.js +1313 -1301
- 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 +33 -35
- 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 +9 -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,844 +7866,159 @@ __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
|
-
if (!nodeData.data.material.texture)
|
|
8314
|
-
return;
|
|
8315
|
-
const { device } = cobalt;
|
|
8316
|
-
const loadOp = nodeData.options.loadOp || "load";
|
|
8317
|
-
const renderpass = commandEncoder.beginRenderPass({
|
|
8318
|
-
label: "tile",
|
|
8319
|
-
colorAttachments: [
|
|
8320
|
-
{
|
|
8321
|
-
view: nodeData.refs.hdr.data.view,
|
|
8322
|
-
clearValue: cobalt.clearValue,
|
|
8323
|
-
loadOp,
|
|
8324
|
-
storeOp: "store"
|
|
8325
|
-
}
|
|
8326
|
-
]
|
|
8327
|
-
});
|
|
8328
|
-
const tileAtlas = nodeData.refs.tileAtlas.data;
|
|
8329
|
-
renderpass.setPipeline(tileAtlas.pipeline);
|
|
8330
|
-
renderpass.setBindGroup(0, nodeData.data.bindGroup);
|
|
8331
|
-
renderpass.setBindGroup(1, tileAtlas.atlasBindGroup);
|
|
8332
|
-
renderpass.draw(3);
|
|
8333
|
-
renderpass.end();
|
|
8334
|
-
}
|
|
8335
|
-
function destroy3(nodeData) {
|
|
8336
|
-
nodeData.data.material.texture.destroy();
|
|
8337
|
-
nodeData.data.material.texture = void 0;
|
|
8338
|
-
}
|
|
8339
|
-
|
|
8340
|
-
// src/displacement/triangles-buffer.ts
|
|
8341
|
-
var TrianglesBuffer = class {
|
|
8342
|
-
device;
|
|
8343
|
-
floatsPerSprite = 6;
|
|
8344
|
-
// vec2(translate) + vec2(scale) + rotation + opacity
|
|
8345
|
-
bufferGpu;
|
|
8346
|
-
bufferNeedsUpdate = false;
|
|
8347
|
-
sprites = /* @__PURE__ */ new Map();
|
|
8348
|
-
get spriteCount() {
|
|
8349
|
-
return this.sprites.size;
|
|
8350
|
-
}
|
|
8351
|
-
constructor(params) {
|
|
8352
|
-
this.device = params.device;
|
|
8353
|
-
this.bufferGpu = this.device.createBuffer({
|
|
8354
|
-
size: params.maxSpriteCount * this.floatsPerSprite * Float32Array.BYTES_PER_ELEMENT,
|
|
8355
|
-
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
|
|
8356
|
-
});
|
|
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;
|
|
8357
7932
|
}
|
|
8358
|
-
|
|
8359
|
-
|
|
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;
|
|
8360
7938
|
}
|
|
8361
|
-
|
|
8362
|
-
|
|
8363
|
-
|
|
8364
|
-
|
|
8365
|
-
|
|
8366
|
-
|
|
8367
|
-
|
|
8368
|
-
|
|
8369
|
-
|
|
8370
|
-
|
|
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);
|
|
8371
7949
|
}
|
|
8372
|
-
|
|
8373
|
-
const
|
|
8374
|
-
|
|
8375
|
-
|
|
8376
|
-
|
|
8377
|
-
const triangleData = this.buildTriangleData(triangleVertices);
|
|
8378
|
-
this.sprites.set(triangleId, triangleData);
|
|
8379
|
-
this.bufferNeedsUpdate = true;
|
|
8380
|
-
return triangleId;
|
|
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;
|
|
8381
7955
|
}
|
|
8382
|
-
|
|
8383
|
-
|
|
8384
|
-
|
|
8385
|
-
}
|
|
8386
|
-
this.sprites.delete(triangleId);
|
|
8387
|
-
this.bufferNeedsUpdate = true;
|
|
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;
|
|
8388
7959
|
}
|
|
8389
|
-
|
|
8390
|
-
|
|
8391
|
-
throw new Error(`Unknown triangle "${triangleId}".`);
|
|
8392
|
-
}
|
|
8393
|
-
const triangleData = this.buildTriangleData(triangleVertices);
|
|
8394
|
-
this.sprites.set(triangleId, triangleData);
|
|
8395
|
-
this.bufferNeedsUpdate = true;
|
|
7960
|
+
function equals(a, b) {
|
|
7961
|
+
return a[0] === b[0] && a[1] === b[1];
|
|
8396
7962
|
}
|
|
8397
|
-
|
|
8398
|
-
|
|
8399
|
-
|
|
8400
|
-
|
|
8401
|
-
|
|
8402
|
-
triangleVertices[1][1],
|
|
8403
|
-
triangleVertices[2][0],
|
|
8404
|
-
triangleVertices[2][1]
|
|
8405
|
-
];
|
|
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;
|
|
8406
7968
|
}
|
|
8407
|
-
|
|
8408
|
-
|
|
8409
|
-
|
|
8410
|
-
|
|
8411
|
-
|
|
8412
|
-
bufferGpu;
|
|
8413
|
-
needsUpdate = true;
|
|
8414
|
-
constructor(params) {
|
|
8415
|
-
this.device = params.device;
|
|
8416
|
-
this.bufferGpu = this.device.createBuffer({
|
|
8417
|
-
label: "DisplacementParametersBuffer buffer",
|
|
8418
|
-
size: 16,
|
|
8419
|
-
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
8420
|
-
});
|
|
8421
|
-
this.setParameters(params.initialParameters);
|
|
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;
|
|
8422
7974
|
}
|
|
8423
|
-
|
|
8424
|
-
|
|
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;
|
|
8425
7980
|
}
|
|
8426
|
-
|
|
8427
|
-
|
|
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;
|
|
8428
7986
|
}
|
|
8429
|
-
|
|
8430
|
-
|
|
8431
|
-
|
|
8432
|
-
|
|
8433
|
-
|
|
8434
|
-
// src/displacement/displacement-composition.ts
|
|
8435
|
-
var DisplacementComposition = class {
|
|
8436
|
-
device;
|
|
8437
|
-
targetFormat;
|
|
8438
|
-
renderPipeline;
|
|
8439
|
-
colorSampler;
|
|
8440
|
-
noiseSampler;
|
|
8441
|
-
displacementParametersBuffer;
|
|
8442
|
-
renderBundle = null;
|
|
8443
|
-
colorTextureView;
|
|
8444
|
-
noiseMapTextureView;
|
|
8445
|
-
displacementTextureView;
|
|
8446
|
-
constructor(params) {
|
|
8447
|
-
this.device = params.device;
|
|
8448
|
-
this.targetFormat = params.targetFormat;
|
|
8449
|
-
this.colorTextureView = params.colorTextureView;
|
|
8450
|
-
this.noiseMapTextureView = params.noiseMapTextureView;
|
|
8451
|
-
this.displacementTextureView = params.displacementTextureView;
|
|
8452
|
-
this.displacementParametersBuffer = params.displacementParametersBuffer;
|
|
8453
|
-
const shaderModule = this.device.createShaderModule({
|
|
8454
|
-
label: "DisplacementComposition shader module",
|
|
8455
|
-
code: composition_default
|
|
8456
|
-
});
|
|
8457
|
-
this.renderPipeline = this.device.createRenderPipeline({
|
|
8458
|
-
label: "DisplacementComposition renderpipeline",
|
|
8459
|
-
layout: "auto",
|
|
8460
|
-
vertex: {
|
|
8461
|
-
module: shaderModule,
|
|
8462
|
-
entryPoint: "main_vertex"
|
|
8463
|
-
},
|
|
8464
|
-
fragment: {
|
|
8465
|
-
module: shaderModule,
|
|
8466
|
-
entryPoint: "main_fragment",
|
|
8467
|
-
targets: [{
|
|
8468
|
-
format: params.targetFormat
|
|
8469
|
-
}]
|
|
8470
|
-
},
|
|
8471
|
-
primitive: {
|
|
8472
|
-
cullMode: "none",
|
|
8473
|
-
topology: "triangle-strip"
|
|
8474
|
-
}
|
|
8475
|
-
});
|
|
8476
|
-
this.noiseSampler = this.device.createSampler({
|
|
8477
|
-
label: "DisplacementComposition noisesampler",
|
|
8478
|
-
addressModeU: "repeat",
|
|
8479
|
-
addressModeV: "repeat",
|
|
8480
|
-
addressModeW: "repeat",
|
|
8481
|
-
magFilter: "linear",
|
|
8482
|
-
minFilter: "linear",
|
|
8483
|
-
mipmapFilter: "linear"
|
|
8484
|
-
});
|
|
8485
|
-
this.colorSampler = this.device.createSampler({
|
|
8486
|
-
label: "DisplacementComposition colorSampler",
|
|
8487
|
-
addressModeU: "clamp-to-edge",
|
|
8488
|
-
addressModeV: "clamp-to-edge",
|
|
8489
|
-
addressModeW: "clamp-to-edge",
|
|
8490
|
-
magFilter: "linear",
|
|
8491
|
-
minFilter: "linear",
|
|
8492
|
-
mipmapFilter: "linear"
|
|
8493
|
-
});
|
|
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;
|
|
8494
7992
|
}
|
|
8495
|
-
|
|
8496
|
-
|
|
8497
|
-
|
|
8498
|
-
|
|
8499
|
-
|
|
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;
|
|
8500
7999
|
}
|
|
8501
|
-
|
|
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;
|
|
8502
8005
|
}
|
|
8503
|
-
|
|
8504
|
-
|
|
8505
|
-
|
|
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;
|
|
8506
8014
|
}
|
|
8507
|
-
|
|
8508
|
-
|
|
8509
|
-
this.renderBundle = null;
|
|
8015
|
+
function dot(a, b) {
|
|
8016
|
+
return a[0] * b[0] + a[1] * b[1];
|
|
8510
8017
|
}
|
|
8511
|
-
|
|
8512
|
-
|
|
8513
|
-
|
|
8514
|
-
|
|
8515
|
-
buildRenderBundle() {
|
|
8516
|
-
const bindgroup = this.device.createBindGroup({
|
|
8517
|
-
label: "DisplacementComposition bindgroup 0",
|
|
8518
|
-
layout: this.renderPipeline.getBindGroupLayout(0),
|
|
8519
|
-
entries: [
|
|
8520
|
-
{
|
|
8521
|
-
binding: 0,
|
|
8522
|
-
resource: { buffer: this.displacementParametersBuffer.bufferGpu }
|
|
8523
|
-
},
|
|
8524
|
-
{
|
|
8525
|
-
binding: 1,
|
|
8526
|
-
resource: this.colorTextureView
|
|
8527
|
-
},
|
|
8528
|
-
{
|
|
8529
|
-
binding: 2,
|
|
8530
|
-
resource: this.colorSampler
|
|
8531
|
-
},
|
|
8532
|
-
{
|
|
8533
|
-
binding: 3,
|
|
8534
|
-
resource: this.noiseMapTextureView
|
|
8535
|
-
},
|
|
8536
|
-
{
|
|
8537
|
-
binding: 4,
|
|
8538
|
-
resource: this.noiseSampler
|
|
8539
|
-
},
|
|
8540
|
-
{
|
|
8541
|
-
binding: 5,
|
|
8542
|
-
resource: this.displacementTextureView
|
|
8543
|
-
}
|
|
8544
|
-
]
|
|
8545
|
-
});
|
|
8546
|
-
const renderBundleEncoder = this.device.createRenderBundleEncoder({
|
|
8547
|
-
label: "DisplacementComposition renderbundle encoder",
|
|
8548
|
-
colorFormats: [this.targetFormat]
|
|
8549
|
-
});
|
|
8550
|
-
renderBundleEncoder.setPipeline(this.renderPipeline);
|
|
8551
|
-
renderBundleEncoder.setBindGroup(0, bindgroup);
|
|
8552
|
-
renderBundleEncoder.draw(4);
|
|
8553
|
-
return renderBundleEncoder.finish({ label: "DisplacementComposition renderbundle" });
|
|
8554
|
-
}
|
|
8555
|
-
};
|
|
8556
|
-
|
|
8557
|
-
// src/displacement/displacement.wgsl
|
|
8558
|
-
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;}`;
|
|
8559
|
-
|
|
8560
|
-
// node_modules/wgpu-matrix/dist/3.x/wgpu-matrix.module.js
|
|
8561
|
-
function wrapConstructor(OriginalConstructor, modifier) {
|
|
8562
|
-
return class extends OriginalConstructor {
|
|
8563
|
-
constructor(...args) {
|
|
8564
|
-
super(...args);
|
|
8565
|
-
modifier(this);
|
|
8566
|
-
}
|
|
8567
|
-
};
|
|
8568
|
-
}
|
|
8569
|
-
var ZeroArray = wrapConstructor(Array, (a) => a.fill(0));
|
|
8570
|
-
var EPSILON = 1e-6;
|
|
8571
|
-
function getAPIImpl$5(Ctor) {
|
|
8572
|
-
function create(x = 0, y = 0) {
|
|
8573
|
-
const newDst = new Ctor(2);
|
|
8574
|
-
if (x !== void 0) {
|
|
8575
|
-
newDst[0] = x;
|
|
8576
|
-
if (y !== void 0) {
|
|
8577
|
-
newDst[1] = y;
|
|
8578
|
-
}
|
|
8579
|
-
}
|
|
8580
|
-
return newDst;
|
|
8581
|
-
}
|
|
8582
|
-
const fromValues = create;
|
|
8583
|
-
function set(x, y, dst) {
|
|
8584
|
-
const newDst = dst ?? new Ctor(2);
|
|
8585
|
-
newDst[0] = x;
|
|
8586
|
-
newDst[1] = y;
|
|
8587
|
-
return newDst;
|
|
8588
|
-
}
|
|
8589
|
-
function ceil(v, dst) {
|
|
8590
|
-
const newDst = dst ?? new Ctor(2);
|
|
8591
|
-
newDst[0] = Math.ceil(v[0]);
|
|
8592
|
-
newDst[1] = Math.ceil(v[1]);
|
|
8593
|
-
return newDst;
|
|
8594
|
-
}
|
|
8595
|
-
function floor(v, dst) {
|
|
8596
|
-
const newDst = dst ?? new Ctor(2);
|
|
8597
|
-
newDst[0] = Math.floor(v[0]);
|
|
8598
|
-
newDst[1] = Math.floor(v[1]);
|
|
8599
|
-
return newDst;
|
|
8600
|
-
}
|
|
8601
|
-
function round2(v, dst) {
|
|
8602
|
-
const newDst = dst ?? new Ctor(2);
|
|
8603
|
-
newDst[0] = Math.round(v[0]);
|
|
8604
|
-
newDst[1] = Math.round(v[1]);
|
|
8605
|
-
return newDst;
|
|
8606
|
-
}
|
|
8607
|
-
function clamp(v, min2 = 0, max2 = 1, dst) {
|
|
8608
|
-
const newDst = dst ?? new Ctor(2);
|
|
8609
|
-
newDst[0] = Math.min(max2, Math.max(min2, v[0]));
|
|
8610
|
-
newDst[1] = Math.min(max2, Math.max(min2, v[1]));
|
|
8611
|
-
return newDst;
|
|
8612
|
-
}
|
|
8613
|
-
function add(a, b, dst) {
|
|
8614
|
-
const newDst = dst ?? new Ctor(2);
|
|
8615
|
-
newDst[0] = a[0] + b[0];
|
|
8616
|
-
newDst[1] = a[1] + b[1];
|
|
8617
|
-
return newDst;
|
|
8618
|
-
}
|
|
8619
|
-
function addScaled(a, b, scale2, dst) {
|
|
8620
|
-
const newDst = dst ?? new Ctor(2);
|
|
8621
|
-
newDst[0] = a[0] + b[0] * scale2;
|
|
8622
|
-
newDst[1] = a[1] + b[1] * scale2;
|
|
8623
|
-
return newDst;
|
|
8624
|
-
}
|
|
8625
|
-
function angle(a, b) {
|
|
8626
|
-
const ax = a[0];
|
|
8627
|
-
const ay = a[1];
|
|
8628
|
-
const bx = b[0];
|
|
8629
|
-
const by = b[1];
|
|
8630
|
-
const mag1 = Math.sqrt(ax * ax + ay * ay);
|
|
8631
|
-
const mag2 = Math.sqrt(bx * bx + by * by);
|
|
8632
|
-
const mag = mag1 * mag2;
|
|
8633
|
-
const cosine = mag && dot(a, b) / mag;
|
|
8634
|
-
return Math.acos(cosine);
|
|
8635
|
-
}
|
|
8636
|
-
function subtract(a, b, dst) {
|
|
8637
|
-
const newDst = dst ?? new Ctor(2);
|
|
8638
|
-
newDst[0] = a[0] - b[0];
|
|
8639
|
-
newDst[1] = a[1] - b[1];
|
|
8640
|
-
return newDst;
|
|
8641
|
-
}
|
|
8642
|
-
const sub = subtract;
|
|
8643
|
-
function equalsApproximately(a, b) {
|
|
8644
|
-
return Math.abs(a[0] - b[0]) < EPSILON && Math.abs(a[1] - b[1]) < EPSILON;
|
|
8645
|
-
}
|
|
8646
|
-
function equals(a, b) {
|
|
8647
|
-
return a[0] === b[0] && a[1] === b[1];
|
|
8648
|
-
}
|
|
8649
|
-
function lerp(a, b, t, dst) {
|
|
8650
|
-
const newDst = dst ?? new Ctor(2);
|
|
8651
|
-
newDst[0] = a[0] + t * (b[0] - a[0]);
|
|
8652
|
-
newDst[1] = a[1] + t * (b[1] - a[1]);
|
|
8653
|
-
return newDst;
|
|
8654
|
-
}
|
|
8655
|
-
function lerpV(a, b, t, dst) {
|
|
8656
|
-
const newDst = dst ?? new Ctor(2);
|
|
8657
|
-
newDst[0] = a[0] + t[0] * (b[0] - a[0]);
|
|
8658
|
-
newDst[1] = a[1] + t[1] * (b[1] - a[1]);
|
|
8659
|
-
return newDst;
|
|
8660
|
-
}
|
|
8661
|
-
function max(a, b, dst) {
|
|
8662
|
-
const newDst = dst ?? new Ctor(2);
|
|
8663
|
-
newDst[0] = Math.max(a[0], b[0]);
|
|
8664
|
-
newDst[1] = Math.max(a[1], b[1]);
|
|
8665
|
-
return newDst;
|
|
8666
|
-
}
|
|
8667
|
-
function min(a, b, dst) {
|
|
8668
|
-
const newDst = dst ?? new Ctor(2);
|
|
8669
|
-
newDst[0] = Math.min(a[0], b[0]);
|
|
8670
|
-
newDst[1] = Math.min(a[1], b[1]);
|
|
8671
|
-
return newDst;
|
|
8672
|
-
}
|
|
8673
|
-
function mulScalar(v, k, dst) {
|
|
8674
|
-
const newDst = dst ?? new Ctor(2);
|
|
8675
|
-
newDst[0] = v[0] * k;
|
|
8676
|
-
newDst[1] = v[1] * k;
|
|
8677
|
-
return newDst;
|
|
8678
|
-
}
|
|
8679
|
-
const scale = mulScalar;
|
|
8680
|
-
function divScalar(v, k, dst) {
|
|
8681
|
-
const newDst = dst ?? new Ctor(2);
|
|
8682
|
-
newDst[0] = v[0] / k;
|
|
8683
|
-
newDst[1] = v[1] / k;
|
|
8684
|
-
return newDst;
|
|
8685
|
-
}
|
|
8686
|
-
function inverse(v, dst) {
|
|
8687
|
-
const newDst = dst ?? new Ctor(2);
|
|
8688
|
-
newDst[0] = 1 / v[0];
|
|
8689
|
-
newDst[1] = 1 / v[1];
|
|
8690
|
-
return newDst;
|
|
8691
|
-
}
|
|
8692
|
-
const invert = inverse;
|
|
8693
|
-
function cross(a, b, dst) {
|
|
8694
|
-
const newDst = dst ?? new Ctor(3);
|
|
8695
|
-
const z = a[0] * b[1] - a[1] * b[0];
|
|
8696
|
-
newDst[0] = 0;
|
|
8697
|
-
newDst[1] = 0;
|
|
8698
|
-
newDst[2] = z;
|
|
8699
|
-
return newDst;
|
|
8700
|
-
}
|
|
8701
|
-
function dot(a, b) {
|
|
8702
|
-
return a[0] * b[0] + a[1] * b[1];
|
|
8703
|
-
}
|
|
8704
|
-
function length(v) {
|
|
8705
|
-
const v0 = v[0];
|
|
8706
|
-
const v1 = v[1];
|
|
8707
|
-
return Math.sqrt(v0 * v0 + v1 * v1);
|
|
8018
|
+
function length(v) {
|
|
8019
|
+
const v0 = v[0];
|
|
8020
|
+
const v1 = v[1];
|
|
8021
|
+
return Math.sqrt(v0 * v0 + v1 * v1);
|
|
8708
8022
|
}
|
|
8709
8023
|
const len = length;
|
|
8710
8024
|
function lengthSq(v) {
|
|
@@ -12059,6 +11373,754 @@ var {
|
|
|
12059
11373
|
vec4: vec4n
|
|
12060
11374
|
} = wgpuMatrixAPI(ZeroArray, Array, Array, Array, Array, Array);
|
|
12061
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
|
+
|
|
12062
12124
|
// src/displacement/displacement-texture.ts
|
|
12063
12125
|
var DisplacementTexture = class {
|
|
12064
12126
|
device;
|
|
@@ -12239,7 +12301,7 @@ var displacement_default2 = {
|
|
|
12239
12301
|
draw5(cobalt, node, webGpuCommandEncoder);
|
|
12240
12302
|
},
|
|
12241
12303
|
onDestroy: function(cobalt, node) {
|
|
12242
|
-
|
|
12304
|
+
destroy3(node);
|
|
12243
12305
|
},
|
|
12244
12306
|
onResize: function(cobalt, node) {
|
|
12245
12307
|
node.data.displacementTexture.resize(cobalt.viewport.width, cobalt.viewport.height);
|
|
@@ -12320,7 +12382,7 @@ function draw5(cobalt, node, commandEncoder) {
|
|
|
12320
12382
|
renderpass.executeBundles([node.data.displacementComposition.getRenderBundle()]);
|
|
12321
12383
|
renderpass.end();
|
|
12322
12384
|
}
|
|
12323
|
-
function
|
|
12385
|
+
function destroy3(node) {
|
|
12324
12386
|
node.data.trianglesBuffer.destroy();
|
|
12325
12387
|
node.data.trianglesBuffer = null;
|
|
12326
12388
|
node.data.displacementParameters.destroy();
|
|
@@ -12331,297 +12393,6 @@ function destroy4(node) {
|
|
|
12331
12393
|
node.data.displacementComposition = null;
|
|
12332
12394
|
}
|
|
12333
12395
|
|
|
12334
|
-
// src/sprite/create-sprite-quads.js
|
|
12335
|
-
function createSpriteQuads(device, spritesheet) {
|
|
12336
|
-
const vertices = spritesheet.vertices;
|
|
12337
|
-
const usage = GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST;
|
|
12338
|
-
const descriptor = {
|
|
12339
|
-
size: vertices.byteLength,
|
|
12340
|
-
usage,
|
|
12341
|
-
// make this memory space accessible from the CPU (host visible)
|
|
12342
|
-
mappedAtCreation: true
|
|
12343
|
-
};
|
|
12344
|
-
const buffer = device.createBuffer(descriptor);
|
|
12345
|
-
new Float32Array(buffer.getMappedRange()).set(vertices);
|
|
12346
|
-
buffer.unmap();
|
|
12347
|
-
const bufferLayout = {
|
|
12348
|
-
arrayStride: 20,
|
|
12349
|
-
stepMode: "vertex",
|
|
12350
|
-
attributes: [
|
|
12351
|
-
// position
|
|
12352
|
-
{
|
|
12353
|
-
shaderLocation: 0,
|
|
12354
|
-
format: "float32x3",
|
|
12355
|
-
offset: 0
|
|
12356
|
-
},
|
|
12357
|
-
// uv
|
|
12358
|
-
{
|
|
12359
|
-
shaderLocation: 1,
|
|
12360
|
-
format: "float32x2",
|
|
12361
|
-
offset: 12
|
|
12362
|
-
}
|
|
12363
|
-
]
|
|
12364
|
-
};
|
|
12365
|
-
return {
|
|
12366
|
-
buffer,
|
|
12367
|
-
bufferLayout
|
|
12368
|
-
};
|
|
12369
|
-
}
|
|
12370
|
-
|
|
12371
|
-
// src/overlay/overlay.wgsl
|
|
12372
|
-
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;}`;
|
|
12373
|
-
|
|
12374
|
-
// src/overlay/constants.js
|
|
12375
|
-
var FLOAT32S_PER_SPRITE2 = 12;
|
|
12376
|
-
|
|
12377
|
-
// src/overlay/overlay.js
|
|
12378
|
-
var _tmpVec4 = vec4.create();
|
|
12379
|
-
var _tmpVec3 = vec3.create();
|
|
12380
|
-
var overlay_default2 = {
|
|
12381
|
-
type: "cobalt:overlay",
|
|
12382
|
-
refs: [
|
|
12383
|
-
{ name: "spritesheet", type: "customResource", access: "read" },
|
|
12384
|
-
{ name: "color", type: "textView", format: "rgba8unorm", access: "write" }
|
|
12385
|
-
],
|
|
12386
|
-
// cobalt event handling functions
|
|
12387
|
-
// @params Object cobalt renderer world object
|
|
12388
|
-
// @params Object options optional data passed when initing this node
|
|
12389
|
-
onInit: async function(cobalt, options = {}) {
|
|
12390
|
-
return init6(cobalt, options);
|
|
12391
|
-
},
|
|
12392
|
-
onRun: function(cobalt, node, webGpuCommandEncoder) {
|
|
12393
|
-
draw6(cobalt, node, webGpuCommandEncoder);
|
|
12394
|
-
},
|
|
12395
|
-
onDestroy: function(cobalt, node) {
|
|
12396
|
-
destroy5(node);
|
|
12397
|
-
},
|
|
12398
|
-
onResize: function(cobalt, node) {
|
|
12399
|
-
_writeOverlayBuffer(cobalt, node);
|
|
12400
|
-
},
|
|
12401
|
-
onViewportPosition: function(cobalt, node) {
|
|
12402
|
-
_writeOverlayBuffer(cobalt, node);
|
|
12403
|
-
},
|
|
12404
|
-
// optional
|
|
12405
|
-
customFunctions: { ...public_api_exports }
|
|
12406
|
-
};
|
|
12407
|
-
async function init6(cobalt, nodeData) {
|
|
12408
|
-
const { device } = cobalt;
|
|
12409
|
-
const MAX_SPRITE_COUNT = 16192;
|
|
12410
|
-
const numInstances = MAX_SPRITE_COUNT;
|
|
12411
|
-
const translateFloatCount = 2;
|
|
12412
|
-
const translateSize = Float32Array.BYTES_PER_ELEMENT * translateFloatCount;
|
|
12413
|
-
const scaleFloatCount = 2;
|
|
12414
|
-
const scaleSize = Float32Array.BYTES_PER_ELEMENT * scaleFloatCount;
|
|
12415
|
-
const tintFloatCount = 4;
|
|
12416
|
-
const tintSize = Float32Array.BYTES_PER_ELEMENT * tintFloatCount;
|
|
12417
|
-
const opacityFloatCount = 4;
|
|
12418
|
-
const opacitySize = Float32Array.BYTES_PER_ELEMENT * opacityFloatCount;
|
|
12419
|
-
const spriteBuffer = device.createBuffer({
|
|
12420
|
-
size: (translateSize + scaleSize + tintSize + opacitySize) * numInstances,
|
|
12421
|
-
// 4x4 matrix with 4 bytes per float32, per instance
|
|
12422
|
-
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
|
|
12423
|
-
});
|
|
12424
|
-
const uniformBuffer = device.createBuffer({
|
|
12425
|
-
size: 64 * 2,
|
|
12426
|
-
// 4x4 matrix with 4 bytes per float32, times 2 matrices (view, projection)
|
|
12427
|
-
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
12428
|
-
});
|
|
12429
|
-
const bindGroupLayout = device.createBindGroupLayout({
|
|
12430
|
-
entries: [
|
|
12431
|
-
{
|
|
12432
|
-
binding: 0,
|
|
12433
|
-
visibility: GPUShaderStage.VERTEX,
|
|
12434
|
-
buffer: {}
|
|
12435
|
-
},
|
|
12436
|
-
{
|
|
12437
|
-
binding: 1,
|
|
12438
|
-
visibility: GPUShaderStage.FRAGMENT,
|
|
12439
|
-
texture: {}
|
|
12440
|
-
},
|
|
12441
|
-
{
|
|
12442
|
-
binding: 2,
|
|
12443
|
-
visibility: GPUShaderStage.FRAGMENT,
|
|
12444
|
-
sampler: {}
|
|
12445
|
-
},
|
|
12446
|
-
{
|
|
12447
|
-
binding: 3,
|
|
12448
|
-
visibility: GPUShaderStage.VERTEX,
|
|
12449
|
-
buffer: {
|
|
12450
|
-
type: "read-only-storage"
|
|
12451
|
-
}
|
|
12452
|
-
}
|
|
12453
|
-
]
|
|
12454
|
-
});
|
|
12455
|
-
const bindGroup = device.createBindGroup({
|
|
12456
|
-
layout: bindGroupLayout,
|
|
12457
|
-
entries: [
|
|
12458
|
-
{
|
|
12459
|
-
binding: 0,
|
|
12460
|
-
resource: {
|
|
12461
|
-
buffer: uniformBuffer
|
|
12462
|
-
}
|
|
12463
|
-
},
|
|
12464
|
-
{
|
|
12465
|
-
binding: 1,
|
|
12466
|
-
resource: nodeData.refs.spritesheet.data.colorTexture.view
|
|
12467
|
-
},
|
|
12468
|
-
{
|
|
12469
|
-
binding: 2,
|
|
12470
|
-
resource: nodeData.refs.spritesheet.data.colorTexture.sampler
|
|
12471
|
-
},
|
|
12472
|
-
{
|
|
12473
|
-
binding: 3,
|
|
12474
|
-
resource: {
|
|
12475
|
-
buffer: spriteBuffer
|
|
12476
|
-
}
|
|
12477
|
-
}
|
|
12478
|
-
]
|
|
12479
|
-
});
|
|
12480
|
-
const pipelineLayout = device.createPipelineLayout({
|
|
12481
|
-
bindGroupLayouts: [bindGroupLayout]
|
|
12482
|
-
});
|
|
12483
|
-
const pipeline = device.createRenderPipeline({
|
|
12484
|
-
label: "overlaysprite",
|
|
12485
|
-
vertex: {
|
|
12486
|
-
module: device.createShaderModule({
|
|
12487
|
-
code: overlay_default
|
|
12488
|
-
}),
|
|
12489
|
-
entryPoint: "vs_main",
|
|
12490
|
-
buffers: [nodeData.refs.spritesheet.data.quads.bufferLayout]
|
|
12491
|
-
},
|
|
12492
|
-
fragment: {
|
|
12493
|
-
module: device.createShaderModule({
|
|
12494
|
-
code: overlay_default
|
|
12495
|
-
}),
|
|
12496
|
-
entryPoint: "fs_main",
|
|
12497
|
-
targets: [
|
|
12498
|
-
// color
|
|
12499
|
-
{
|
|
12500
|
-
format: getPreferredFormat(cobalt),
|
|
12501
|
-
blend: {
|
|
12502
|
-
color: {
|
|
12503
|
-
srcFactor: "src-alpha",
|
|
12504
|
-
dstFactor: "one-minus-src-alpha"
|
|
12505
|
-
},
|
|
12506
|
-
alpha: {
|
|
12507
|
-
srcFactor: "zero",
|
|
12508
|
-
dstFactor: "one"
|
|
12509
|
-
}
|
|
12510
|
-
}
|
|
12511
|
-
}
|
|
12512
|
-
]
|
|
12513
|
-
},
|
|
12514
|
-
primitive: {
|
|
12515
|
-
topology: "triangle-list"
|
|
12516
|
-
},
|
|
12517
|
-
layout: pipelineLayout
|
|
12518
|
-
});
|
|
12519
|
-
return {
|
|
12520
|
-
// instancedDrawCalls is used to actually perform draw calls within the render pass
|
|
12521
|
-
// layout is interleaved with baseVtxIdx (the sprite type), and instanceCount (how many sprites)
|
|
12522
|
-
// [
|
|
12523
|
-
// baseVtxIdx0, instanceCount0,
|
|
12524
|
-
// baseVtxIdx1, instanceCount1,
|
|
12525
|
-
// ...
|
|
12526
|
-
// ]
|
|
12527
|
-
instancedDrawCalls: new Uint32Array(MAX_SPRITE_COUNT * 2),
|
|
12528
|
-
instancedDrawCallCount: 0,
|
|
12529
|
-
spriteBuffer,
|
|
12530
|
-
uniformBuffer,
|
|
12531
|
-
pipeline,
|
|
12532
|
-
bindGroupLayout,
|
|
12533
|
-
bindGroup,
|
|
12534
|
-
// actual sprite instance data. ordered by layer, then sprite type
|
|
12535
|
-
// this is used to update the spriteBuffer.
|
|
12536
|
-
spriteData: new Float32Array(MAX_SPRITE_COUNT * FLOAT32S_PER_SPRITE2),
|
|
12537
|
-
spriteCount: 0,
|
|
12538
|
-
spriteIndices: /* @__PURE__ */ new Map(),
|
|
12539
|
-
// key is spriteId, value is insert index of the sprite. e.g., 0 means 1st sprite , 1 means 2nd sprite, etc.
|
|
12540
|
-
// when a sprite is changed the renderpass is dirty, and should have it's instance data copied to the gpu
|
|
12541
|
-
dirty: false
|
|
12542
|
-
};
|
|
12543
|
-
}
|
|
12544
|
-
function draw6(cobalt, node, commandEncoder) {
|
|
12545
|
-
const { device } = cobalt;
|
|
12546
|
-
const loadOp = node.options.loadOp || "load";
|
|
12547
|
-
if (node.data.dirty) {
|
|
12548
|
-
_rebuildSpriteDrawCalls2(node.data);
|
|
12549
|
-
node.data.dirty = false;
|
|
12550
|
-
}
|
|
12551
|
-
if (node.data.spriteCount > 0) {
|
|
12552
|
-
const writeLength = node.data.spriteCount * FLOAT32S_PER_SPRITE2 * Float32Array.BYTES_PER_ELEMENT;
|
|
12553
|
-
device.queue.writeBuffer(node.data.spriteBuffer, 0, node.data.spriteData.buffer, 0, writeLength);
|
|
12554
|
-
}
|
|
12555
|
-
const renderpass = commandEncoder.beginRenderPass({
|
|
12556
|
-
label: "overlay",
|
|
12557
|
-
colorAttachments: [
|
|
12558
|
-
// color
|
|
12559
|
-
{
|
|
12560
|
-
view: node.refs.color,
|
|
12561
|
-
clearValue: cobalt.clearValue,
|
|
12562
|
-
loadOp,
|
|
12563
|
-
storeOp: "store"
|
|
12564
|
-
}
|
|
12565
|
-
]
|
|
12566
|
-
});
|
|
12567
|
-
renderpass.setPipeline(node.data.pipeline);
|
|
12568
|
-
renderpass.setBindGroup(0, node.data.bindGroup);
|
|
12569
|
-
renderpass.setVertexBuffer(0, node.refs.spritesheet.data.quads.buffer);
|
|
12570
|
-
const vertexCount = 6;
|
|
12571
|
-
let baseInstanceIdx = 0;
|
|
12572
|
-
for (let i = 0; i < node.data.instancedDrawCallCount; i++) {
|
|
12573
|
-
const baseVertexIdx = node.data.instancedDrawCalls[i * 2] * vertexCount;
|
|
12574
|
-
const instanceCount = node.data.instancedDrawCalls[i * 2 + 1];
|
|
12575
|
-
renderpass.draw(vertexCount, instanceCount, baseVertexIdx, baseInstanceIdx);
|
|
12576
|
-
baseInstanceIdx += instanceCount;
|
|
12577
|
-
}
|
|
12578
|
-
renderpass.end();
|
|
12579
|
-
}
|
|
12580
|
-
function _rebuildSpriteDrawCalls2(renderPass) {
|
|
12581
|
-
let currentSpriteType = -1;
|
|
12582
|
-
let instanceCount = 0;
|
|
12583
|
-
renderPass.instancedDrawCallCount = 0;
|
|
12584
|
-
for (let i = 0; i < renderPass.spriteCount; i++) {
|
|
12585
|
-
const spriteType = renderPass.spriteData[i * FLOAT32S_PER_SPRITE2 + 11] & 65535;
|
|
12586
|
-
if (spriteType !== currentSpriteType) {
|
|
12587
|
-
if (instanceCount > 0) {
|
|
12588
|
-
renderPass.instancedDrawCalls[renderPass.instancedDrawCallCount * 2] = currentSpriteType;
|
|
12589
|
-
renderPass.instancedDrawCalls[renderPass.instancedDrawCallCount * 2 + 1] = instanceCount;
|
|
12590
|
-
renderPass.instancedDrawCallCount++;
|
|
12591
|
-
}
|
|
12592
|
-
currentSpriteType = spriteType;
|
|
12593
|
-
instanceCount = 0;
|
|
12594
|
-
}
|
|
12595
|
-
instanceCount++;
|
|
12596
|
-
}
|
|
12597
|
-
if (instanceCount > 0) {
|
|
12598
|
-
renderPass.instancedDrawCalls[renderPass.instancedDrawCallCount * 2] = currentSpriteType;
|
|
12599
|
-
renderPass.instancedDrawCalls[renderPass.instancedDrawCallCount * 2 + 1] = instanceCount;
|
|
12600
|
-
renderPass.instancedDrawCallCount++;
|
|
12601
|
-
}
|
|
12602
|
-
}
|
|
12603
|
-
function _writeOverlayBuffer(cobalt, nodeData) {
|
|
12604
|
-
const zoom = 1;
|
|
12605
|
-
const GAME_WIDTH = Math.round(cobalt.viewport.width / zoom);
|
|
12606
|
-
const GAME_HEIGHT = Math.round(cobalt.viewport.height / zoom);
|
|
12607
|
-
const projection = mat4.ortho(0, GAME_WIDTH, GAME_HEIGHT, 0, -10, 10);
|
|
12608
|
-
vec3.set(0, 0, 0, _tmpVec3);
|
|
12609
|
-
const view = mat4.translation(_tmpVec3);
|
|
12610
|
-
cobalt.device.queue.writeBuffer(nodeData.data.uniformBuffer, 0, view.buffer);
|
|
12611
|
-
cobalt.device.queue.writeBuffer(nodeData.data.uniformBuffer, 64, projection.buffer);
|
|
12612
|
-
}
|
|
12613
|
-
function destroy5(nodeData) {
|
|
12614
|
-
nodeData.data.instancedDrawCalls = null;
|
|
12615
|
-
nodeData.data.bindGroup = null;
|
|
12616
|
-
nodeData.data.spriteBuffer.destroy();
|
|
12617
|
-
nodeData.data.spriteBuffer = null;
|
|
12618
|
-
nodeData.data.uniformBuffer.destroy();
|
|
12619
|
-
nodeData.data.uniformBuffer = null;
|
|
12620
|
-
nodeData.data.spriteData = null;
|
|
12621
|
-
nodeData.data.spriteIndices.clear();
|
|
12622
|
-
nodeData.data.spriteIndices = null;
|
|
12623
|
-
}
|
|
12624
|
-
|
|
12625
12396
|
// src/fb-blit/fb-blit.wgsl
|
|
12626
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);}`;
|
|
12627
12398
|
|
|
@@ -12635,10 +12406,10 @@ var fb_blit_default2 = {
|
|
|
12635
12406
|
// @params Object cobalt renderer world object
|
|
12636
12407
|
// @params Object options optional data passed when initing this node
|
|
12637
12408
|
onInit: async function(cobalt, options = {}) {
|
|
12638
|
-
return
|
|
12409
|
+
return init6(cobalt, options);
|
|
12639
12410
|
},
|
|
12640
12411
|
onRun: function(cobalt, node, webGpuCommandEncoder) {
|
|
12641
|
-
|
|
12412
|
+
draw6(cobalt, node, webGpuCommandEncoder);
|
|
12642
12413
|
},
|
|
12643
12414
|
onDestroy: function(cobalt, node) {
|
|
12644
12415
|
},
|
|
@@ -12648,7 +12419,7 @@ var fb_blit_default2 = {
|
|
|
12648
12419
|
onViewportPosition: function(cobalt, node) {
|
|
12649
12420
|
}
|
|
12650
12421
|
};
|
|
12651
|
-
async function
|
|
12422
|
+
async function init6(cobalt, node) {
|
|
12652
12423
|
const { device } = cobalt;
|
|
12653
12424
|
const bindGroupLayout = device.createBindGroupLayout({
|
|
12654
12425
|
entries: [
|
|
@@ -12723,7 +12494,7 @@ async function init7(cobalt, node) {
|
|
|
12723
12494
|
pipeline
|
|
12724
12495
|
};
|
|
12725
12496
|
}
|
|
12726
|
-
function
|
|
12497
|
+
function draw6(cobalt, node, commandEncoder) {
|
|
12727
12498
|
const { device } = cobalt;
|
|
12728
12499
|
const renderpass = commandEncoder.beginRenderPass({
|
|
12729
12500
|
label: "fb-blit",
|
|
@@ -13060,13 +12831,6 @@ function perpendicularComponent(inp) {
|
|
|
13060
12831
|
return [-inp[1], inp[0]];
|
|
13061
12832
|
}
|
|
13062
12833
|
|
|
13063
|
-
// node_modules/round-half-up-symmetric/index.js
|
|
13064
|
-
function round(value) {
|
|
13065
|
-
if (value >= 0)
|
|
13066
|
-
return Math.round(value);
|
|
13067
|
-
return value % 0.5 === 0 ? Math.floor(value) : Math.round(value);
|
|
13068
|
-
}
|
|
13069
|
-
|
|
13070
12834
|
// src/primitives/primitives.js
|
|
13071
12835
|
var _tmpVec32 = vec3.create(0, 0, 0);
|
|
13072
12836
|
var primitives_default2 = {
|
|
@@ -13078,13 +12842,13 @@ var primitives_default2 = {
|
|
|
13078
12842
|
// @params Object cobalt renderer world object
|
|
13079
12843
|
// @params Object options optional data passed when initing this node
|
|
13080
12844
|
onInit: async function(cobalt, options = {}) {
|
|
13081
|
-
return
|
|
12845
|
+
return init7(cobalt, options);
|
|
13082
12846
|
},
|
|
13083
12847
|
onRun: function(cobalt, node, webGpuCommandEncoder) {
|
|
13084
|
-
|
|
12848
|
+
draw7(cobalt, node, webGpuCommandEncoder);
|
|
13085
12849
|
},
|
|
13086
12850
|
onDestroy: function(cobalt, node) {
|
|
13087
|
-
|
|
12851
|
+
destroy4(node);
|
|
13088
12852
|
},
|
|
13089
12853
|
onResize: function(cobalt, node) {
|
|
13090
12854
|
_writeMatricesBuffer(cobalt, node);
|
|
@@ -13095,7 +12859,7 @@ var primitives_default2 = {
|
|
|
13095
12859
|
// optional
|
|
13096
12860
|
customFunctions: public_api_default
|
|
13097
12861
|
};
|
|
13098
|
-
async function
|
|
12862
|
+
async function init7(cobalt, node) {
|
|
13099
12863
|
const { device } = cobalt;
|
|
13100
12864
|
const vertices = new Float32Array(1024);
|
|
13101
12865
|
const vertexBuffer = device.createBuffer({
|
|
@@ -13201,7 +12965,7 @@ async function init8(cobalt, node) {
|
|
|
13201
12965
|
transforms: [mat3.identity()]
|
|
13202
12966
|
};
|
|
13203
12967
|
}
|
|
13204
|
-
function
|
|
12968
|
+
function draw7(cobalt, node, commandEncoder) {
|
|
13205
12969
|
if (node.data.vertexCount === 0)
|
|
13206
12970
|
return;
|
|
13207
12971
|
const { device } = cobalt;
|
|
@@ -13242,7 +13006,7 @@ function draw8(cobalt, node, commandEncoder) {
|
|
|
13242
13006
|
renderpass.draw(node.data.vertexCount);
|
|
13243
13007
|
renderpass.end();
|
|
13244
13008
|
}
|
|
13245
|
-
function
|
|
13009
|
+
function destroy4(node) {
|
|
13246
13010
|
node.data.vertexBuffer.destroy();
|
|
13247
13011
|
node.data.vertexBuffer = null;
|
|
13248
13012
|
node.data.uniformBuffer.destroy();
|
|
@@ -14140,13 +13904,13 @@ var light_default = {
|
|
|
14140
13904
|
// @params Object cobalt renderer world object
|
|
14141
13905
|
// @params Object options optional data passed when initing this node
|
|
14142
13906
|
onInit: async function(cobalt, options = {}) {
|
|
14143
|
-
return
|
|
13907
|
+
return init8(cobalt, options);
|
|
14144
13908
|
},
|
|
14145
13909
|
onRun: function(cobalt, node, webGpuCommandEncoder) {
|
|
14146
|
-
|
|
13910
|
+
draw8(cobalt, node, webGpuCommandEncoder);
|
|
14147
13911
|
},
|
|
14148
13912
|
onDestroy: function(cobalt, node) {
|
|
14149
|
-
|
|
13913
|
+
destroy5(node);
|
|
14150
13914
|
},
|
|
14151
13915
|
onResize: function(cobalt, node) {
|
|
14152
13916
|
resize4(cobalt, node);
|
|
@@ -14159,7 +13923,7 @@ var light_default = {
|
|
|
14159
13923
|
...public_api_exports2
|
|
14160
13924
|
}
|
|
14161
13925
|
};
|
|
14162
|
-
async function
|
|
13926
|
+
async function init8(cobalt, node) {
|
|
14163
13927
|
const { device } = cobalt;
|
|
14164
13928
|
const MAX_LIGHT_COUNT = 256;
|
|
14165
13929
|
const MAX_LIGHT_SIZE = 256;
|
|
@@ -14197,7 +13961,7 @@ async function init9(cobalt, node) {
|
|
|
14197
13961
|
lights: []
|
|
14198
13962
|
};
|
|
14199
13963
|
}
|
|
14200
|
-
function
|
|
13964
|
+
function draw8(cobalt, node, commandEncoder) {
|
|
14201
13965
|
if (node.data.lightsBufferNeedsUpdate) {
|
|
14202
13966
|
const lightsBuffer = node.data.lightsBuffer;
|
|
14203
13967
|
lightsBuffer.setLights(node.data.lights);
|
|
@@ -14225,7 +13989,7 @@ function draw9(cobalt, node, commandEncoder) {
|
|
|
14225
13989
|
lightsRenderer.render(renderpass, invertVpMatrix);
|
|
14226
13990
|
renderpass.end();
|
|
14227
13991
|
}
|
|
14228
|
-
function
|
|
13992
|
+
function destroy5(node) {
|
|
14229
13993
|
node.data.lightsBuffer.destroy();
|
|
14230
13994
|
node.data.lightsRenderer.destroy();
|
|
14231
13995
|
}
|
|
@@ -14237,10 +14001,386 @@ function resize4(cobalt, node) {
|
|
|
14237
14001
|
node.data.viewport.setViewportSize(cobalt.viewport.width, cobalt.viewport.height);
|
|
14238
14002
|
}
|
|
14239
14003
|
|
|
14240
|
-
// 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
|
|
14241
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;}`;
|
|
14242
14382
|
|
|
14243
|
-
// src/tile/atlas.js
|
|
14383
|
+
// src/tile-hdr/atlas.js
|
|
14244
14384
|
var _buf = new Float32Array(8);
|
|
14245
14385
|
var atlas_default = {
|
|
14246
14386
|
type: "cobalt:tileAtlas",
|
|
@@ -14253,7 +14393,7 @@ var atlas_default = {
|
|
|
14253
14393
|
onRun: function(cobalt, node, webGpuCommandEncoder) {
|
|
14254
14394
|
},
|
|
14255
14395
|
onDestroy: function(cobalt, node) {
|
|
14256
|
-
|
|
14396
|
+
destroy6(data);
|
|
14257
14397
|
},
|
|
14258
14398
|
onResize: function(cobalt, node) {
|
|
14259
14399
|
_writeTileBuffer(cobalt, node);
|
|
@@ -14352,7 +14492,7 @@ async function init10(cobalt, nodeData) {
|
|
|
14352
14492
|
entryPoint: "fs_main",
|
|
14353
14493
|
targets: [
|
|
14354
14494
|
{
|
|
14355
|
-
format:
|
|
14495
|
+
format: nodeData.options.outputFormat || getPreferredFormat(cobalt),
|
|
14356
14496
|
blend: {
|
|
14357
14497
|
color: {
|
|
14358
14498
|
srcFactor: "src-alpha",
|
|
@@ -14382,13 +14522,13 @@ async function init10(cobalt, nodeData) {
|
|
|
14382
14522
|
tileScale: nodeData.options.tileScale
|
|
14383
14523
|
};
|
|
14384
14524
|
}
|
|
14385
|
-
function
|
|
14525
|
+
function destroy6(data2) {
|
|
14386
14526
|
data2.atlasMaterial.texture.destroy();
|
|
14387
14527
|
data2.atlasMaterial.texture = void 0;
|
|
14388
14528
|
}
|
|
14389
14529
|
function _writeTileBuffer(c, nodeData) {
|
|
14390
|
-
_buf[0] = c.viewport.position[0];
|
|
14391
|
-
_buf[1] = c.viewport.position[1];
|
|
14530
|
+
_buf[0] = round(c.viewport.position[0]);
|
|
14531
|
+
_buf[1] = round(c.viewport.position[1]);
|
|
14392
14532
|
const tile = nodeData.data;
|
|
14393
14533
|
const { tileScale, tileSize } = tile;
|
|
14394
14534
|
const GAME_WIDTH = c.viewport.width / c.viewport.zoom;
|
|
@@ -14402,61 +14542,32 @@ function _writeTileBuffer(c, nodeData) {
|
|
|
14402
14542
|
c.device.queue.writeBuffer(tile.uniformBuffer, 0, _buf, 0, 8);
|
|
14403
14543
|
}
|
|
14404
14544
|
|
|
14405
|
-
// src/
|
|
14406
|
-
function
|
|
14407
|
-
const
|
|
14408
|
-
const
|
|
14409
|
-
const
|
|
14410
|
-
const
|
|
14411
|
-
|
|
14412
|
-
|
|
14413
|
-
|
|
14414
|
-
const
|
|
14415
|
-
|
|
14416
|
-
|
|
14417
|
-
const
|
|
14418
|
-
const
|
|
14419
|
-
const
|
|
14420
|
-
|
|
14421
|
-
|
|
14422
|
-
|
|
14423
|
-
|
|
14424
|
-
|
|
14425
|
-
|
|
14426
|
-
const minV = 0 + frame.frame.y / spritesheetJson.meta.size.h;
|
|
14427
|
-
const maxU = 0 + (frame.frame.x + frame.frame.w) / spritesheetJson.meta.size.w;
|
|
14428
|
-
const maxV = 0 + (frame.frame.y + frame.frame.h) / spritesheetJson.meta.size.h;
|
|
14429
|
-
const uv0 = [minU, minV];
|
|
14430
|
-
const uv1 = [minU, maxV];
|
|
14431
|
-
const uv2 = [maxU, maxV];
|
|
14432
|
-
const uv3 = [maxU, minV];
|
|
14433
|
-
vertices.set(p0, i);
|
|
14434
|
-
vertices.set(uv0, i + 3);
|
|
14435
|
-
vertices.set(p1, i + 5);
|
|
14436
|
-
vertices.set(uv1, i + 8);
|
|
14437
|
-
vertices.set(p2, i + 10);
|
|
14438
|
-
vertices.set(uv2, i + 13);
|
|
14439
|
-
vertices.set(p0, i + 15);
|
|
14440
|
-
vertices.set(uv0, i + 18);
|
|
14441
|
-
vertices.set(p2, i + 20);
|
|
14442
|
-
vertices.set(uv2, i + 23);
|
|
14443
|
-
vertices.set(p3, i + 25);
|
|
14444
|
-
vertices.set(uv3, i + 28);
|
|
14445
|
-
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
|
+
};
|
|
14446
14566
|
}
|
|
14447
|
-
return {
|
|
14448
|
-
/*spriteCount, */
|
|
14449
|
-
spriteMeta,
|
|
14450
|
-
locations,
|
|
14451
|
-
vertices
|
|
14452
|
-
};
|
|
14567
|
+
return { descs, names };
|
|
14453
14568
|
}
|
|
14454
14569
|
|
|
14455
|
-
// src/
|
|
14456
|
-
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;}`;
|
|
14457
|
-
|
|
14458
|
-
// src/sprite/spritesheet.js
|
|
14459
|
-
var _tmpVec33 = vec3.create(0, 0, 0);
|
|
14570
|
+
// src/spritesheet/spritesheet.js
|
|
14460
14571
|
var spritesheet_default = {
|
|
14461
14572
|
type: "cobalt:spritesheet",
|
|
14462
14573
|
refs: [],
|
|
@@ -14468,13 +14579,11 @@ var spritesheet_default = {
|
|
|
14468
14579
|
onRun: function(cobalt, node, webGpuCommandEncoder) {
|
|
14469
14580
|
},
|
|
14470
14581
|
onDestroy: function(cobalt, node) {
|
|
14471
|
-
|
|
14582
|
+
destroy7(node);
|
|
14472
14583
|
},
|
|
14473
14584
|
onResize: function(cobalt, node) {
|
|
14474
|
-
_writeSpriteBuffer(cobalt, node);
|
|
14475
14585
|
},
|
|
14476
14586
|
onViewportPosition: function(cobalt, node) {
|
|
14477
|
-
_writeSpriteBuffer(cobalt, node);
|
|
14478
14587
|
}
|
|
14479
14588
|
};
|
|
14480
14589
|
async function init11(cobalt, node) {
|
|
@@ -14482,127 +14591,30 @@ async function init11(cobalt, node) {
|
|
|
14482
14591
|
let spritesheet, colorTexture, emissiveTexture;
|
|
14483
14592
|
const format = node.options.format || "rgba8unorm";
|
|
14484
14593
|
if (canvas) {
|
|
14485
|
-
spritesheet = await
|
|
14486
|
-
spritesheet =
|
|
14594
|
+
spritesheet = await fetch(node.options.spriteSheetJsonUrl);
|
|
14595
|
+
spritesheet = await spritesheet.json();
|
|
14596
|
+
spritesheet = buildSpriteTableFromTexturePacker(spritesheet);
|
|
14487
14597
|
colorTexture = await createTextureFromUrl(cobalt, "sprite", node.options.colorTextureUrl, format);
|
|
14488
14598
|
emissiveTexture = await createTextureFromUrl(cobalt, "emissive sprite", node.options.emissiveTextureUrl, format);
|
|
14489
14599
|
canvas.style.imageRendering = "pixelated";
|
|
14490
14600
|
} else {
|
|
14491
|
-
spritesheet =
|
|
14601
|
+
spritesheet = buildSpriteTableFromTexturePacker(node.options.spriteSheetJson);
|
|
14492
14602
|
colorTexture = await createTextureFromBuffer(cobalt, "sprite", node.options.colorTexture, format);
|
|
14493
14603
|
emissiveTexture = await createTextureFromBuffer(cobalt, "emissive sprite", node.options.emissiveTexture, format);
|
|
14494
14604
|
}
|
|
14495
|
-
const
|
|
14496
|
-
const uniformBuffer = device.createBuffer({
|
|
14497
|
-
size: 64 * 2,
|
|
14498
|
-
// 4x4 matrix with 4 bytes per float32, times 2 matrices (view, projection)
|
|
14499
|
-
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
14500
|
-
});
|
|
14501
|
-
const bindGroupLayout = device.createBindGroupLayout({
|
|
14502
|
-
entries: [
|
|
14503
|
-
{
|
|
14504
|
-
binding: 0,
|
|
14505
|
-
visibility: GPUShaderStage.VERTEX,
|
|
14506
|
-
buffer: {}
|
|
14507
|
-
},
|
|
14508
|
-
{
|
|
14509
|
-
binding: 1,
|
|
14510
|
-
visibility: GPUShaderStage.FRAGMENT,
|
|
14511
|
-
texture: {}
|
|
14512
|
-
},
|
|
14513
|
-
{
|
|
14514
|
-
binding: 2,
|
|
14515
|
-
visibility: GPUShaderStage.FRAGMENT,
|
|
14516
|
-
sampler: {}
|
|
14517
|
-
},
|
|
14518
|
-
{
|
|
14519
|
-
binding: 3,
|
|
14520
|
-
visibility: GPUShaderStage.VERTEX,
|
|
14521
|
-
buffer: {
|
|
14522
|
-
type: "read-only-storage"
|
|
14523
|
-
}
|
|
14524
|
-
},
|
|
14525
|
-
{
|
|
14526
|
-
binding: 4,
|
|
14527
|
-
visibility: GPUShaderStage.FRAGMENT,
|
|
14528
|
-
texture: {}
|
|
14529
|
-
}
|
|
14530
|
-
]
|
|
14531
|
-
});
|
|
14532
|
-
const pipelineLayout = device.createPipelineLayout({
|
|
14533
|
-
bindGroupLayouts: [bindGroupLayout]
|
|
14534
|
-
});
|
|
14535
|
-
const pipeline = device.createRenderPipeline({
|
|
14536
|
-
label: "spritesheet",
|
|
14537
|
-
vertex: {
|
|
14538
|
-
module: device.createShaderModule({
|
|
14539
|
-
code: sprite_default2
|
|
14540
|
-
}),
|
|
14541
|
-
entryPoint: "vs_main",
|
|
14542
|
-
buffers: [quads.bufferLayout]
|
|
14543
|
-
},
|
|
14544
|
-
fragment: {
|
|
14545
|
-
module: device.createShaderModule({
|
|
14546
|
-
code: sprite_default2
|
|
14547
|
-
}),
|
|
14548
|
-
entryPoint: "fs_main",
|
|
14549
|
-
targets: [
|
|
14550
|
-
// color
|
|
14551
|
-
{
|
|
14552
|
-
format: "rgba16float",
|
|
14553
|
-
blend: {
|
|
14554
|
-
color: {
|
|
14555
|
-
srcFactor: "src-alpha",
|
|
14556
|
-
dstFactor: "one-minus-src-alpha"
|
|
14557
|
-
},
|
|
14558
|
-
alpha: {
|
|
14559
|
-
srcFactor: "zero",
|
|
14560
|
-
dstFactor: "one"
|
|
14561
|
-
}
|
|
14562
|
-
}
|
|
14563
|
-
},
|
|
14564
|
-
// emissive
|
|
14565
|
-
{
|
|
14566
|
-
format: "rgba16float"
|
|
14567
|
-
}
|
|
14568
|
-
]
|
|
14569
|
-
},
|
|
14570
|
-
primitive: {
|
|
14571
|
-
topology: "triangle-list"
|
|
14572
|
-
},
|
|
14573
|
-
layout: pipelineLayout
|
|
14574
|
-
});
|
|
14605
|
+
const idByName = new Map(spritesheet.names.map((n, i) => [n, i]));
|
|
14575
14606
|
return {
|
|
14576
|
-
pipeline,
|
|
14577
|
-
uniformBuffer,
|
|
14578
|
-
// perspective and view matrices for the camera
|
|
14579
|
-
quads,
|
|
14580
14607
|
colorTexture,
|
|
14581
14608
|
emissiveTexture,
|
|
14582
|
-
|
|
14583
|
-
|
|
14609
|
+
spritesheet,
|
|
14610
|
+
idByName
|
|
14584
14611
|
};
|
|
14585
14612
|
}
|
|
14586
|
-
function
|
|
14613
|
+
function destroy7(node) {
|
|
14587
14614
|
node.data.quads.buffer.destroy();
|
|
14588
14615
|
node.data.colorTexture.buffer.destroy();
|
|
14589
|
-
node.data.uniformBuffer.destroy();
|
|
14590
14616
|
node.data.emissiveTexture.texture.destroy();
|
|
14591
14617
|
}
|
|
14592
|
-
async function fetchJson(url) {
|
|
14593
|
-
const raw = await fetch(url);
|
|
14594
|
-
return raw.json();
|
|
14595
|
-
}
|
|
14596
|
-
function _writeSpriteBuffer(cobalt, node) {
|
|
14597
|
-
const { device, viewport } = cobalt;
|
|
14598
|
-
const GAME_WIDTH = viewport.width / viewport.zoom;
|
|
14599
|
-
const GAME_HEIGHT = viewport.height / viewport.zoom;
|
|
14600
|
-
const projection = mat4.ortho(0, GAME_WIDTH, GAME_HEIGHT, 0, -10, 10);
|
|
14601
|
-
vec3.set(-round(viewport.position[0]), -round(viewport.position[1]), 0, _tmpVec33);
|
|
14602
|
-
const view = mat4.translation(_tmpVec33);
|
|
14603
|
-
device.queue.writeBuffer(node.data.uniformBuffer, 0, view.buffer);
|
|
14604
|
-
device.queue.writeBuffer(node.data.uniformBuffer, 64, projection.buffer);
|
|
14605
|
-
}
|
|
14606
14618
|
|
|
14607
14619
|
// src/fb-texture/fb-texture.js
|
|
14608
14620
|
var fb_texture_default = {
|
|
@@ -14616,7 +14628,7 @@ var fb_texture_default = {
|
|
|
14616
14628
|
onRun: function(cobalt, node, webGpuCommandEncoder) {
|
|
14617
14629
|
},
|
|
14618
14630
|
onDestroy: function(cobalt, node) {
|
|
14619
|
-
|
|
14631
|
+
destroy8(data);
|
|
14620
14632
|
},
|
|
14621
14633
|
onResize: function(cobalt, node) {
|
|
14622
14634
|
resize5(cobalt, node);
|
|
@@ -14630,12 +14642,12 @@ async function init12(cobalt, node) {
|
|
|
14630
14642
|
const { format, label, mip_count, usage, viewportScale } = node.options;
|
|
14631
14643
|
return createTexture(device, label, cobalt.viewport.width * viewportScale, cobalt.viewport.height * viewportScale, mip_count, format, usage);
|
|
14632
14644
|
}
|
|
14633
|
-
function
|
|
14645
|
+
function destroy8(node) {
|
|
14634
14646
|
node.data.texture.destroy();
|
|
14635
14647
|
}
|
|
14636
14648
|
function resize5(cobalt, node) {
|
|
14637
14649
|
const { device } = cobalt;
|
|
14638
|
-
|
|
14650
|
+
destroy8(node);
|
|
14639
14651
|
const { width, height } = cobalt.viewport;
|
|
14640
14652
|
const { options } = node;
|
|
14641
14653
|
const scale = node.options.viewportScale;
|
|
@@ -14675,12 +14687,12 @@ async function init13(ctx, viewportWidth, viewportHeight) {
|
|
|
14675
14687
|
"cobalt:spritesheet": spritesheet_default,
|
|
14676
14688
|
"cobalt:fbTexture": fb_texture_default,
|
|
14677
14689
|
// builtin run nodes
|
|
14690
|
+
"cobalt:sprite": sprite_default4,
|
|
14678
14691
|
"cobalt:bloom": bloom_default2,
|
|
14679
14692
|
"cobalt:composite": scene_composite_default2,
|
|
14680
|
-
"cobalt:
|
|
14681
|
-
"cobalt:
|
|
14693
|
+
"cobalt:spriteHDR": sprite_default2,
|
|
14694
|
+
"cobalt:tileHDR": tile_default,
|
|
14682
14695
|
"cobalt:displacement": displacement_default2,
|
|
14683
|
-
"cobalt:overlay": overlay_default2,
|
|
14684
14696
|
"cobalt:fbBlit": fb_blit_default2,
|
|
14685
14697
|
"cobalt:primitives": primitives_default2,
|
|
14686
14698
|
"cobalt:light": light_default
|