Browse Source

read tex async (#27006)

Co-authored-by: aardgoose <[email protected]>
aardgoose 1 year ago
parent
commit
3b86f576ce

+ 2 - 2
examples/jsm/renderers/webgl/WebGLBackend.js

@@ -605,9 +605,9 @@ class WebGLBackend extends Backend {
 
 
 	}
 	}
 
 
-	copyTextureToBuffer( /*texture, x, y, width, height*/ ) {
+	copyTextureToBuffer( texture, x, y, width, height ) {
 
 
-		console.warn( 'Abstract class.' );
+		return this.textureUtils.copyTextureToBuffer( texture, x, y, width, height );
 
 
 	}
 	}
 
 

+ 103 - 0
examples/jsm/renderers/webgl/utils/WebGLTextureUtils.js

@@ -211,6 +211,109 @@ class WebGLTextureUtils {
 
 
 	}
 	}
 
 
+	async copyTextureToBuffer( texture, x, y, width, height ) {
+
+		const { gl } = this;
+
+		const { textureGPU, glFormat, glType } = this.backend.get( texture );
+
+		const fb = gl.createFramebuffer();
+
+		gl.bindFramebuffer( gl.READ_FRAMEBUFFER, fb );
+		gl.framebufferTexture2D( gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textureGPU, 0 );
+
+		const typedArrayType = this._getTypedArrayType( glType );
+		const bytesPerTexel = this._getBytesPerTexel( glFormat );
+
+		const elementCount = width * height;
+		const byteLength = elementCount * bytesPerTexel;
+
+		const buffer = gl.createBuffer();
+
+		gl.bindBuffer( gl.PIXEL_PACK_BUFFER, buffer );
+		gl.bufferData( gl.PIXEL_PACK_BUFFER, byteLength, gl.STREAM_READ );
+		gl.readPixels( x, y, width, height, glFormat, glType, 0 );
+		gl.bindBuffer( gl.PIXEL_PACK_BUFFER, null );
+
+		const sync = gl.fenceSync( gl.SYNC_GPU_COMMANDS_COMPLETE, 0 );
+
+		gl.flush();
+
+		await this._clientWaitAsync( sync );
+
+		gl.deleteSync( sync );
+
+		const dstBuffer = new typedArrayType( elementCount );
+
+		gl.bindBuffer(  gl.PIXEL_PACK_BUFFER, buffer );
+		gl.getBufferSubData( gl.PIXEL_PACK_BUFFER, 0, dstBuffer );
+		gl.bindBuffer(  gl.PIXEL_PACK_BUFFER, null );
+
+		return dstBuffer;
+
+	}
+
+	_getTypedArrayType( glType ) {
+
+		const { gl } = this;
+
+		if ( glType === gl.UNSIGNED_BYTE ) return Uint8Array;
+
+		if ( glType === gl.UNSIGNED_SHORT_4_4_4_4 ) return Uint16Array;
+		if ( glType === gl.UNSIGNED_SHORT_5_5_5_1 ) return Uint16Array;
+		if ( glType === gl.UNSIGNED_SHORT_5_6_5 ) return Uint16Array;
+		if ( glType === gl.UNSIGNED_SHORT ) return Uint16Array;
+
+		if ( glType === gl.UNSIGNED_INT ) return Uint32Array;
+
+		if ( glType === gl.UNSIGNED_FLOAT ) return Float32Array;
+
+	}
+
+	_getBytesPerTexel( glFormat ) {
+
+		const { gl } = this;
+
+		if ( glFormat === gl.RGBA ) return 4;
+		if ( glFormat === gl.RGB ) return 3;
+		if ( glFormat === gl.ALPHA ) return 1;
+
+	}
+
+	_clientWaitAsync( sync ) {
+
+		const { gl } = this;
+
+		return new Promise( ( resolve, reject ) => {
+
+			function test() {
+
+				const res = gl.clientWaitSync( sync, gl.SYNC_FLUSH_COMMANDS_BIT, 0 );
+
+				if ( res === gl.WAIT_FAILED) {
+
+					reject();
+					return;
+
+				}
+
+				if ( res === gl.TIMEOUT_EXPIRED) {
+
+					requestAnimationFrame( test );
+					return;
+
+				}
+
+				resolve();
+
+			}
+
+			test();
+
+		} );
+
+	}
+
 }
 }
 
 
 export default WebGLTextureUtils;
 export default WebGLTextureUtils;