Răsfoiți Sursa

Merge pull request #20257 from Mugen87/dev35

WebGPUTextures: Use ImageBitmap.
Michael Herzog 4 ani în urmă
părinte
comite
16d8e2e22f
1 a modificat fișierele cu 33 adăugiri și 61 ștergeri
  1. 33 61
      examples/jsm/renderers/webgpu/WebGPUTextures.js

+ 33 - 61
examples/jsm/renderers/webgpu/WebGPUTextures.js

@@ -11,7 +11,6 @@ class WebGPUTextures {
 
 		this.defaultTexture = null;
 		this.defaultSampler = null;
-		this.canvas = null;
 
 		this.samplerCache = new WeakMap();
 
@@ -33,7 +32,7 @@ class WebGPUTextures {
 
 		if ( this.defaultTexture === null ) {
 
-			this.defaultTexture = this._createTexture( new Texture( new Image( 1, 1 ) ) );
+			this.defaultTexture = this._createTexture( new Texture() );
 
 		}
 
@@ -165,88 +164,61 @@ class WebGPUTextures {
 		const device = this.device;
 		const image = texture.image;
 
-		if ( this.canvas === null ) this.canvas = new OffscreenCanvas( 1, 1 );
+		const width = ( image !== undefined ) ? image.width : 1;
+		const height = ( image !== undefined ) ? image.height : 1;
 
-		const width = image.width;
-		const height = image.height;
-
-		this.canvas.width = width;
-		this.canvas.height = height;
+		const textureGPU = device.createTexture( {
+			size: {
+				width: width,
+				height: height,
+				depth: 1,
+			},
+			format: "rgba8unorm",
+			usage: GPUTextureUsage.SAMPLED | GPUTextureUsage.COPY_DST,
+		} );
 
-		const context = this.canvas.getContext( '2d' );
-		context.translate( 0, height );
-		context.scale( 1, - 1 );
-		context.drawImage( image, 0, 0, width, height );
-		const imageData = context.getImageData( 0, 0, width, height );
+		// convert HTML iamges and canvas elements to ImageBitmap before copy
 
-		let data = null;
+		if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
+			( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ) {
 
-		const bytesPerRow = Math.ceil( width * 4 / 256 ) * 256;
+			createImageBitmap( image, 0, 0, width, height ).then( imageBitmap => {
 
-		if ( bytesPerRow === width * 4 ) {
+				this._uploadTexture( imageBitmap, textureGPU );
 
-			data = imageData.data;
+			} );
 
 		} else {
 
-			// ensure 4 byte alignment
-
-			data = new Uint8Array( bytesPerRow * height );
-			let imagePixelIndex = 0;
-
-			for ( let y = 0; y < height; ++ y ) {
-
-				for ( let x = 0; x < width; ++ x ) {
+			if ( image !== undefined ) {
 
-					const i = x * 4 + y * bytesPerRow;
-					data[ i ] = imageData.data[ imagePixelIndex ];
-					data[ i + 1 ] = imageData.data[ imagePixelIndex + 1 ];
-					data[ i + 2 ] = imageData.data[ imagePixelIndex + 2 ];
-					data[ i + 3 ] = imageData.data[ imagePixelIndex + 3 ];
-					imagePixelIndex += 4;
+				// assuming ImageBitmap. Directly start operation of the contents of ImageBitmap into the destination texture
 
-				}
+				this._uploadTexture( image, textureGPU );
 
 			}
 
 		}
 
-		const textureGPU = device.createTexture( {
-			size: {
-				width: image.width,
-				height: image.height,
-				depth: 1,
-			},
-			format: "rgba8unorm",
-			usage: GPUTextureUsage.SAMPLED | GPUTextureUsage.COPY_DST,
-		} );
-
-		const buffer = device.createBuffer( {
-			size: data.byteLength,
-			usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC,
-			mappedAtCreation: true,
-		} );
+		return textureGPU;
 
-		new Uint8Array( buffer.getMappedRange() ).set( data );
+	}
 
-		buffer.unmap();
+	_uploadTexture( imageBitmap, textureGPU ) {
 
-		const commandEncoder = device.createCommandEncoder( {} );
+		const device = this.device;
 
-		commandEncoder.copyBufferToTexture(
+		device.defaultQueue.copyImageBitmapToTexture(
 			{
-				buffer: buffer, bytesPerRow: bytesPerRow,
+				imageBitmap: imageBitmap
 			}, {
-				texture: textureGPU,
+				texture: textureGPU
 			}, {
-				width: image.width,
-				height: image.height,
-				depth: 1,
-			} );
-		device.defaultQueue.submit( [ commandEncoder.finish() ] );
-		buffer.destroy();
-
-		return textureGPU;
+				width: imageBitmap.width,
+				height: imageBitmap.height,
+				depth: 1
+			}
+		);
 
 	}