diff --git a/examples/assets/DamagedHelmet.glb b/examples/assets/DamagedHelmet.glb new file mode 100644 index 0000000..2cee76d Binary files /dev/null and b/examples/assets/DamagedHelmet.glb differ diff --git a/examples/index.html b/examples/index.html index 0617fa1..3b65425 100644 --- a/examples/index.html +++ b/examples/index.html @@ -17,6 +17,7 @@

Spark.js Examples

  • spark.js basic example
  • spark.js svg example
  • three.js + spark.js basic example
  • +
  • three.js + spark.js GLTF example
  • \ No newline at end of file diff --git a/examples/three-basic.html b/examples/three-basic.html index 6cf8527..86d247b 100644 --- a/examples/three-basic.html +++ b/examples/three-basic.html @@ -13,7 +13,7 @@ + + diff --git a/package-lock.json b/package-lock.json index 168807c..6a7f84c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,11 @@ "npm-run-all": "^4.1.5", "prettier": "^3.0.0", "rimraf": "^5.0.0", + "three": "^0.180.0", "vite": "^7.0.0" + }, + "peerDependencies": { + "three": "^0.180.0" } }, "node_modules/@esbuild/aix-ppc64": { @@ -4099,6 +4103,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/three": { + "version": "0.180.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.180.0.tgz", + "integrity": "sha512-o+qycAMZrh+TsE01GqWUxUIKR1AL0S8pq7zDkYOQw8GqfX8b8VoCKYUoHbhiX5j+7hr8XsuHDVU6+gkQJQKg9w==", + "dev": true, + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", diff --git a/package.json b/package.json index 83ddef7..63739c0 100644 --- a/package.json +++ b/package.json @@ -61,8 +61,12 @@ "npm-run-all": "^4.1.5", "prettier": "^3.0.0", "rimraf": "^5.0.0", + "three": "^0.180.0", "vite": "^7.0.0" }, + "peerDependencies": { + "three": "^0.180.0" + }, "publishConfig": { "access": "public" }, diff --git a/src/spark.js b/src/spark.js index e6077c0..09426e7 100644 --- a/src/spark.js +++ b/src/spark.js @@ -336,6 +336,8 @@ class Spark { #queryBuffer #queryReadbackBuffer + #encodeCounter = 0 + /** * Initialize the encoder by detecting available compression formats. * @param {GPUDevice} device - WebGPU device. @@ -555,7 +557,8 @@ class Spark { // a single temporary texture that is reused for all texture uploads, and resized/freed as needed. // Allocate input texture. @@ This texture could be persistent. - console.time("create input texture") + const counter = this.#encodeCounter++ + console.time("create input texture #" + counter) let inputUsage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.STORAGE_BINDING @@ -567,7 +570,7 @@ class Spark { const commandEncoder = this.#device.createCommandEncoder() - commandEncoder.pushDebugGroup?.("spark process texture"); + commandEncoder.pushDebugGroup?.("spark process texture") if (this.#querySet && typeof commandEncoder.writeTimestamp === "function") { commandEncoder.writeTimestamp(this.#querySet, 0) @@ -630,9 +633,9 @@ class Spark { this.#generateMipmaps(commandEncoder, inputTexture, mipmapCount, width, height, srgb) } - commandEncoder.popDebugGroup?.(); + commandEncoder.popDebugGroup?.() - console.timeEnd("create input texture") + console.timeEnd("create input texture #" + counter) // Allocate output texture. const outputTexture = this.#device.createTexture({ @@ -649,9 +652,9 @@ class Spark { }) // Dispatch compute shader to encode the input texture in the output buffer. - console.time("dispatch compute shader") + console.time("dispatch compute shader #" + counter) - commandEncoder.pushDebugGroup?.("spark encode texture"); + commandEncoder.pushDebugGroup?.("spark encode texture") let args = {} if (this.#querySet && typeof commandEncoder.writeTimestamp !== "function") { @@ -727,11 +730,11 @@ class Spark { commandEncoder.writeTimestamp(this.#querySet, 1) } - commandEncoder.popDebugGroup?.(); + commandEncoder.popDebugGroup?.() this.#device.queue.submit([commandEncoder.finish()]) - console.timeEnd("dispatch compute shader") + console.timeEnd("dispatch compute shader #" + counter) // Destroy temporary buffers/textures after the work is done. // this.#device.queue.onSubmittedWorkDone().then(() => {