reze-engine 0.1.13 → 0.1.14

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/dist/engine.d.ts CHANGED
@@ -35,6 +35,7 @@ export declare class Engine {
35
35
  private worldMatrixBuffer?;
36
36
  private inverseBindMatrixBuffer?;
37
37
  private skinMatrixComputePipeline?;
38
+ private skinMatrixComputeBindGroup?;
38
39
  private boneCountBuffer?;
39
40
  private multisampleTexture;
40
41
  private readonly sampleCount;
@@ -52,6 +53,10 @@ export declare class Engine {
52
53
  private bloomIntensityBuffer;
53
54
  private bloomThresholdBuffer;
54
55
  private linearSampler;
56
+ private bloomExtractBindGroup?;
57
+ private bloomBlurHBindGroup?;
58
+ private bloomBlurVBindGroup?;
59
+ private bloomComposeBindGroup?;
55
60
  bloomThreshold: number;
56
61
  bloomIntensity: number;
57
62
  private rimLightIntensity;
@@ -78,6 +83,7 @@ export declare class Engine {
78
83
  private createSkinMatrixComputePipeline;
79
84
  private createFullscreenQuad;
80
85
  private createBloomPipelines;
86
+ private setupBloom;
81
87
  private setupResize;
82
88
  private handleResize;
83
89
  private setupCamera;
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAKnC,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,kBAAkB,CAAmB;IACtC,MAAM,EAAG,MAAM,CAAA;IACtB,OAAO,CAAC,mBAAmB,CAAY;IACvC,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,kBAAkB,CAAY;IACtC,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,UAAU,CAAI;IACtB,OAAO,CAAC,YAAY,CAAY;IAChC,OAAO,CAAC,WAAW,CAAC,CAAW;IAC/B,OAAO,CAAC,cAAc,CAA8B;IACpD,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,eAAe,CAAoB;IAC3C,OAAO,CAAC,mBAAmB,CAAoB;IAC/C,OAAO,CAAC,2BAA2B,CAAoB;IACvD,OAAO,CAAC,oBAAoB,CAAoB;IAChD,OAAO,CAAC,kBAAkB,CAAoB;IAC9C,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,mBAAmB,CAAqB;IAChD,OAAO,CAAC,sBAAsB,CAAqB;IACnD,OAAO,CAAC,YAAY,CAAY;IAChC,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,gBAAgB,CAAC,CAAW;IACpC,OAAO,CAAC,iBAAiB,CAAC,CAAW;IACrC,OAAO,CAAC,uBAAuB,CAAC,CAAW;IAC3C,OAAO,CAAC,yBAAyB,CAAC,CAAoB;IACtD,OAAO,CAAC,eAAe,CAAC,CAAW;IACnC,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAI;IAChC,OAAO,CAAC,oBAAoB,CAA0B;IAEtD,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,sBAAsB,CAAiB;IAC/C,OAAO,CAAC,mBAAmB,CAAa;IACxC,OAAO,CAAC,iBAAiB,CAAa;IACtC,OAAO,CAAC,iBAAiB,CAAa;IAEtC,OAAO,CAAC,oBAAoB,CAAoB;IAChD,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,oBAAoB,CAAoB;IAEhD,OAAO,CAAC,oBAAoB,CAAY;IACxC,OAAO,CAAC,mBAAmB,CAAY;IACvC,OAAO,CAAC,oBAAoB,CAAY;IACxC,OAAO,CAAC,oBAAoB,CAAY;IACxC,OAAO,CAAC,aAAa,CAAa;IAE3B,cAAc,EAAE,MAAM,CAAM;IAC5B,cAAc,EAAE,MAAM,CAAM;IAEnC,OAAO,CAAC,iBAAiB,CAAe;IACxC,OAAO,CAAC,aAAa,CAAc;IACnC,OAAO,CAAC,aAAa,CAA4C;IACjE,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,cAAc,CAAa;IACnC,OAAO,CAAC,YAAY,CAAgC;IACpD,OAAO,CAAC,YAAY,CAAuD;IAE3E,OAAO,CAAC,aAAa,CAAoB;IACzC,OAAO,CAAC,qBAAqB,CAAI;IACjC,OAAO,CAAC,gBAAgB,CAAe;IACvC,OAAO,CAAC,YAAY,CAAY;IAChC,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,aAAa,CAAoB;IACzC,OAAO,CAAC,KAAK,CAIZ;IACD,OAAO,CAAC,gBAAgB,CAAsB;IAC9C,OAAO,CAAC,kBAAkB,CAA4B;gBAE1C,MAAM,EAAE,iBAAiB;IAKxB,IAAI;IA+BjB,OAAO,CAAC,eAAe;IAwsBvB,OAAO,CAAC,+BAA+B;IAyCvC,OAAO,CAAC,oBAAoB;IAwC5B,OAAO,CAAC,oBAAoB;IAgP5B,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,YAAY;IAiGpB,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,aAAa;IAgBd,QAAQ,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,GAAE,MAAY,GAAG,OAAO;IAmBxE,UAAU,CAAC,SAAS,EAAE,MAAM;IAI5B,QAAQ,IAAI,WAAW;IAIvB,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI;IAgBnC,cAAc;IAQd,OAAO;IAUD,SAAS,CAAC,IAAI,EAAE,MAAM;IAW5B,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,UAAU,CAAC,EAAE,MAAM;YAK5D,iBAAiB;IA+F/B,OAAO,CAAC,wBAAwB,CAKxB;IACR,OAAO,CAAC,QAAQ,CAA+F;IAC/G,OAAO,CAAC,iBAAiB,CACrB;IACJ,OAAO,CAAC,oBAAoB,CAKpB;IACR,OAAO,CAAC,6BAA6B,CAK7B;IACR,OAAO,CAAC,+BAA+B,CAK/B;IACR,OAAO,CAAC,eAAe,CAA+F;IACtH,OAAO,CAAC,gBAAgB,CACpB;IACJ,OAAO,CAAC,oCAAoC,CAKpC;YAGM,cAAc;YA0Rd,qBAAqB;IAkD5B,MAAM;IA0Hb,OAAO,CAAC,UAAU;IA8IlB,OAAO,CAAC,oBAAoB;IAa5B,OAAO,CAAC,kBAAkB;IAY1B,OAAO,CAAC,eAAe;IA0BvB,OAAO,CAAC,mBAAmB;IAgC3B,OAAO,CAAC,YAAY;IAqBpB,OAAO,CAAC,WAAW;CA4GpB"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
package/dist/engine.js CHANGED
@@ -1072,6 +1072,65 @@ export class Engine {
1072
1072
  this.bloomThresholdBuffer = bloomThresholdBuffer;
1073
1073
  this.linearSampler = linearSampler;
1074
1074
  }
1075
+ // Setup bloom textures and bind groups (called when canvas is resized)
1076
+ setupBloom(width, height) {
1077
+ // Create bloom textures (half resolution for performance)
1078
+ const bloomWidth = Math.floor(width / 2);
1079
+ const bloomHeight = Math.floor(height / 2);
1080
+ this.bloomExtractTexture = this.device.createTexture({
1081
+ label: "bloom extract",
1082
+ size: [bloomWidth, bloomHeight],
1083
+ format: this.presentationFormat,
1084
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
1085
+ });
1086
+ this.bloomBlurTexture1 = this.device.createTexture({
1087
+ label: "bloom blur 1",
1088
+ size: [bloomWidth, bloomHeight],
1089
+ format: this.presentationFormat,
1090
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
1091
+ });
1092
+ this.bloomBlurTexture2 = this.device.createTexture({
1093
+ label: "bloom blur 2",
1094
+ size: [bloomWidth, bloomHeight],
1095
+ format: this.presentationFormat,
1096
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
1097
+ });
1098
+ // Create bloom bind groups
1099
+ this.bloomExtractBindGroup = this.device.createBindGroup({
1100
+ layout: this.bloomExtractPipeline.getBindGroupLayout(0),
1101
+ entries: [
1102
+ { binding: 0, resource: this.sceneRenderTexture.createView() },
1103
+ { binding: 1, resource: this.linearSampler },
1104
+ { binding: 2, resource: { buffer: this.bloomThresholdBuffer } },
1105
+ ],
1106
+ });
1107
+ this.bloomBlurHBindGroup = this.device.createBindGroup({
1108
+ layout: this.bloomBlurPipeline.getBindGroupLayout(0),
1109
+ entries: [
1110
+ { binding: 0, resource: this.bloomExtractTexture.createView() },
1111
+ { binding: 1, resource: this.linearSampler },
1112
+ { binding: 2, resource: { buffer: this.blurDirectionBuffer } },
1113
+ ],
1114
+ });
1115
+ this.bloomBlurVBindGroup = this.device.createBindGroup({
1116
+ layout: this.bloomBlurPipeline.getBindGroupLayout(0),
1117
+ entries: [
1118
+ { binding: 0, resource: this.bloomBlurTexture1.createView() },
1119
+ { binding: 1, resource: this.linearSampler },
1120
+ { binding: 2, resource: { buffer: this.blurDirectionBuffer } },
1121
+ ],
1122
+ });
1123
+ this.bloomComposeBindGroup = this.device.createBindGroup({
1124
+ layout: this.bloomComposePipeline.getBindGroupLayout(0),
1125
+ entries: [
1126
+ { binding: 0, resource: this.sceneRenderTexture.createView() },
1127
+ { binding: 1, resource: this.linearSampler },
1128
+ { binding: 2, resource: this.bloomBlurTexture2.createView() },
1129
+ { binding: 3, resource: this.linearSampler },
1130
+ { binding: 4, resource: { buffer: this.bloomIntensityBuffer } },
1131
+ ],
1132
+ });
1133
+ }
1075
1134
  // Step 3: Setup canvas resize handling
1076
1135
  setupResize() {
1077
1136
  this.resizeObserver = new ResizeObserver(() => this.handleResize());
@@ -1109,27 +1168,8 @@ export class Engine {
1109
1168
  usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
1110
1169
  });
1111
1170
  this.sceneRenderTextureView = this.sceneRenderTexture.createView();
1112
- // Create bloom textures (half resolution for performance)
1113
- const bloomWidth = Math.floor(width / 2);
1114
- const bloomHeight = Math.floor(height / 2);
1115
- this.bloomExtractTexture = this.device.createTexture({
1116
- label: "bloom extract",
1117
- size: [bloomWidth, bloomHeight],
1118
- format: this.presentationFormat,
1119
- usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
1120
- });
1121
- this.bloomBlurTexture1 = this.device.createTexture({
1122
- label: "bloom blur 1",
1123
- size: [bloomWidth, bloomHeight],
1124
- format: this.presentationFormat,
1125
- usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
1126
- });
1127
- this.bloomBlurTexture2 = this.device.createTexture({
1128
- label: "bloom blur 2",
1129
- size: [bloomWidth, bloomHeight],
1130
- format: this.presentationFormat,
1131
- usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
1132
- });
1171
+ // Setup bloom textures and bind groups
1172
+ this.setupBloom(width, height);
1133
1173
  const depthTextureView = this.depthTexture.createView();
1134
1174
  // Render scene to texture instead of directly to canvas
1135
1175
  const colorAttachment = this.sampleCount > 1
@@ -1302,6 +1342,16 @@ export class Engine {
1302
1342
  boneCountData[0] = boneCount;
1303
1343
  this.device.queue.writeBuffer(this.boneCountBuffer, 0, boneCountData);
1304
1344
  this.createSkinMatrixComputePipeline();
1345
+ // Create compute bind group once (reused every frame)
1346
+ this.skinMatrixComputeBindGroup = this.device.createBindGroup({
1347
+ layout: this.skinMatrixComputePipeline.getBindGroupLayout(0),
1348
+ entries: [
1349
+ { binding: 0, resource: { buffer: this.boneCountBuffer } },
1350
+ { binding: 1, resource: { buffer: this.worldMatrixBuffer } },
1351
+ { binding: 2, resource: { buffer: this.inverseBindMatrixBuffer } },
1352
+ { binding: 3, resource: { buffer: this.skinMatrixBuffer } },
1353
+ ],
1354
+ });
1305
1355
  const indices = model.getIndices();
1306
1356
  if (indices) {
1307
1357
  this.indexBuffer = this.device.createBuffer({
@@ -1751,16 +1801,8 @@ export class Engine {
1751
1801
  },
1752
1802
  ],
1753
1803
  });
1754
- const extractBindGroup = this.device.createBindGroup({
1755
- layout: this.bloomExtractPipeline.getBindGroupLayout(0),
1756
- entries: [
1757
- { binding: 0, resource: this.sceneRenderTexture.createView() },
1758
- { binding: 1, resource: this.linearSampler },
1759
- { binding: 2, resource: { buffer: this.bloomThresholdBuffer } },
1760
- ],
1761
- });
1762
1804
  extractPass.setPipeline(this.bloomExtractPipeline);
1763
- extractPass.setBindGroup(0, extractBindGroup);
1805
+ extractPass.setBindGroup(0, this.bloomExtractBindGroup);
1764
1806
  extractPass.draw(6, 1, 0, 0);
1765
1807
  extractPass.end();
1766
1808
  // Pass 2: Horizontal blur
@@ -1779,16 +1821,8 @@ export class Engine {
1779
1821
  },
1780
1822
  ],
1781
1823
  });
1782
- const blurHBindGroup = this.device.createBindGroup({
1783
- layout: this.bloomBlurPipeline.getBindGroupLayout(0),
1784
- entries: [
1785
- { binding: 0, resource: this.bloomExtractTexture.createView() },
1786
- { binding: 1, resource: this.linearSampler },
1787
- { binding: 2, resource: { buffer: this.blurDirectionBuffer } },
1788
- ],
1789
- });
1790
1824
  blurHPass.setPipeline(this.bloomBlurPipeline);
1791
- blurHPass.setBindGroup(0, blurHBindGroup);
1825
+ blurHPass.setBindGroup(0, this.bloomBlurHBindGroup);
1792
1826
  blurHPass.draw(6, 1, 0, 0);
1793
1827
  blurHPass.end();
1794
1828
  // Pass 3: Vertical blur
@@ -1807,16 +1841,8 @@ export class Engine {
1807
1841
  },
1808
1842
  ],
