添加关照、全局等高线、修改图层问题
This commit is contained in:
		| @ -0,0 +1,321 @@ | ||||
| import { Float16BufferAttribute } from 'three'; | ||||
| import { GPUInputStepMode } from './WebGPUConstants.js'; | ||||
|  | ||||
| const typedArraysToVertexFormatPrefix = new Map( [ | ||||
| 	[ Int8Array, [ 'sint8', 'snorm8' ]], | ||||
| 	[ Uint8Array, [ 'uint8', 'unorm8' ]], | ||||
| 	[ Int16Array, [ 'sint16', 'snorm16' ]], | ||||
| 	[ Uint16Array, [ 'uint16', 'unorm16' ]], | ||||
| 	[ Int32Array, [ 'sint32', 'snorm32' ]], | ||||
| 	[ Uint32Array, [ 'uint32', 'unorm32' ]], | ||||
| 	[ Float32Array, [ 'float32', ]], | ||||
| ] ); | ||||
|  | ||||
| const typedAttributeToVertexFormatPrefix = new Map( [ | ||||
| 	[ Float16BufferAttribute, [ 'float16', ]], | ||||
| ] ); | ||||
|  | ||||
| const typeArraysToVertexFormatPrefixForItemSize1 = new Map( [ | ||||
| 	[ Int32Array, 'sint32' ], | ||||
| 	[ Int16Array, 'sint32' ], // patch for INT16 | ||||
| 	[ Uint32Array, 'uint32' ], | ||||
| 	[ Uint16Array, 'uint32' ], // patch for UINT16 | ||||
| 	[ Float32Array, 'float32' ] | ||||
| ] ); | ||||
|  | ||||
| class WebGPUAttributeUtils { | ||||
|  | ||||
| 	constructor( backend ) { | ||||
|  | ||||
| 		this.backend = backend; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	createAttribute( attribute, usage ) { | ||||
|  | ||||
| 		const bufferAttribute = this._getBufferAttribute( attribute ); | ||||
|  | ||||
| 		const backend = this.backend; | ||||
| 		const bufferData = backend.get( bufferAttribute ); | ||||
|  | ||||
| 		let buffer = bufferData.buffer; | ||||
|  | ||||
| 		if ( buffer === undefined ) { | ||||
|  | ||||
| 			const device = backend.device; | ||||
|  | ||||
| 			let array = bufferAttribute.array; | ||||
|  | ||||
| 			// patch for INT16 and UINT16 | ||||
| 			if ( attribute.normalized === false && ( array.constructor === Int16Array || array.constructor === Uint16Array ) ) { | ||||
|  | ||||
| 				const tempArray = new Uint32Array( array.length ); | ||||
| 				for ( let i = 0; i < array.length; i ++ ) { | ||||
|  | ||||
| 					tempArray[ i ] = array[ i ]; | ||||
|  | ||||
| 				} | ||||
|  | ||||
| 				array = tempArray; | ||||
|  | ||||
| 			} | ||||
|  | ||||
| 			bufferAttribute.array = array; | ||||
|  | ||||
| 			if ( ( bufferAttribute.isStorageBufferAttribute || bufferAttribute.isStorageInstancedBufferAttribute ) && bufferAttribute.itemSize === 3 ) { | ||||
|  | ||||
| 				array = new array.constructor( bufferAttribute.count * 4 ); | ||||
|  | ||||
| 				for ( let i = 0; i < bufferAttribute.count; i ++ ) { | ||||
|  | ||||
| 					array.set( bufferAttribute.array.subarray( i * 3, i * 3 + 3 ), i * 4 ); | ||||
|  | ||||
| 				} | ||||
|  | ||||
| 				// Update BufferAttribute | ||||
| 				bufferAttribute.itemSize = 4; | ||||
| 				bufferAttribute.array = array; | ||||
|  | ||||
| 			} | ||||
|  | ||||
| 			const size = array.byteLength + ( ( 4 - ( array.byteLength % 4 ) ) % 4 ); // ensure 4 byte alignment, see #20441 | ||||
|  | ||||
| 			buffer = device.createBuffer( { | ||||
| 				label: bufferAttribute.name, | ||||
| 				size: size, | ||||
| 				usage: usage, | ||||
| 				mappedAtCreation: true | ||||
| 			} ); | ||||
|  | ||||
| 			new array.constructor( buffer.getMappedRange() ).set( array ); | ||||
|  | ||||
| 			buffer.unmap(); | ||||
|  | ||||
| 			bufferData.buffer = buffer; | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	updateAttribute( attribute ) { | ||||
|  | ||||
| 		const bufferAttribute = this._getBufferAttribute( attribute ); | ||||
|  | ||||
| 		const backend = this.backend; | ||||
| 		const device = backend.device; | ||||
|  | ||||
| 		const buffer = backend.get( bufferAttribute ).buffer; | ||||
|  | ||||
| 		const array = bufferAttribute.array; | ||||
| 		const updateRanges = bufferAttribute.updateRanges; | ||||
|  | ||||
| 		if ( updateRanges.length === 0 ) { | ||||
|  | ||||
| 			// Not using update ranges | ||||
|  | ||||
| 			device.queue.writeBuffer( | ||||
| 				buffer, | ||||
| 				0, | ||||
| 				array, | ||||
| 				0 | ||||
| 			); | ||||
|  | ||||
| 		} else { | ||||
|  | ||||
| 			for ( let i = 0, l = updateRanges.length; i < l; i ++ ) { | ||||
|  | ||||
| 				const range = updateRanges[ i ]; | ||||
| 				device.queue.writeBuffer( | ||||
| 					buffer, | ||||
| 					0, | ||||
| 					array, | ||||
| 					range.start * array.BYTES_PER_ELEMENT, | ||||
| 					range.count * array.BYTES_PER_ELEMENT | ||||
| 				); | ||||
|  | ||||
| 			} | ||||
|  | ||||
| 			bufferAttribute.clearUpdateRanges(); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	createShaderVertexBuffers( renderObject ) { | ||||
|  | ||||
| 		const attributes = renderObject.getAttributes(); | ||||
| 		const vertexBuffers = new Map(); | ||||
|  | ||||
| 		for ( let slot = 0; slot < attributes.length; slot ++ ) { | ||||
|  | ||||
| 			const geometryAttribute = attributes[ slot ]; | ||||
| 			const bytesPerElement = geometryAttribute.array.BYTES_PER_ELEMENT; | ||||
| 			const bufferAttribute = this._getBufferAttribute( geometryAttribute ); | ||||
|  | ||||
| 			let vertexBufferLayout = vertexBuffers.get( bufferAttribute ); | ||||
|  | ||||
| 			if ( vertexBufferLayout === undefined ) { | ||||
|  | ||||
| 				let arrayStride, stepMode; | ||||
|  | ||||
| 				if ( geometryAttribute.isInterleavedBufferAttribute === true ) { | ||||
|  | ||||
| 					arrayStride = geometryAttribute.data.stride * bytesPerElement; | ||||
| 					stepMode = geometryAttribute.data.isInstancedInterleavedBuffer ? GPUInputStepMode.Instance : GPUInputStepMode.Vertex; | ||||
|  | ||||
| 				} else { | ||||
|  | ||||
| 					arrayStride = geometryAttribute.itemSize * bytesPerElement; | ||||
| 					stepMode = geometryAttribute.isInstancedBufferAttribute ? GPUInputStepMode.Instance : GPUInputStepMode.Vertex; | ||||
|  | ||||
| 				} | ||||
|  | ||||
| 				// patch for INT16 and UINT16 | ||||
| 				if ( geometryAttribute.normalized === false && ( geometryAttribute.array.constructor === Int16Array || geometryAttribute.array.constructor === Uint16Array ) ) { | ||||
|  | ||||
| 					arrayStride = 4; | ||||
|  | ||||
| 				} | ||||
|  | ||||
| 				vertexBufferLayout = { | ||||
| 					arrayStride, | ||||
| 					attributes: [], | ||||
| 					stepMode | ||||
| 				}; | ||||
|  | ||||
| 				vertexBuffers.set( bufferAttribute, vertexBufferLayout ); | ||||
|  | ||||
| 			} | ||||
|  | ||||
| 			const format = this._getVertexFormat( geometryAttribute ); | ||||
| 			const offset = ( geometryAttribute.isInterleavedBufferAttribute === true ) ? geometryAttribute.offset * bytesPerElement : 0; | ||||
|  | ||||
| 			vertexBufferLayout.attributes.push( { | ||||
| 				shaderLocation: slot, | ||||
| 				offset, | ||||
| 				format | ||||
| 			} ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		return Array.from( vertexBuffers.values() ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	destroyAttribute( attribute ) { | ||||
|  | ||||
| 		const backend = this.backend; | ||||
| 		const data = backend.get( this._getBufferAttribute( attribute ) ); | ||||
|  | ||||
| 		data.buffer.destroy(); | ||||
|  | ||||
| 		backend.delete( attribute ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	async getArrayBufferAsync( attribute ) { | ||||
|  | ||||
| 		const backend = this.backend; | ||||
| 		const device = backend.device; | ||||
|  | ||||
| 		const data = backend.get( this._getBufferAttribute( attribute ) ); | ||||
|  | ||||
| 		const bufferGPU = data.buffer; | ||||
| 		const size = bufferGPU.size; | ||||
|  | ||||
| 		let readBufferGPU = data.readBuffer; | ||||
| 		let needsUnmap = true; | ||||
|  | ||||
| 		if ( readBufferGPU === undefined ) { | ||||
|  | ||||
| 			readBufferGPU = device.createBuffer( { | ||||
| 				label: attribute.name, | ||||
| 				size, | ||||
| 				usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ | ||||
| 			} ); | ||||
|  | ||||
| 			needsUnmap = false; | ||||
|  | ||||
| 			data.readBuffer = readBufferGPU; | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		const cmdEncoder = device.createCommandEncoder( {} ); | ||||
|  | ||||
| 		cmdEncoder.copyBufferToBuffer( | ||||
| 			bufferGPU, | ||||
| 			0, | ||||
| 			readBufferGPU, | ||||
| 			0, | ||||
| 			size | ||||
| 		); | ||||
|  | ||||
| 		if ( needsUnmap ) readBufferGPU.unmap(); | ||||
|  | ||||
| 		const gpuCommands = cmdEncoder.finish(); | ||||
| 		device.queue.submit( [ gpuCommands ] ); | ||||
|  | ||||
| 		await readBufferGPU.mapAsync( GPUMapMode.READ ); | ||||
|  | ||||
| 		const arrayBuffer = readBufferGPU.getMappedRange(); | ||||
|  | ||||
| 		return arrayBuffer; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	_getVertexFormat( geometryAttribute ) { | ||||
|  | ||||
| 		const { itemSize, normalized } = geometryAttribute; | ||||
| 		const ArrayType = geometryAttribute.array.constructor; | ||||
| 		const AttributeType = geometryAttribute.constructor; | ||||
|  | ||||
| 		let format; | ||||
|  | ||||
| 		if ( itemSize == 1 ) { | ||||
|  | ||||
| 			format = typeArraysToVertexFormatPrefixForItemSize1.get( ArrayType ); | ||||
|  | ||||
| 		} else { | ||||
|  | ||||
| 			const prefixOptions = typedAttributeToVertexFormatPrefix.get( AttributeType ) || typedArraysToVertexFormatPrefix.get( ArrayType ); | ||||
| 			const prefix = prefixOptions[ normalized ? 1 : 0 ]; | ||||
|  | ||||
| 			if ( prefix ) { | ||||
|  | ||||
| 				const bytesPerUnit = ArrayType.BYTES_PER_ELEMENT * itemSize; | ||||
| 				const paddedBytesPerUnit = Math.floor( ( bytesPerUnit + 3 ) / 4 ) * 4; | ||||
| 				const paddedItemSize = paddedBytesPerUnit / ArrayType.BYTES_PER_ELEMENT; | ||||
|  | ||||
| 				if ( paddedItemSize % 1 ) { | ||||
|  | ||||
| 					throw new Error( 'THREE.WebGPUAttributeUtils: Bad vertex format item size.' ); | ||||
|  | ||||
| 				} | ||||
|  | ||||
| 				format = `${prefix}x${paddedItemSize}`; | ||||
|  | ||||
| 			} | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		if ( ! format ) { | ||||
|  | ||||
| 			console.error( 'THREE.WebGPUAttributeUtils: Vertex format not supported yet.' ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		return format; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	_getBufferAttribute( attribute ) { | ||||
|  | ||||
| 		if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; | ||||
|  | ||||
| 		return attribute; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| export default WebGPUAttributeUtils; | ||||
		Reference in New Issue
	
	Block a user