Browse Source

Added HTMLTexture support to WebGPU renderer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mr.doob 1 week ago
parent
commit
f27dc87235
2 changed files with 103 additions and 1 deletions
  1. 27 1
      src/renderers/common/Textures.js
  2. 76 0
      src/renderers/webgpu/utils/WebGPUTextureUtils.js

+ 27 - 1
src/renderers/common/Textures.js

@@ -220,6 +220,26 @@ class Textures extends DataMap {
 
 		}
 
+		// Ensure HTMLTexture elements are in the canvas before measuring size.
+
+		if ( texture.isHTMLTexture && texture.image ) {
+
+			const canvas = this.renderer.domElement;
+
+			if ( ! canvas.hasAttribute( 'layoutsubtree' ) ) {
+
+				canvas.setAttribute( 'layoutsubtree', 'true' );
+
+			}
+
+			if ( texture.image.parentNode !== canvas ) {
+
+				canvas.appendChild( texture.image );
+
+			}
+
+		}
+
 		//
 
 		const { width, height, depth } = this.getSize( texture );
@@ -390,7 +410,13 @@ class Textures extends DataMap {
 
 			if ( image.image !== undefined ) image = image.image;
 
-			if ( ( typeof HTMLVideoElement !== 'undefined' ) && ( image instanceof HTMLVideoElement ) ) {
+			if ( texture.isHTMLTexture ) {
+
+				target.width = image.offsetWidth || 1;
+				target.height = image.offsetHeight || 1;
+				target.depth = 1;
+
+			} else if ( ( typeof HTMLVideoElement !== 'undefined' ) && ( image instanceof HTMLVideoElement ) ) {
 
 				target.width = image.videoWidth || 1;
 				target.height = image.videoHeight || 1;

+ 76 - 0
src/renderers/webgpu/utils/WebGPUTextureUtils.js

@@ -95,6 +95,13 @@ class WebGPUTextureUtils {
 		 */
 		this._samplerCache = new Map();
 
+		/**
+		 * A set of HTMLTextures that need paint updates.
+		 *
+		 * @type {Set<HTMLTexture>}
+		 */
+		this._htmlTextures = new Set();
+
 	}
 
 	/**
@@ -357,6 +364,8 @@ class WebGPUTextureUtils {
 
 		if ( textureData.msaaTexture !== undefined ) textureData.msaaTexture.destroy();
 
+		this._htmlTextures.delete( texture );
+
 		backend.delete( texture );
 
 	}
@@ -566,6 +575,39 @@ class WebGPUTextureUtils {
 
 			this._copyCubeMapToTexture( texture, textureData.texture, textureDescriptorGPU );
 
+		} else if ( texture.isHTMLTexture ) {
+
+			const device = this.backend.device;
+			const canvas = this.backend.renderer.domElement;
+			const image = texture.image;
+
+			// Set up paint callback if not already done.
+			if ( ! textureData.hasPaintCallback ) {
+
+				textureData.hasPaintCallback = true;
+
+				this._addHTMLTexture( texture );
+
+				// Wait for the browser to paint the element before uploading.
+				canvas.requestPaint();
+				return;
+
+			}
+
+			const width = textureDescriptorGPU.size.width;
+			const height = textureDescriptorGPU.size.height;
+
+			device.queue.copyElementImageToTexture(
+				image, width, height,
+				{ texture: textureData.texture }
+			);
+
+			if ( texture.flipY ) {
+
+				this._flipY( textureData.texture, textureDescriptorGPU );
+
+			}
+
 		} else {
 
 			if ( mipmaps.length > 0 ) {
@@ -654,12 +696,46 @@ class WebGPUTextureUtils {
 
 	}
 
+	/**
+	 * Registers an HTMLTexture for paint updates.
+	 * Sets up a single shared `onpaint` handler on the canvas
+	 * that notifies all registered HTMLTextures.
+	 *
+	 * @private
+	 * @param {HTMLTexture} texture - The HTMLTexture to register.
+	 */
+	_addHTMLTexture( texture ) {
+
+		this._htmlTextures.add( texture );
+
+		const canvas = this.backend.renderer.domElement;
+		const htmlTextures = this._htmlTextures;
+
+		canvas.onpaint = ( event ) => {
+
+			const changed = event.changedElements;
+
+			for ( const t of htmlTextures ) {
+
+				if ( changed.includes( t.image ) ) {
+
+					t.needsUpdate = true;
+
+				}
+
+			}
+
+		};
+
+	}
+
 	/**
 	 * Frees all internal resources.
 	 */
 	dispose() {
 
 		this._samplerCache.clear();
+		this._htmlTextures.clear();
 
 	}
 

粤ICP备19079148号