1809
1843
  });
1810
- const blurVBindGroup = this.device.createBindGroup({
1811
- layout: this.bloomBlurPipeline.getBindGroupLayout(0),
1812
- entries: [
1813
- { binding: 0, resource: this.bloomBlurTexture1.createView() },
1814
- { binding: 1, resource: this.linearSampler },
1815
- { binding: 2, resource: { buffer: this.blurDirectionBuffer } },
1816
- ],
1817
- });
1818
1844
  blurVPass.setPipeline(this.bloomBlurPipeline);
1819
- blurVPass.setBindGroup(0, blurVBindGroup);
1845
+ blurVPass.setBindGroup(0, this.bloomBlurVBindGroup);
1820
1846
  blurVPass.draw(6, 1, 0, 0);
1821
1847
  blurVPass.end();
1822
1848
  // Pass 4: Compose scene + bloom to canvas
@@ -1831,18 +1857,8 @@ export class Engine {
1831
1857
  },
1832
1858
  ],
1833
1859
  });
1834
- const composeBindGroup = this.device.createBindGroup({
1835
- layout: this.bloomComposePipeline.getBindGroupLayout(0),
1836
- entries: [
1837
- { binding: 0, resource: this.sceneRenderTexture.createView() },
1838
- { binding: 1, resource: this.linearSampler },
1839
- { binding: 2, resource: this.bloomBlurTexture2.createView() },
1840
- { binding: 3, resource: this.linearSampler },
1841
- { binding: 4, resource: { buffer: this.bloomIntensityBuffer } },
1842
- ],
1843
- });
1844
1860
  composePass.setPipeline(this.bloomComposePipeline);
