Skip to content

Conversation

@donmccurdy
Copy link
Collaborator

@donmccurdy donmccurdy commented Aug 15, 2025

Related issue:

Adds support for initializing a THREE.ExternalTexture instance with a GPUTexture created by the WebGPU renderer's own device. Provides a fast path for using textures created by other libraries (example: https://ludicon.com/sparkjs/) without extra copies.

Example:

import { Spark } from '@ludicon/spark.js';

const gpuTexture = await spark.encodeTexture( texturePath, { mips: true, srgb: true, flipY: true } );

const texture = new THREE.ExternalTexture( gpuTexture );

On local testing, our textures/uv_grid_opengl.jpg is compressed to BC7 in 0.1 ms (!) on an M1 device.

The code changes required are trivial, but I'm not sure if using THREE.ExternalTexture as proposed in #31595 is semantically right — this is the opposite of a "texture created externally from the renderer context" as the JSDoc suggests... Would it make more sense to use THREE.CompressedTexture? A new THREE.InternalTexture or THREE.GPUTexture class? My (slight) preference would be to keep using THREE.ExternalTexture, but to update the documentation to say "externally from three.js" instead.

@donmccurdy donmccurdy changed the title WebGPURenderer: Support ExternalTexture WebGPURenderer: Support ExternalTexture with GPUTexture Aug 15, 2025
@github-actions
Copy link

github-actions bot commented Aug 15, 2025

📦 Bundle size

Full ESM build, minified and gzipped.

Before After Diff
WebGL 338.96
79.12
338.91
79.11
-51 B
-16 B
WebGPU 575.35
158.76
575.47
158.8
+121 B
+44 B
WebGPU Nodes 573.96
158.51
574.08
158.56
+121 B
+45 B

🌳 Bundle size after tree-shaking

Minimal build including a renderer, camera, empty scene, and dependencies.

Before After Diff
WebGL 470.7
113.89
470.7
113.91
+0 B
+23 B
WebGPU 646.42
174.83
646.53
174.86
+105 B
+27 B
WebGPU Nodes 600.6
164.01
600.71
164.04
+105 B
+30 B

@Mugen87
Copy link
Collaborator

Mugen87 commented Aug 15, 2025

What kind of object type is gpuTexture returned by spark?

ExternalTexture is intended for the case when external components like third-party projects share the same rendering context and provide raw/native texture objects for use. So GL or GPU texture object.

ExternalTexture is not intended for any other use case. If an external component generates a canvas with color data, CanvasTexture should be used. If the data are represented as (typed) arrays, it should be DataTexture or CompressedTexture depending on whether compression is used or not.

@donmccurdy
Copy link
Collaborator Author

Ahh ok, thanks. I'd misread the JSDoc description on ExternalTexture. Spark.js returns a WebGPU GPUTexture, so ExternalTexture would be the right class then!

@Mugen87 Mugen87 added this to the r180 milestone Aug 15, 2025
@sunag sunag merged commit aec0e87 into mrdoob:dev Aug 16, 2025
9 checks passed
@donmccurdy donmccurdy deleted the feat/externaltexture-webgpu branch August 16, 2025 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants