@bloopjs/toodle 0.1.4 → 0.1.6

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.
@@ -25,6 +25,8 @@ export type QuadShaderCreationOpts = {
25
25
  export interface IBackendShader {
26
26
  /** Debug label for the shader */
27
27
  readonly label: string;
28
+ /** The final compiled shader code (for debugging) */
29
+ readonly code: string;
28
30
  /**
29
31
  * Prepare for a new frame.
30
32
  * Called once per frame before any processBatch calls.
@@ -1 +1 @@
1
- {"version":3,"file":"IBackendShader.d.ts","sourceRoot":"","sources":["../../src/backends/IBackendShader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,aAAa,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,iCAAiC;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB;;;;;OAKG;IACH,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC;IAEzC;;;;;OAKG;IACH,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IAEzC;;;OAGG;IACH,QAAQ,IAAI,IAAI,CAAC;CAClB"}
1
+ {"version":3,"file":"IBackendShader.d.ts","sourceRoot":"","sources":["../../src/backends/IBackendShader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,aAAa,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,iCAAiC;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,qDAAqD;IACrD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;;;OAKG;IACH,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC;IAEzC;;;;;OAKG;IACH,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IAEzC;;;OAGG;IACH,QAAQ,IAAI,IAAI,CAAC;CAClB"}
@@ -8,6 +8,7 @@ import type { WebGLBackend } from "./WebGLBackend";
8
8
  export declare class WebGLQuadShader implements IBackendShader {
9
9
  #private;
10
10
  readonly label: string;
11
+ readonly code: string;
11
12
  constructor(label: string, backend: WebGLBackend, instanceCount: number, userFragmentShader?: string, atlasId?: string);
12
13
  startFrame(uniform: EngineUniform): void;
13
14
  processBatch(nodes: SceneNode[]): number;
@@ -1 +1 @@
1
- {"version":3,"file":"WebGLQuadShader.d.ts","sourceRoot":"","sources":["../../../src/backends/webgl2/WebGLQuadShader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAOnD;;GAEG;AACH,qBAAa,eAAgB,YAAW,cAAc;;IACpD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAiBrB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,YAAY,EACrB,aAAa,EAAE,MAAM,EACrB,kBAAkB,CAAC,EAAE,MAAM,EAC3B,OAAO,CAAC,EAAE,MAAM;IA8GlB,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAkDxC,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM;IAgDxC,QAAQ,IAAI,IAAI;IAyBhB,OAAO,IAAI,IAAI;CAMhB"}
1
+ {"version":3,"file":"WebGLQuadShader.d.ts","sourceRoot":"","sources":["../../../src/backends/webgl2/WebGLQuadShader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAOnD;;GAEG;AACH,qBAAa,eAAgB,YAAW,cAAc;;IACpD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAiBpB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,YAAY,EACrB,aAAa,EAAE,MAAM,EACrB,kBAAkB,CAAC,EAAE,MAAM,EAC3B,OAAO,CAAC,EAAE,MAAM;IA+GlB,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAkDxC,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM;IAgDxC,QAAQ,IAAI,IAAI;IAyBhB,OAAO,IAAI,IAAI;CAMhB"}
@@ -13,6 +13,7 @@ import type { WebGLFontPipeline } from "./WebGLFontPipeline";
13
13
  export declare class WebGLTextShader implements ITextShader {
14
14
  #private;
15
15
  readonly label = "text";
16
+ readonly code: string;
16
17
  readonly font: MsdfFont;
17
18
  readonly maxCharCount: number;
18
19
  constructor(backend: WebGLBackend, pipeline: WebGLFontPipeline);
@@ -1 +1 @@
1
- {"version":3,"file":"WebGLTextShader.d.ts","sourceRoot":"","sources":["../../../src/backends/webgl2/WebGLTextShader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAOpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D;;;;;GAKG;AACH,qBAAa,eAAgB,YAAW,WAAW;;IACjD,QAAQ,CAAC,KAAK,UAAU;IACxB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;gBAqBlB,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,iBAAiB;IAmD9D,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAIxC,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM;IA+IxC,QAAQ,IAAI,IAAI;IAyBhB,OAAO,IAAI,IAAI;CAMhB"}
1
+ {"version":3,"file":"WebGLTextShader.d.ts","sourceRoot":"","sources":["../../../src/backends/webgl2/WebGLTextShader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAOpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D;;;;;GAKG;AACH,qBAAa,eAAgB,YAAW,WAAW;;IACjD,QAAQ,CAAC,KAAK,UAAU;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAkB;IACvC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;gBAqBlB,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,iBAAiB;IAmD9D,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAIxC,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM;IA+IxC,QAAQ,IAAI,IAAI;IAyBhB,OAAO,IAAI,IAAI;CAMhB"}
@@ -7,6 +7,7 @@ import type { WebGPUBackend } from "./WebGPUBackend";
7
7
  export declare class WebGPUTextShader implements ITextShader {
8
8
  #private;
9
9
  readonly label = "text";
10
+ readonly code: string;
10
11
  constructor(backend: WebGPUBackend, pipeline: FontPipeline, font: MsdfFont, _colorFormat: GPUTextureFormat, instanceCount: number);
11
12
  startFrame(uniform: EngineUniform): void;
12
13
  processBatch(nodes: SceneNode[]): number;
@@ -1 +1 @@
1
- {"version":3,"file":"WebGPUTextShader.d.ts","sourceRoot":"","sources":["../../../src/backends/webgpu/WebGPUTextShader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAMpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAUrD,qBAAa,gBAAiB,YAAW,WAAW;;IAClD,QAAQ,CAAC,KAAK,UAAU;gBAgBtB,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE,QAAQ,EACd,YAAY,EAAE,gBAAgB,EAC9B,aAAa,EAAE,MAAM;IAqEvB,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAWxC,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM;IAkGxC,QAAQ,IAAI,IAAI;IAIhB,IAAI,IAAI,aAEP;IAED,IAAI,YAAY,WAEf;CACF"}
1
+ {"version":3,"file":"WebGPUTextShader.d.ts","sourceRoot":"","sources":["../../../src/backends/webgpu/WebGPUTextShader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAMpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAUrD,qBAAa,gBAAiB,YAAW,WAAW;;IAClD,QAAQ,CAAC,KAAK,UAAU;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAc;gBAgBjC,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE,QAAQ,EACd,YAAY,EAAE,gBAAgB,EAC9B,aAAa,EAAE,MAAM;IAqEvB,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAWxC,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM;IAkGxC,QAAQ,IAAI,IAAI;IAIhB,IAAI,IAAI,aAEP;IAED,IAAI,YAAY,WAEf;CACF"}
package/dist/mod.js CHANGED
@@ -3602,6 +3602,7 @@ var INSTANCE_BYTES = INSTANCE_FLOATS * Float32Array.BYTES_PER_ELEMENT;
3602
3602
 
3603
3603
  class WebGLQuadShader {
3604
3604
  label;
3605
+ code;
3605
3606
  #backend;
3606
3607
  #atlas;
3607
3608
  #program;
@@ -3620,6 +3621,7 @@ class WebGLQuadShader {
3620
3621
  }
3621
3622
  this.#atlas = atlas;
3622
3623
  this.label = label;
3624
+ this.code = userFragmentShader ?? fragmentShader;
3623
3625
  this.#backend = backend;
3624
3626
  this.#instanceCount = instanceCount;
3625
3627
  const gl = backend.gl;
@@ -18154,6 +18156,7 @@ void main() {
18154
18156
  // src/backends/webgl2/WebGLTextShader.ts
18155
18157
  class WebGLTextShader {
18156
18158
  label = "text";
18159
+ code = fragmentShader2;
18157
18160
  font;
18158
18161
  maxCharCount;
18159
18162
  #backend;
@@ -18656,6 +18659,7 @@ var textDescriptorInstanceSize = struct.size;
18656
18659
 
18657
18660
  class WebGPUTextShader {
18658
18661
  label = "text";
18662
+ code = text_wgsl_default;
18659
18663
  #backend;
18660
18664
  #pipeline;
18661
18665
  #bindGroups = [];
@@ -19926,6 +19930,105 @@ async function textureToBitmap(device, texture, width, height) {
19926
19930
  readBuffer.unmap();
19927
19931
  return bitmap;
19928
19932
  }
19933
+ async function packBitmapsToAtlasCPU(images, textureSize) {
19934
+ const cpuTextureAtlases = [];
19935
+ const packed = [];
19936
+ const spaces = [
19937
+ { x: 0, y: 0, width: textureSize, height: textureSize }
19938
+ ];
19939
+ let atlasRegionMap = new Map;
19940
+ for (const [id, { bitmap }] of images) {
19941
+ let bestSpace = -1;
19942
+ let bestScore = Number.POSITIVE_INFINITY;
19943
+ for (let i3 = 0;i3 < spaces.length; i3++) {
19944
+ const space2 = spaces[i3];
19945
+ if (bitmap.width <= space2.width && bitmap.height <= space2.height) {
19946
+ const score = Math.abs(space2.width * space2.height - bitmap.width * bitmap.height);
19947
+ if (score < bestScore) {
19948
+ bestScore = score;
19949
+ bestSpace = i3;
19950
+ }
19951
+ }
19952
+ }
19953
+ if (bestSpace === -1) {
19954
+ const tex2 = createAtlasBitmapFromPacked(packed, textureSize);
19955
+ cpuTextureAtlases.push({
19956
+ texture: tex2,
19957
+ textureRegions: atlasRegionMap,
19958
+ width: tex2.width,
19959
+ height: tex2.height
19960
+ });
19961
+ atlasRegionMap = new Map;
19962
+ packed.length = 0;
19963
+ spaces.length = 0;
19964
+ spaces.push({
19965
+ x: 0,
19966
+ y: 0,
19967
+ width: textureSize,
19968
+ height: textureSize
19969
+ });
19970
+ bestSpace = 0;
19971
+ }
19972
+ const space = spaces[bestSpace];
19973
+ packed.push({
19974
+ texture: bitmap,
19975
+ x: space.x,
19976
+ y: space.y,
19977
+ width: bitmap.width,
19978
+ height: bitmap.height
19979
+ });
19980
+ spaces.splice(bestSpace, 1);
19981
+ if (space.width - bitmap.width > 0) {
19982
+ spaces.push({
19983
+ x: space.x + bitmap.width,
19984
+ y: space.y,
19985
+ width: space.width - bitmap.width,
19986
+ height: bitmap.height
19987
+ });
19988
+ }
19989
+ if (space.height - bitmap.height > 0) {
19990
+ spaces.push({
19991
+ x: space.x,
19992
+ y: space.y + bitmap.height,
19993
+ width: space.width,
19994
+ height: space.height - bitmap.height
19995
+ });
19996
+ }
19997
+ const uvScale = {
19998
+ width: bitmap.width / textureSize,
19999
+ height: bitmap.height / textureSize
20000
+ };
20001
+ atlasRegionMap.set(id, {
20002
+ uvOffset: {
20003
+ x: space.x / textureSize,
20004
+ y: space.y / textureSize
20005
+ },
20006
+ uvScale,
20007
+ uvScaleCropped: uvScale,
20008
+ cropOffset: { x: 0, y: 0 },
20009
+ originalSize: { width: bitmap.width, height: bitmap.height }
20010
+ });
20011
+ }
20012
+ const tex = createAtlasBitmapFromPacked(packed, textureSize);
20013
+ cpuTextureAtlases.push({
20014
+ texture: tex,
20015
+ textureRegions: atlasRegionMap,
20016
+ width: tex.width,
20017
+ height: tex.height
20018
+ });
20019
+ return cpuTextureAtlases;
20020
+ }
20021
+ function createAtlasBitmapFromPacked(packed, atlasSize) {
20022
+ const canvas = new OffscreenCanvas(atlasSize, atlasSize);
20023
+ const ctx = canvas.getContext("2d");
20024
+ if (!ctx) {
20025
+ throw new Error("Failed to get 2d context from OffscreenCanvas");
20026
+ }
20027
+ for (const texture of packed) {
20028
+ ctx.drawImage(texture.texture, texture.x, texture.y);
20029
+ }
20030
+ return canvas.transferToImageBitmap();
20031
+ }
19929
20032
 
19930
20033
  // src/textures/AssetManager.ts
19931
20034
  class AssetManager {
@@ -20115,24 +20218,31 @@ class AssetManager {
20115
20218
  return texture;
20116
20219
  }
20117
20220
  async#registerBundleFromTextures(bundleId, opts) {
20118
- if (this.#backend.type !== "webgpu") {
20119
- throw new Error("Dynamic texture bundle registration is only supported with WebGPU backend. Use prebaked atlases instead.");
20120
- }
20121
- const device = this.#backend.device;
20122
- const images = new Map;
20123
- let _networkLoadTime = 0;
20124
- await Promise.all(Object.entries(opts.textures).map(async ([id, url]) => {
20125
- const now = performance.now();
20126
- const bitmap = await getBitmapFromUrl(url);
20127
- _networkLoadTime += performance.now() - now;
20128
- let textureWrapper = this.#wrapBitmapToTexture(bitmap, id);
20129
- if (opts.cropTransparentPixels && this.#cropComputeShader) {
20130
- textureWrapper = await this.#cropComputeShader.processTexture(textureWrapper);
20221
+ if (this.#backend.type === "webgpu") {
20222
+ const device = this.#backend.device;
20223
+ const images = new Map;
20224
+ await Promise.all(Object.entries(opts.textures).map(async ([id, url]) => {
20225
+ const bitmap = await getBitmapFromUrl(url);
20226
+ let textureWrapper = this.#wrapBitmapToTexture(bitmap, id);
20227
+ if (opts.cropTransparentPixels && this.#cropComputeShader) {
20228
+ textureWrapper = await this.#cropComputeShader.processTexture(textureWrapper);
20229
+ }
20230
+ images.set(id, textureWrapper);
20231
+ }));
20232
+ const atlases = await packBitmapsToAtlas(images, this.#backend.limits.textureSize, device);
20233
+ this.bundles.registerDynamicBundle(bundleId, atlases);
20234
+ } else {
20235
+ if (opts.cropTransparentPixels) {
20236
+ console.warn("cropTransparentPixels is not supported on WebGL2 backend and will be ignored.");
20131
20237
  }
20132
- images.set(id, textureWrapper);
20133
- }));
20134
- const atlases = await packBitmapsToAtlas(images, this.#backend.limits.textureSize, device);
20135
- this.bundles.registerDynamicBundle(bundleId, atlases);
20238
+ const images = new Map;
20239
+ await Promise.all(Object.entries(opts.textures).map(async ([id, url]) => {
20240
+ const bitmap = await getBitmapFromUrl(url);
20241
+ images.set(id, { bitmap, id });
20242
+ }));
20243
+ const atlases = await packBitmapsToAtlasCPU(images, this.#backend.limits.textureSize);
20244
+ this.bundles.registerDynamicBundle(bundleId, atlases);
20245
+ }
20136
20246
  }
20137
20247
  async#registerBundleFromAtlases(bundleId, opts) {
20138
20248
  await this.bundles.registerAtlasBundle(bundleId, opts);
@@ -20798,5 +20908,5 @@ export {
20798
20908
  AssetManager
20799
20909
  };
20800
20910
 
20801
- //# debugId=4A88BA8B6CA05C3D64756E2164756E21
20911
+ //# debugId=8FA83A386B693B6064756E2164756E21
20802
20912
  //# sourceMappingURL=mod.js.map