1845
- composePass.setBindGroup(0, composeBindGroup);
1861
+ composePass.setBindGroup(0, this.bloomComposeBindGroup);
1846
1862
  composePass.draw(6, 1, 0, 0);
1847
1863
  composePass.end();
1848
1864
  this.device.queue.submit([encoder.finish()]);
@@ -1892,24 +1908,11 @@ export class Engine {
1892
1908
  const workgroupSize = 64;
1893
1909
  // Dispatch exactly enough threads for all bones (no bounds check needed)
1894
1910
  const workgroupCount = Math.ceil(boneCount / workgroupSize);
1895
- // Update bone count uniform
1896
- const boneCountData = new Uint32Array(8); // 32 bytes total
1897
- boneCountData[0] = boneCount;
1898
- this.device.queue.writeBuffer(this.boneCountBuffer, 0, boneCountData);
1899
- const bindGroup = this.device.createBindGroup({
1900
- label: "skin matrix compute bind group",
1901
- layout: this.skinMatrixComputePipeline.getBindGroupLayout(0),
1902
- entries: [
1903
- { binding: 0, resource: { buffer: this.boneCountBuffer } },
1904
- { binding: 1, resource: { buffer: this.worldMatrixBuffer } },
1905
- { binding: 2, resource: { buffer: this.inverseBindMatrixBuffer } },
1906
- { binding: 3, resource: { buffer: this.skinMatrixBuffer } },
1907
- ],
1908
- });
1911
+ // Bone count is written once in setupModelBuffers() and never changes
1909
1912
  const encoder = this.device.createCommandEncoder();
1910
1913
  const pass = encoder.beginComputePass();
1911
1914
  pass.setPipeline(this.skinMatrixComputePipeline);
1912
- pass.setBindGroup(0, bindGroup);
1915
+ pass.setBindGroup(0, this.skinMatrixComputeBindGroup);
1913
1916
  pass.dispatchWorkgroups(workgroupCount);
1914
1917
  pass.end();
1915
1918
  this.device.queue.submit([encoder.finish()]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reze-engine",
3
- "version": "0.1.13",
3
+ "version": "0.1.14",
4
4
  "description": "A WebGPU-based MMD model renderer",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
package/src/engine.ts CHANGED
@@ -40,6 +40,7 @@ export class Engine {
40
40
  private worldMatrixBuffer?: GPUBuffer
41
41
  private inverseBindMatrixBuffer?: GPUBuffer
42
42
  private skinMatrixComputePipeline?: GPUComputePipeline
43
+ private skinMatrixComputeBindGroup?: GPUBindGroup
43
44
  private boneCountBuffer?: GPUBuffer
44
45
  private multisampleTexture!: GPUTexture
45
46
  private readonly sampleCount = 4 // MSAA 4x
@@ -60,6 +61,11 @@ export class Engine {
60
61
  private bloomIntensityBuffer!: GPUBuffer
61
62
  private bloomThresholdBuffer!: GPUBuffer
62
63
  private linearSampler!: GPUSampler
64
+ // Bloom bind groups (created once, reused every frame)
65
+ private bloomExtractBindGroup?: GPUBindGroup
66
+ private bloomBlurHBindGroup?: GPUBindGroup
67
+ private bloomBlurVBindGroup?: GPUBindGroup
68
+ private bloomComposeBindGroup?: GPUBindGroup
63
69
  // Bloom settings
64
70
  public bloomThreshold: number = 0.3
65
71
  public bloomIntensity: number = 0.1
@@ -1156,6 +1162,70 @@ export class Engine {
1156
1162
  this.linearSampler = linearSampler
1157
1163
  }
1158
1164
 
1165
+ // Setup bloom textures and bind groups (called when canvas is resized)
1166
+ private setupBloom(width: number, height: number) {
1167
+ // Create bloom textures (half resolution for performance)
1168
+ const bloomWidth = Math.floor(width / 2)
1169
+ const bloomHeight = Math.floor(height / 2)
1170
+ this.bloomExtractTexture = this.device.createTexture({
1171
+ label: "bloom extract",
1172
+ size: [bloomWidth, bloomHeight],
1173
+ format: this.presentationFormat,
1174
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
1175
+ })
1176
+ this.bloomBlurTexture1 = this.device.createTexture({
1177
+ label: "bloom blur 1",
1178
+ size: [bloomWidth, bloomHeight],
1179
+ format: this.presentationFormat,
1180
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
1181
+ })
1182
+ this.bloomBlurTexture2 = this.device.createTexture({
1183
+ label: "bloom blur 2",
1184
+ size: [bloomWidth, bloomHeight],
1185
+ format: this.presentationFormat,
1186
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
1187
+ })
1188
+
1189
+ // Create bloom bind groups
1190
+ this.bloomExtractBindGroup = this.device.createBindGroup({
1191
+ layout: this.bloomExtractPipeline.getBindGroupLayout(0),
1192
+ entries: [
1193
+ { binding: 0, resource: this.sceneRenderTexture.createView() },
1194
+ { binding: 1, resource: this.linearSampler },
1195
+ { binding: 2, resource: { buffer: this.bloomThresholdBuffer } },
1196
+ ],
1197
+ })
1198
+
1199
+ this.bloomBlurHBindGroup = this.device.createBindGroup({
1200
+ layout: this.bloomBlurPipeline.getBindGroupLayout(0),
1201
+ entries: [
1202
+ { binding: 0, resource: this.bloomExtractTexture.createView() },
1203
+ { binding: 1, resource: this.linearSampler },
1204
+ { binding: 2, resource: { buffer: this.blurDirectionBuffer } },
1205
+ ],
1206
+ })
1207
+
1208
+ this.bloomBlurVBindGroup = this.device.createBindGroup({
1209
+ layout: this.bloomBlurPipeline.getBindGroupLayout(0),
1210
+ entries: [
1211
+ { binding: 0, resource: this.bloomBlurTexture1.createView() },
1212
+ { binding: 1, resource: this.linearSampler },
1213
+ { binding: 2, resource: { buffer: this.blurDirectionBuffer } },
1214
+ ],
1215
+ })
1216
+
1217
+ this.bloomComposeBindGroup = this.device.createBindGroup({
1218
+ layout: this.bloomComposePipeline.getBindGroupLayout(0),
1219
+ entries: [
1220
+ { binding: 0, resource: this.sceneRenderTexture.createView() },
1221
+ { binding: 1, resource: this.linearSampler },
1222
+ { binding: 2, resource: this.bloomBlurTexture2.createView() },
1223
+ { binding: 3, resource: this.linearSampler },
1224
+ { binding: 4, resource: { buffer: this.bloomIntensityBuffer } },
1225
+ ],
1226
+ })
1227
+ }
1228
+
1159
1229
  // Step 3: Setup canvas resize handling
1160
1230
  private setupResize() {
1161
1231
  this.resizeObserver = new ResizeObserver(() => this.handleResize())
@@ -1200,27 +1270,8 @@ export class Engine {
1200
1270
  })
1201
1271
  this.sceneRenderTextureView = this.sceneRenderTexture.createView()
1202
1272
 
1203
- // Create bloom textures (half resolution for performance)
1204
- const bloomWidth = Math.floor(width / 2)
1205
- const bloomHeight = Math.floor(height / 2)
1206
- this.bloomExtractTexture = this.device.createTexture({
1207
- label: "bloom extract",
1208
- size: [bloomWidth, bloomHeight],
1209
- format: this.presentationFormat,
1210
- usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
1211
- })
1212
- this.bloomBlurTexture1 = this.device.createTexture({
1213
- label: "bloom blur 1",
1214
- size: [bloomWidth, bloomHeight],
1215
- format: this.presentationFormat,
1216
- usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
1217
- })
1218
- this.bloomBlurTexture2 = this.device.createTexture({
1219
- label: "bloom blur 2",
1220
- size: [bloomWidth, bloomHeight],
1221
- format: this.presentationFormat,
1222
- usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
1223
- })
1273
+ // Setup bloom textures and bind groups
1274
+ this.setupBloom(width, height)
1224
1275
 
1225
1276
  const depthTextureView = this.depthTexture.createView()
1226
1277
 
@@ -1447,6 +1498,17 @@ export class Engine {
1447
1498
 
1448
1499
  this.createSkinMatrixComputePipeline()
1449
1500
 
1501
+ // Create compute bind group once (reused every frame)
1502
+ this.skinMatrixComputeBindGroup = this.device.createBindGroup({
1503
+ layout: this.skinMatrixComputePipeline!.getBindGroupLayout(0),
1504
+ entries: [
1505
+ { binding: 0, resource: { buffer: this.boneCountBuffer } },
1506
+ { binding: 1, resource: { buffer: this.worldMatrixBuffer } },
1507
+ { binding: 2, resource: { buffer: this.inverseBindMatrixBuffer } },
1508
+ { binding: 3, resource: { buffer: this.skinMatrixBuffer } },
1509
+ ],
1510
+ })
1511
+
1450
1512
  const indices = model.getIndices()
1451
1513
  if (indices) {
1452
1514
  this.indexBuffer = this.device.createBuffer({
@@ -1987,17 +2049,8 @@ export class Engine {
1987
2049
  ],
1988
2050
  })
1989
2051
 
1990
- const extractBindGroup = this.device.createBindGroup({
1991
- layout: this.bloomExtractPipeline.getBindGroupLayout(0),
1992
- entries: [
1993
- { binding: 0, resource: this.sceneRenderTexture.createView() },
1994
- { binding: 1, resource: this.linearSampler },
1995
- { binding: 2, resource: { buffer: this.bloomThresholdBuffer } },
1996
- ],
1997
- })
1998
-
1999
2052
  extractPass.setPipeline(this.bloomExtractPipeline)
2000
- extractPass.setBindGroup(0, extractBindGroup)
2053
+ extractPass.setBindGroup(0, this.bloomExtractBindGroup!)
2001
2054
  extractPass.draw(6, 1, 0, 0)
2002
2055
  extractPass.end()
2003
2056
 
@@ -2018,17 +2071,8 @@ export class Engine {
2018
2071
  ],
2019
2072
  })
2020
2073
 
2021
- const blurHBindGroup = this.device.createBindGroup({
2022
- layout: this.bloomBlurPipeline.getBindGroupLayout(0),
2023
- entries: [
2024
- { binding: 0, resource: this.bloomExtractTexture.createView() },
2025
- { binding: 1, resource: this.linearSampler },
2026
- { binding: 2, resource: { buffer: this.blurDirectionBuffer } },
2027
- ],
2028
- })
2029
-
2030
2074
  blurHPass.setPipeline(this.bloomBlurPipeline)
2031
- blurHPass.setBindGroup(0, blurHBindGroup)
2075
+ blurHPass.setBindGroup(0, this.bloomBlurHBindGroup!)
2032
2076
  blurHPass.draw(6, 1, 0, 0)
2033
2077
  blurHPass.end()
2034
2078
 
@@ -2049,17 +2093,8 @@ export class Engine {
2049
2093
  ],
2050
2094
  })
2051
2095
 
2052
- const blurVBindGroup = this.device.createBindGroup({
2053
- layout: this.bloomBlurPipeline.getBindGroupLayout(0),
2054
- entries: [
2055
- { binding: 0, resource: this.bloomBlurTexture1.createView() },
2056
- { binding: 1, resource: this.linearSampler },
2057
- { binding: 2, resource: { buffer: this.blurDirectionBuffer } },
2058
- ],
2059
- })
2060
-
2061
2096
  blurVPass.setPipeline(this.bloomBlurPipeline)
2062
- blurVPass.setBindGroup(0, blurVBindGroup)
2097
+ blurVPass.setBindGroup(0, this.bloomBlurVBindGroup!)
2063
2098
  blurVPass.draw(6, 1, 0, 0)
2064
2099
  blurVPass.end()
2065
2100
 
@@ -2076,19 +2111,8 @@ export class Engine {
2076
2111
  ],
2077
2112
  })
