WebGLAttributes.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. function WebGLAttributes( gl, capabilities ) {
  2. const isWebGL2 = capabilities.isWebGL2;
  3. const buffers = new WeakMap();
  4. function createBuffer( attribute, bufferType ) {
  5. const array = attribute.array;
  6. const usage = attribute.usage;
  7. const size = array.byteLength;
  8. const buffer = gl.createBuffer();
  9. gl.bindBuffer( bufferType, buffer );
  10. gl.bufferData( bufferType, array, usage );
  11. attribute.onUploadCallback();
  12. let type;
  13. if ( array instanceof Float32Array ) {
  14. type = gl.FLOAT;
  15. } else if ( array instanceof Uint16Array ) {
  16. if ( attribute.isFloat16BufferAttribute ) {
  17. if ( isWebGL2 ) {
  18. type = gl.HALF_FLOAT;
  19. } else {
  20. throw new Error( 'THREE.WebGLAttributes: Usage of Float16BufferAttribute requires WebGL2.' );
  21. }
  22. } else {
  23. type = gl.UNSIGNED_SHORT;
  24. }
  25. } else if ( array instanceof Int16Array ) {
  26. type = gl.SHORT;
  27. } else if ( array instanceof Uint32Array ) {
  28. type = gl.UNSIGNED_INT;
  29. } else if ( array instanceof Int32Array ) {
  30. type = gl.INT;
  31. } else if ( array instanceof Int8Array ) {
  32. type = gl.BYTE;
  33. } else if ( array instanceof Uint8Array ) {
  34. type = gl.UNSIGNED_BYTE;
  35. } else if ( array instanceof Uint8ClampedArray ) {
  36. type = gl.UNSIGNED_BYTE;
  37. } else {
  38. throw new Error( 'THREE.WebGLAttributes: Unsupported buffer data format: ' + array );
  39. }
  40. return {
  41. buffer: buffer,
  42. type: type,
  43. bytesPerElement: array.BYTES_PER_ELEMENT,
  44. version: attribute.version,
  45. size: size
  46. };
  47. }
  48. function updateBuffer( buffer, attribute, bufferType ) {
  49. const array = attribute.array;
  50. const updateRange = attribute._updateRange; // @deprecated, r159
  51. const updateRanges = attribute.updateRanges;
  52. gl.bindBuffer( bufferType, buffer );
  53. if ( updateRange.count === - 1 && updateRanges.length === 0 ) {
  54. // Not using update ranges
  55. gl.bufferSubData( bufferType, 0, array );
  56. }
  57. if ( updateRanges.length !== 0 ) {
  58. for ( let i = 0, l = updateRanges.length; i < l; i ++ ) {
  59. const range = updateRanges[ i ];
  60. if ( isWebGL2 ) {
  61. gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT,
  62. array, range.start, range.count );
  63. } else {
  64. gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT,
  65. array.subarray( range.start, range.start + range.count ) );
  66. }
  67. }
  68. attribute.clearUpdateRanges();
  69. }
  70. // @deprecated, r159
  71. if ( updateRange.count !== - 1 ) {
  72. if ( isWebGL2 ) {
  73. gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
  74. array, updateRange.offset, updateRange.count );
  75. } else {
  76. gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
  77. array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );
  78. }
  79. updateRange.count = - 1; // reset range
  80. }
  81. attribute.onUploadCallback();
  82. }
  83. //
  84. function get( attribute ) {
  85. if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
  86. return buffers.get( attribute );
  87. }
  88. function remove( attribute ) {
  89. if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
  90. const data = buffers.get( attribute );
  91. if ( data ) {
  92. gl.deleteBuffer( data.buffer );
  93. buffers.delete( attribute );
  94. }
  95. }
  96. function update( attribute, bufferType ) {
  97. if ( attribute.isGLBufferAttribute ) {
  98. const cached = buffers.get( attribute );
  99. if ( ! cached || cached.version < attribute.version ) {
  100. buffers.set( attribute, {
  101. buffer: attribute.buffer,
  102. type: attribute.type,
  103. bytesPerElement: attribute.elementSize,
  104. version: attribute.version
  105. } );
  106. }
  107. return;
  108. }
  109. if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
  110. const data = buffers.get( attribute );
  111. if ( data === undefined ) {
  112. buffers.set( attribute, createBuffer( attribute, bufferType ) );
  113. } else if ( data.version < attribute.version ) {
  114. if ( data.size !== attribute.array.byteLength ) {
  115. throw new Error( 'THREE.WebGLAttributes: The size of the buffer attribute\'s array buffer does not match the original size. Resizing buffer attributes is not supported.' );
  116. }
  117. updateBuffer( data.buffer, attribute, bufferType );
  118. data.version = attribute.version;
  119. }
  120. }
  121. return {
  122. get: get,
  123. remove: remove,
  124. update: update
  125. };
  126. }
  127. export { WebGLAttributes };