babylon.buffer.ts 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. module BABYLON {
  2. /**
  3. * Class used to store data that will be store in GPU memory
  4. */
  5. export class Buffer {
  6. private _engine: Engine;
  7. private _buffer: Nullable<WebGLBuffer>;
  8. /** @hidden */
  9. public _data: Nullable<DataArray>;
  10. private _updatable: boolean;
  11. private _instanced: boolean;
  12. /**
  13. * Gets the byte stride.
  14. */
  15. public readonly byteStride: number;
  16. /**
  17. * Constructor
  18. * @param engine the engine
  19. * @param data the data to use for this buffer
  20. * @param updatable whether the data is updatable
  21. * @param stride the stride (optional)
  22. * @param postponeInternalCreation whether to postpone creating the internal WebGL buffer (optional)
  23. * @param instanced whether the buffer is instanced (optional)
  24. * @param useBytes set to true if the stride in in bytes (optional)
  25. */
  26. constructor(engine: any, data: DataArray, updatable: boolean, stride = 0, postponeInternalCreation = false, instanced = false, useBytes = false) {
  27. if (engine instanceof Mesh) { // old versions of BABYLON.VertexBuffer accepted 'mesh' instead of 'engine'
  28. this._engine = engine.getScene().getEngine();
  29. }
  30. else {
  31. this._engine = engine;
  32. }
  33. this._updatable = updatable;
  34. this._instanced = instanced;
  35. this._data = data;
  36. this.byteStride = useBytes ? stride : stride * Float32Array.BYTES_PER_ELEMENT;
  37. if (!postponeInternalCreation) { // by default
  38. this.create();
  39. }
  40. }
  41. /**
  42. * Create a new {BABYLON.VertexBuffer} based on the current buffer
  43. * @param kind defines the vertex buffer kind (position, normal, etc.)
  44. * @param offset defines offset in the buffer (0 by default)
  45. * @param size defines the size in floats of attributes (position is 3 for instance)
  46. * @param stride defines the stride size in floats in the buffer (the offset to apply to reach next value when data is interleaved)
  47. * @param instanced defines if the vertex buffer contains indexed data
  48. * @param useBytes defines if the offset and stride are in bytes
  49. * @returns the new vertex buffer
  50. */
  51. public createVertexBuffer(kind: string, offset: number, size: number, stride?: number, instanced?: boolean, useBytes = false): VertexBuffer {
  52. const byteOffset = useBytes ? offset : offset * Float32Array.BYTES_PER_ELEMENT;
  53. const byteStride = stride ? (useBytes ? stride : stride * Float32Array.BYTES_PER_ELEMENT) : this.byteStride;
  54. // a lot of these parameters are ignored as they are overriden by the buffer
  55. return new VertexBuffer(this._engine, this, kind, this._updatable, true, byteStride, instanced === undefined ? this._instanced : instanced, byteOffset, size, undefined, undefined, true);
  56. }
  57. // Properties
  58. /**
  59. * Gets a boolean indicating if the Buffer is updatable?
  60. * @returns true if the buffer is updatable
  61. */
  62. public isUpdatable(): boolean {
  63. return this._updatable;
  64. }
  65. /**
  66. * Gets current buffer's data
  67. * @returns a DataArray or null
  68. */
  69. public getData(): Nullable<DataArray> {
  70. return this._data;
  71. }
  72. /**
  73. * Gets underlying native buffer
  74. * @returns underlying native buffer
  75. */
  76. public getBuffer(): Nullable<WebGLBuffer> {
  77. return this._buffer;
  78. }
  79. /**
  80. * Gets the stride in float32 units (i.e. byte stride / 4).
  81. * May not be an integer if the byte stride is not divisible by 4.
  82. * DEPRECATED. Use byteStride instead.
  83. * @returns the stride in float32 units
  84. */
  85. public getStrideSize(): number {
  86. return this.byteStride / Float32Array.BYTES_PER_ELEMENT;
  87. }
  88. // Methods
  89. /**
  90. * Store data into the buffer. If the buffer was already used it will be either recreated or updated depending on isUpdatable property
  91. * @param data defines the data to store
  92. */
  93. public create(data: Nullable<DataArray> = null): void {
  94. if (!data && this._buffer) {
  95. return; // nothing to do
  96. }
  97. data = data || this._data;
  98. if (!data) {
  99. return;
  100. }
  101. if (!this._buffer) { // create buffer
  102. if (this._updatable) {
  103. this._buffer = this._engine.createDynamicVertexBuffer(data);
  104. this._data = data;
  105. } else {
  106. this._buffer = this._engine.createVertexBuffer(data);
  107. }
  108. } else if (this._updatable) { // update buffer
  109. this._engine.updateDynamicVertexBuffer(this._buffer, data);
  110. this._data = data;
  111. }
  112. }
  113. /** @hidden */
  114. public _rebuild(): void {
  115. this._buffer = null;
  116. this.create(this._data);
  117. }
  118. /**
  119. * Update current buffer data
  120. * @param data defines the data to store
  121. */
  122. public update(data: DataArray): void {
  123. this.create(data);
  124. }
  125. /**
  126. * Updates the data directly.
  127. * @param data the new data
  128. * @param offset the new offset
  129. * @param vertexCount the vertex count (optional)
  130. * @param useBytes set to true if the offset is in bytes
  131. */
  132. public updateDirectly(data: DataArray, offset: number, vertexCount?: number, useBytes: boolean = false): void {
  133. if (!this._buffer) {
  134. return;
  135. }
  136. if (this._updatable) { // update buffer
  137. this._engine.updateDynamicVertexBuffer(this._buffer, data, useBytes ? offset : offset * Float32Array.BYTES_PER_ELEMENT, (vertexCount ? vertexCount * this.byteStride : undefined));
  138. this._data = null;
  139. }
  140. }
  141. /**
  142. * Release all resources
  143. */
  144. public dispose(): void {
  145. if (!this._buffer) {
  146. return;
  147. }
  148. if (this._engine._releaseBuffer(this._buffer)) {
  149. this._buffer = null;
  150. }
  151. }
  152. }
  153. }