2078
2113
 
2079
- const composeBindGroup = this.device.createBindGroup({
2080
- layout: this.bloomComposePipeline.getBindGroupLayout(0),
2081
- entries: [
2082
- { binding: 0, resource: this.sceneRenderTexture.createView() },
2083
- { binding: 1, resource: this.linearSampler },
2084
- { binding: 2, resource: this.bloomBlurTexture2.createView() },
2085
- { binding: 3, resource: this.linearSampler },
2086
- { binding: 4, resource: { buffer: this.bloomIntensityBuffer } },
2087
- ],
2088
- })
2089
-
2090
2114
  composePass.setPipeline(this.bloomComposePipeline)
2091
- composePass.setBindGroup(0, composeBindGroup)
2115
+ composePass.setBindGroup(0, this.bloomComposeBindGroup!)
2092
2116
  composePass.draw(6, 1, 0, 0)
2093
2117
  composePass.end()
2094
2118
 
@@ -2153,26 +2177,12 @@ export class Engine {
2153
2177
  // Dispatch exactly enough threads for all bones (no bounds check needed)
2154
2178
  const workgroupCount = Math.ceil(boneCount / workgroupSize)
2155
2179
 
2156
- // Update bone count uniform
2157
- const boneCountData = new Uint32Array(8) // 32 bytes total
2158
- boneCountData[0] = boneCount
2159
- this.device.queue.writeBuffer(this.boneCountBuffer!, 0, boneCountData)
2160
-
2161
- const bindGroup = this.device.createBindGroup({
2162
- label: "skin matrix compute bind group",
2163
- layout: this.skinMatrixComputePipeline!.getBindGroupLayout(0),
2164
- entries: [
2165
- { binding: 0, resource: { buffer: this.boneCountBuffer! } },
2166
- { binding: 1, resource: { buffer: this.worldMatrixBuffer! } },
2167
- { binding: 2, resource: { buffer: this.inverseBindMatrixBuffer! } },
2168
- { binding: 3, resource: { buffer: this.skinMatrixBuffer! } },
2169
- ],
2170
- })
2180
+ // Bone count is written once in setupModelBuffers() and never changes
2171
2181
 
2172
2182
  const encoder = this.device.createCommandEncoder()
2173
2183
  const pass = encoder.beginComputePass()
2174
2184
  pass.setPipeline(this.skinMatrixComputePipeline!)
2175
- pass.setBindGroup(0, bindGroup)
2185
+ pass.setBindGroup(0, this.skinMatrixComputeBindGroup!)
2176
2186
  pass.dispatchWorkgroups(workgroupCount)
2177
2187
  pass.end()
2178
2188
  this.device.queue.submit([encoder.finish()])