WebGLAttributeUtils.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. import { IntType } from 'three';
  2. class WebGLAttributeUtils {
  3. constructor( backend ) {
  4. this.backend = backend;
  5. }
  6. createAttribute( attribute, bufferType ) {
  7. const backend = this.backend;
  8. const { gl } = backend;
  9. const array = attribute.array;
  10. const usage = attribute.usage || gl.STATIC_DRAW;
  11. const bufferAttribute = attribute.isInterleavedBufferAttribute ? attribute.data : attribute;
  12. const bufferData = backend.get( bufferAttribute );
  13. let bufferGPU = bufferData.bufferGPU;
  14. if ( bufferGPU === undefined ) {
  15. bufferGPU = gl.createBuffer();
  16. gl.bindBuffer( bufferType, bufferGPU );
  17. gl.bufferData( bufferType, array, usage );
  18. gl.bindBuffer( bufferType, null );
  19. bufferData.bufferGPU = bufferGPU;
  20. bufferData.bufferType = bufferType;
  21. bufferData.version = bufferAttribute.version;
  22. }
  23. //attribute.onUploadCallback();
  24. let type;
  25. if ( array instanceof Float32Array ) {
  26. type = gl.FLOAT;
  27. } else if ( array instanceof Uint16Array ) {
  28. if ( attribute.isFloat16BufferAttribute ) {
  29. type = gl.HALF_FLOAT;
  30. } else {
  31. type = gl.UNSIGNED_SHORT;
  32. }
  33. } else if ( array instanceof Int16Array ) {
  34. type = gl.SHORT;
  35. } else if ( array instanceof Uint32Array ) {
  36. type = gl.UNSIGNED_INT;
  37. } else if ( array instanceof Int32Array ) {
  38. type = gl.INT;
  39. } else if ( array instanceof Int8Array ) {
  40. type = gl.BYTE;
  41. } else if ( array instanceof Uint8Array ) {
  42. type = gl.UNSIGNED_BYTE;
  43. } else if ( array instanceof Uint8ClampedArray ) {
  44. type = gl.UNSIGNED_BYTE;
  45. } else {
  46. throw new Error( 'THREE.WebGLBackend: Unsupported buffer data format: ' + array );
  47. }
  48. backend.set( attribute, {
  49. bufferGPU,
  50. type,
  51. bytesPerElement: array.BYTES_PER_ELEMENT,
  52. version: attribute.version,
  53. isInteger: type === gl.INT || type === gl.UNSIGNED_INT || attribute.gpuType === IntType
  54. } );
  55. }
  56. updateAttribute( attribute ) {
  57. const backend = this.backend;
  58. const { gl } = backend;
  59. const array = attribute.array;
  60. const bufferAttribute = attribute.isInterleavedBufferAttribute ? attribute.data : attribute;
  61. const bufferData = backend.get( bufferAttribute );
  62. const bufferType = bufferData.bufferType;
  63. const updateRanges = attribute.isInterleavedBufferAttribute ? attribute.data.updateRanges : attribute.updateRanges;
  64. gl.bindBuffer( bufferType, bufferData.bufferGPU );
  65. if ( updateRanges.length === 0 ) {
  66. // Not using update ranges
  67. gl.bufferSubData( bufferType, 0, array );
  68. } else {
  69. for ( let i = 0, l = updateRanges.length; i < l; i ++ ) {
  70. const range = updateRanges[ i ];
  71. gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT,
  72. array, range.start, range.count );
  73. }
  74. bufferAttribute.clearUpdateRanges();
  75. }
  76. gl.bindBuffer( bufferType, null );
  77. bufferData.version = bufferAttribute.version;
  78. }
  79. async getArrayBufferAsync( attribute ) {
  80. const backend = this.backend;
  81. const { gl } = backend;
  82. const bufferAttribute = attribute.isInterleavedBufferAttribute ? attribute.data : attribute;
  83. const { bufferGPU } = backend.get( bufferAttribute );
  84. const array = attribute.array;
  85. const byteLength = array.byteLength;
  86. gl.bindBuffer( gl.COPY_READ_BUFFER, bufferGPU );
  87. const writeBuffer = gl.createBuffer();
  88. gl.bindBuffer( gl.COPY_WRITE_BUFFER, writeBuffer );
  89. gl.bufferData( gl.COPY_WRITE_BUFFER, byteLength, gl.STREAM_READ );
  90. gl.copyBufferSubData( gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, byteLength );
  91. await backend.utils._clientWaitAsync();
  92. const dstBuffer = new attribute.array.constructor( array.length );
  93. gl.getBufferSubData( gl.COPY_WRITE_BUFFER, 0, dstBuffer );
  94. gl.deleteBuffer( writeBuffer );
  95. return dstBuffer.buffer;
  96. }
  97. }
  98. export default WebGLAttributeUtils;