123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- import { IntType } from 'three';
- let _id = 0;
- class DualAttributeData {
- constructor( attributeData, dualBuffer ) {
- this.buffers = [ attributeData.bufferGPU, dualBuffer ];
- this.type = attributeData.type;
- this.bufferType = attributeData.bufferType;
- this.pbo = attributeData.pbo;
- this.byteLength = attributeData.byteLength;
- this.bytesPerElement = attributeData.BYTES_PER_ELEMENT;
- this.version = attributeData.version;
- this.isInteger = attributeData.isInteger;
- this.activeBufferIndex = 0;
- this.baseId = attributeData.id;
- }
- get id() {
- return `${ this.baseId }|${ this.activeBufferIndex }`;
- }
- get bufferGPU() {
- return this.buffers[ this.activeBufferIndex ];
- }
- get transformBuffer() {
- return this.buffers[ this.activeBufferIndex ^ 1 ];
- }
- switchBuffers() {
- this.activeBufferIndex ^= 1;
- }
- }
- class WebGLAttributeUtils {
- constructor( backend ) {
- this.backend = backend;
- }
- createAttribute( attribute, bufferType ) {
- const backend = this.backend;
- const { gl } = backend;
- const array = attribute.array;
- const usage = attribute.usage || gl.STATIC_DRAW;
- const bufferAttribute = attribute.isInterleavedBufferAttribute ? attribute.data : attribute;
- const bufferData = backend.get( bufferAttribute );
- let bufferGPU = bufferData.bufferGPU;
- if ( bufferGPU === undefined ) {
- bufferGPU = this._createBuffer( gl, bufferType, array, usage );
- bufferData.bufferGPU = bufferGPU;
- bufferData.bufferType = bufferType;
- bufferData.version = bufferAttribute.version;
- }
- //attribute.onUploadCallback();
- let type;
- if ( array instanceof Float32Array ) {
- type = gl.FLOAT;
- } else if ( array instanceof Uint16Array ) {
- if ( attribute.isFloat16BufferAttribute ) {
- type = gl.HALF_FLOAT;
- } else {
- type = gl.UNSIGNED_SHORT;
- }
- } else if ( array instanceof Int16Array ) {
- type = gl.SHORT;
- } else if ( array instanceof Uint32Array ) {
- type = gl.UNSIGNED_INT;
- } else if ( array instanceof Int32Array ) {
- type = gl.INT;
- } else if ( array instanceof Int8Array ) {
- type = gl.BYTE;
- } else if ( array instanceof Uint8Array ) {
- type = gl.UNSIGNED_BYTE;
- } else if ( array instanceof Uint8ClampedArray ) {
- type = gl.UNSIGNED_BYTE;
- } else {
- throw new Error( 'THREE.WebGLBackend: Unsupported buffer data format: ' + array );
- }
- let attributeData = {
- bufferGPU,
- bufferType,
- type,
- byteLength: array.byteLength,
- bytesPerElement: array.BYTES_PER_ELEMENT,
- version: attribute.version,
- pbo: attribute.pbo,
- isInteger: type === gl.INT || type === gl.UNSIGNED_INT || type === gl.UNSIGNED_SHORT || attribute.gpuType === IntType,
- id: _id ++
- };
- if ( attribute.isStorageBufferAttribute || attribute.isStorageInstancedBufferAttribute ) {
- // create buffer for tranform feedback use
- const bufferGPUDual = this._createBuffer( gl, bufferType, array, usage );
- attributeData = new DualAttributeData( attributeData, bufferGPUDual );
- }
- backend.set( attribute, attributeData );
- }
- updateAttribute( attribute ) {
- const backend = this.backend;
- const { gl } = backend;
- const array = attribute.array;
- const bufferAttribute = attribute.isInterleavedBufferAttribute ? attribute.data : attribute;
- const bufferData = backend.get( bufferAttribute );
- const bufferType = bufferData.bufferType;
- const updateRanges = attribute.isInterleavedBufferAttribute ? attribute.data.updateRanges : attribute.updateRanges;
- gl.bindBuffer( bufferType, bufferData.bufferGPU );
- if ( updateRanges.length === 0 ) {
- // Not using update ranges
- gl.bufferSubData( bufferType, 0, array );
- } else {
- for ( let i = 0, l = updateRanges.length; i < l; i ++ ) {
- const range = updateRanges[ i ];
- gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT,
- array, range.start, range.count );
- }
- bufferAttribute.clearUpdateRanges();
- }
- gl.bindBuffer( bufferType, null );
- bufferData.version = bufferAttribute.version;
- }
- destroyAttribute( attribute ) {
- const backend = this.backend;
- const { gl } = backend;
- if ( attribute.isInterleavedBufferAttribute ) {
- backend.delete( attribute.data );
- }
- const attributeData = backend.get( attribute );
- gl.deleteBuffer( attributeData.bufferGPU );
- backend.delete( attribute );
- }
- async getArrayBufferAsync( attribute ) {
- const backend = this.backend;
- const { gl } = backend;
- const bufferAttribute = attribute.isInterleavedBufferAttribute ? attribute.data : attribute;
- const { bufferGPU } = backend.get( bufferAttribute );
- const array = attribute.array;
- const byteLength = array.byteLength;
- gl.bindBuffer( gl.COPY_READ_BUFFER, bufferGPU );
- const writeBuffer = gl.createBuffer();
- gl.bindBuffer( gl.COPY_WRITE_BUFFER, writeBuffer );
- gl.bufferData( gl.COPY_WRITE_BUFFER, byteLength, gl.STREAM_READ );
- gl.copyBufferSubData( gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, byteLength );
- await backend.utils._clientWaitAsync();
- const dstBuffer = new attribute.array.constructor( array.length );
- gl.getBufferSubData( gl.COPY_WRITE_BUFFER, 0, dstBuffer );
- gl.deleteBuffer( writeBuffer );
- return dstBuffer.buffer;
- }
- _createBuffer( gl, bufferType, array, usage ) {
- const bufferGPU = gl.createBuffer();
- gl.bindBuffer( bufferType, bufferGPU );
- gl.bufferData( bufferType, array, usage );
- gl.bindBuffer( bufferType, null );
- return bufferGPU;
- }
- }
- export default WebGLAttributeUtils;
|