- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334
- 335
- 336
- 337
- 338
- 339
- 340
- 341
- 342
- 343
- 344
- 345
- 346
- 347
- 348
- 349
- 350
- 351
- 352
- 353
- 354
- 355
- 356
- 357
- 358
- 359
- 360
- 361
- 362
- 363
- 364
- 365
- 366
- 367
- 368
- 369
- 370
- 371
- 372
- 373
- 374
- 375
- 376
- 377
- 378
- 379
- 380
- 381
- 382
- 383
- 384
- 385
- 386
- 387
- 388
- 389
- 390
- 391
- 392
- 393
- 394
- 395
- 396
- 397
- 398
- 399
- 400
- 401
- 402
- 403
- 404
- 405
- 406
- 407
- 408
- 409
- 410
- 411
- 412
- 413
- 414
- 415
- 416
- 417
- 418
- 419
- 420
- 421
- 422
- 423
- 424
- 425
- 426
- 427
- 428
- 429
- 430
- 431
- 432
- 433
- 434
- 435
- 436
- 437
- 438
- 439
- 440
- 441
- 442
- 443
- 444
- 445
- 446
- 447
- 448
- 449
- 450
- 451
- 452
- 453
- 454
- 455
- 456
- 457
- 458
- 459
- 460
- 461
- 462
- 463
- 464
- 465
- 466
- 467
- 468
- 469
- 470
- 471
- 472
- 473
- 474
- 475
- 476
- 477
- 478
- 479
- 480
- 481
- 482
- 483
- 484
- 485
- 486
- 487
- 488
- 489
- 490
- 491
- 492
- 493
- 494
- 495
- 496
- 497
- 498
- 499
- 500
- 501
- 502
- 503
- 504
- 505
- 506
- 507
- 508
- 509
- 510
- 511
- 512
- 513
- 514
- 515
- 516
- 517
- 518
- 519
- 520
- 521
- 522
- 523
- 524
- 525
- 526
- 527
- 528
- 529
- 530
- 531
- 532
- 533
- 534
- 535
- 536
- 537
- 538
- 539
- 540
- 541
- 542
- 543
- 544
- 545
- 546
- 547
- 548
- 549
- 550
- 551
- 552
- 553
- 554
- 555
- 556
- 557
- 558
- 559
- 560
- 561
- 562
- 563
- 564
- 565
- 566
- 567
- 568
- 569
- 570
- 571
- 572
- 573
- 574
- 575
- 576
- 577
- 578
- 579
- 580
- 581
- 582
- 583
- 584
- 585
- 586
- 587
- 588
- 589
- 590
- 591
- 592
- 593
- 594
- 595
- 596
- 597
- 598
- 599
- 600
- 601
- 602
- 603
- 604
- 605
- 606
- 607
- 608
- 609
- 610
- 611
- 612
- 613
- 614
- 615
- 616
- 617
- 618
- 619
- 620
- 621
- 622
- 623
- 624
- 625
- 626
- 627
- 628
- 629
- 630
- 631
- 632
- 633
- 634
- 635
- 636
- 637
- 638
- 639
- 640
- 641
- 642
- 643
- 644
- 645
- 646
- 647
- 648
- 649
- 650
- 651
- 652
- 653
- 654
- 655
- 656
- 657
- 658
- 659
- 660
- 661
- 662
- 663
- 664
- 665
- 666
- 667
- 668
- 669
- 670
- 671
- 672
- 673
- 674
- 675
- 676
- 677
- 678
- 679
- 680
- 681
- 682
- 683
- 684
- 685
- 686
- 687
- 688
- 689
- 690
- 691
- 692
- 693
- 694
- 695
- 696
- 697
- 698
- 699
- 700
- 701
- 702
- 703
- 704
- 705
- 706
- 707
- 708
- 709
- 710
- 711
- 712
- 713
- 714
- 715
- 716
- 717
- 718
- 719
- 720
import { BatchDrawCall } from './BatchDrawCall';
import { BatchTextureArray } from './BatchTextureArray';
import { BaseTexture } from '../textures/BaseTexture';
import { ObjectRenderer } from './ObjectRenderer';
import { State } from '../state/State';
import { ViewableBuffer } from '../geometry/ViewableBuffer';
import { checkMaxIfStatementsInShader } from '../shader/utils/checkMaxIfStatementsInShader';
import { settings } from '@pixi/settings';
import { premultiplyBlendMode, premultiplyTint, nextPow2, log2 } from '@pixi/utils';
import { ENV } from '@pixi/constants';
import type { Renderer } from '../Renderer';
import type { Shader } from '../shader/Shader';
import type { BatchShaderGenerator } from './BatchShaderGenerator';
import type { BatchGeometry } from './BatchGeometry';
import type { Texture } from '../textures/Texture';
import type { BLEND_MODES } from '@pixi/constants';
/**
* Interface for elements like Sprite, Mesh etc. for batching.
* @memberof PIXI
*/
export interface IBatchableElement
{
_texture: Texture;
vertexData: Float32Array;
indices: Uint16Array | Uint32Array | Array<number>;
uvs: Float32Array;
worldAlpha: number;
_tintRGB: number;
blendMode: BLEND_MODES;
}
/**
* Renderer dedicated to drawing and batching sprites.
*
* This is the default batch renderer. It buffers objects
* with texture-based geometries and renders them in
* batches. It uploads multiple textures to the GPU to
* reduce to the number of draw calls.
* @memberof PIXI
*/
export class AbstractBatchRenderer extends ObjectRenderer
{
/** The WebGL state in which this renderer will work. */
public readonly state: State;
/**
* The number of bufferable objects before a flush
* occurs automatically.
* @default settings.SPRITE_BATCH_SIZE * 4
*/
public size: number;
/**
* Maximum number of textures that can be uploaded to
* the GPU under the current context. It is initialized
* properly in `this.contextChange`.
* @see PIXI.AbstractBatchRenderer#contextChange
* @readonly
*/
public MAX_TEXTURES: number;
/**
* This is used to generate a shader that can
* color each vertex based on a `aTextureId`
* attribute that points to an texture in `uSampler`.
*
* This enables the objects with different textures
* to be drawn in the same draw call.
*
* You can customize your shader by creating your
* custom shader generator.
*/
protected shaderGenerator: BatchShaderGenerator;
/**
* The class that represents the geometry of objects
* that are going to be batched with this.
* @member {object}
* @default PIXI.BatchGeometry
*/
protected geometryClass: typeof BatchGeometry;
/**
* Size of data being buffered per vertex in the
* attribute buffers (in floats). By default, the
* batch-renderer plugin uses 6:
*
* | aVertexPosition | 2 |
* |-----------------|---|
* | aTextureCoords | 2 |
* | aColor | 1 |
* | aTextureId | 1 |
* @readonly
*/
protected vertexSize: number;
/** Total count of all vertices used by the currently buffered objects. */
protected _vertexCount: number;
/** Total count of all indices used by the currently buffered objects. */
protected _indexCount: number;
/**
* Buffer of objects that are yet to be rendered.
* @member {PIXI.DisplayObject[]}
*/
protected _bufferedElements: Array<IBatchableElement>;
/**
* Data for texture batch builder, helps to save a bit of CPU on a pass.
* @member {PIXI.BaseTexture[]}
*/
protected _bufferedTextures: Array<BaseTexture>;
/** Number of elements that are buffered and are waiting to be flushed. */
protected _bufferSize: number;
/**
* This shader is generated by `this.shaderGenerator`.
*
* It is generated specifically to handle the required
* number of textures being batched together.
*/
protected _shader: Shader;
/**
* A flush may occur multiple times in a single
* frame. On iOS devices or when
* `settings.CAN_UPLOAD_SAME_BUFFER` is false, the
* batch renderer does not upload data to the same
* `WebGLBuffer` for performance reasons.
*
* This is the index into `packedGeometries` that points to
* geometry holding the most recent buffers.
*/
protected _flushId: number;
/**
* Pool of `ViewableBuffer` objects that are sorted in
* order of increasing size. The flush method uses
* the buffer with the least size above the amount
* it requires. These are used for passing attributes.
*
* The first buffer has a size of 8; each subsequent
* buffer has double capacity of its previous.
* @member {PIXI.ViewableBuffer[]}
* @see PIXI.AbstractBatchRenderer#getAttributeBuffer
*/
protected _aBuffers: Array<ViewableBuffer>;
/**
* Pool of `Uint16Array` objects that are sorted in
* order of increasing size. The flush method uses
* the buffer with the least size above the amount
* it requires. These are used for passing indices.
*
* The first buffer has a size of 12; each subsequent
* buffer has double capacity of its previous.
* @member {Uint16Array[]}
* @see PIXI.AbstractBatchRenderer#getIndexBuffer
*/
protected _iBuffers: Array<Uint16Array>;
protected _dcIndex: number;
protected _aIndex: number;
protected _iIndex: number;
protected _attributeBuffer: ViewableBuffer;
protected _indexBuffer: Uint16Array;
protected _tempBoundTextures: BaseTexture[];
/**
* Pool of `this.geometryClass` geometry objects
* that store buffers. They are used to pass data
* to the shader on each draw call.
*
* These are never re-allocated again, unless a
* context change occurs; however, the pool may
* be expanded if required.
* @member {PIXI.Geometry[]}
* @see PIXI.AbstractBatchRenderer.contextChange
*/
private _packedGeometries: Array<BatchGeometry>;
/**
* Size of `this._packedGeometries`. It can be expanded
* if more than `this._packedGeometryPoolSize` flushes
* occur in a single frame.
*/
private _packedGeometryPoolSize: number;
/**
* This will hook onto the renderer's `contextChange`
* and `prerender` signals.
* @param {PIXI.Renderer} renderer - The renderer this works for.
*/
constructor(renderer: Renderer)
{
super(renderer);
this.shaderGenerator = null;
this.geometryClass = null;
this.vertexSize = null;
this.state = State.for2d();
this.size = settings.SPRITE_BATCH_SIZE * 4;
this._vertexCount = 0;
this._indexCount = 0;
this._bufferedElements = [];
this._bufferedTextures = [];
this._bufferSize = 0;
this._shader = null;
this._packedGeometries = [];
this._packedGeometryPoolSize = 2;
this._flushId = 0;
this._aBuffers = {} as any;
this._iBuffers = {} as any;
this.MAX_TEXTURES = 1;
this.renderer.on('prerender', this.onPrerender, this);
renderer.runners.contextChange.add(this);
this._dcIndex = 0;
this._aIndex = 0;
this._iIndex = 0;
this._attributeBuffer = null;
this._indexBuffer = null;
this._tempBoundTextures = [];
}
/**
* Handles the `contextChange` signal.
*
* It calculates `this.MAX_TEXTURES` and allocating the packed-geometry object pool.
*/
contextChange(): void
{
const gl = this.renderer.gl;
if (settings.PREFER_ENV === ENV.WEBGL_LEGACY)
{
this.MAX_TEXTURES = 1;
}
else
{
// step 1: first check max textures the GPU can handle.
this.MAX_TEXTURES = Math.min(
gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS),
settings.SPRITE_MAX_TEXTURES);
// step 2: check the maximum number of if statements the shader can have too..
this.MAX_TEXTURES = checkMaxIfStatementsInShader(
this.MAX_TEXTURES, gl);
}
this._shader = this.shaderGenerator.generateShader(this.MAX_TEXTURES);
// we use the second shader as the first one depending on your browser
// may omit aTextureId as it is not used by the shader so is optimized out.
for (let i = 0; i < this._packedGeometryPoolSize; i++)
{
/* eslint-disable max-len */
this._packedGeometries[i] = new (this.geometryClass)();
}
this.initFlushBuffers();
}
/** Makes sure that static and dynamic flush pooled objects have correct dimensions. */
initFlushBuffers(): void
{
const {
_drawCallPool,
_textureArrayPool,
} = AbstractBatchRenderer;
// max draw calls
const MAX_SPRITES = this.size / 4;
// max texture arrays
const MAX_TA = Math.floor(MAX_SPRITES / this.MAX_TEXTURES) + 1;
while (_drawCallPool.length < MAX_SPRITES)
{
_drawCallPool.push(new BatchDrawCall());
}
while (_textureArrayPool.length < MAX_TA)
{
_textureArrayPool.push(new BatchTextureArray());
}
for (let i = 0; i < this.MAX_TEXTURES; i++)
{
this._tempBoundTextures[i] = null;
}
}
/** Handles the `prerender` signal. It ensures that flushes start from the first geometry object again. */
onPrerender(): void
{
this._flushId = 0;
}
/**
* Buffers the "batchable" object. It need not be rendered immediately.
* @param {PIXI.DisplayObject} element - the element to render when
* using this renderer
*/
render(element: IBatchableElement): void
{
if (!element._texture.valid)
{
return;
}
if (this._vertexCount + (element.vertexData.length / 2) > this.size)
{
this.flush();
}
this._vertexCount += element.vertexData.length / 2;
this._indexCount += element.indices.length;
this._bufferedTextures[this._bufferSize] = element._texture.baseTexture;
this._bufferedElements[this._bufferSize++] = element;
}
buildTexturesAndDrawCalls(): void
{
const {
_bufferedTextures: textures,
MAX_TEXTURES,
} = this;
const textureArrays = AbstractBatchRenderer._textureArrayPool;
const batch = this.renderer.batch;
const boundTextures = this._tempBoundTextures;
const touch = this.renderer.textureGC.count;
let TICK = ++BaseTexture._globalBatch;
let countTexArrays = 0;
let texArray = textureArrays[0];
let start = 0;
batch.copyBoundTextures(boundTextures, MAX_TEXTURES);
for (let i = 0; i < this._bufferSize; ++i)
{
const tex = textures[i];
textures[i] = null;
if (tex._batchEnabled === TICK)
{
continue;
}
if (texArray.count >= MAX_TEXTURES)
{
batch.boundArray(texArray, boundTextures, TICK, MAX_TEXTURES);
this.buildDrawCalls(texArray, start, i);
start = i;
texArray = textureArrays[++countTexArrays];
++TICK;
}
tex._batchEnabled = TICK;
tex.touched = touch;
texArray.elements[texArray.count++] = tex;
}
if (texArray.count > 0)
{
batch.boundArray(texArray, boundTextures, TICK, MAX_TEXTURES);
this.buildDrawCalls(texArray, start, this._bufferSize);
++countTexArrays;
++TICK;
}
// Clean-up
for (let i = 0; i < boundTextures.length; i++)
{
boundTextures[i] = null;
}
BaseTexture._globalBatch = TICK;
}
/**
* Populating drawcalls for rendering
* @param texArray
* @param start
* @param finish
*/
buildDrawCalls(texArray: BatchTextureArray, start: number, finish: number): void
{
const {
_bufferedElements: elements,
_attributeBuffer,
_indexBuffer,
vertexSize,
} = this;
const drawCalls = AbstractBatchRenderer._drawCallPool;
let dcIndex = this._dcIndex;
let aIndex = this._aIndex;
let iIndex = this._iIndex;
let drawCall = drawCalls[dcIndex];
drawCall.start = this._iIndex;
drawCall.texArray = texArray;
for (let i = start; i < finish; ++i)
{
const sprite = elements[i];
const tex = sprite._texture.baseTexture;
const spriteBlendMode = premultiplyBlendMode[
tex.alphaMode ? 1 : 0][sprite.blendMode];
elements[i] = null;
if (start < i && drawCall.blend !== spriteBlendMode)
{
drawCall.size = iIndex - drawCall.start;
start = i;
drawCall = drawCalls[++dcIndex];
drawCall.texArray = texArray;
drawCall.start = iIndex;
}
this.packInterleavedGeometry(sprite, _attributeBuffer, _indexBuffer, aIndex, iIndex);
aIndex += sprite.vertexData.length / 2 * vertexSize;
iIndex += sprite.indices.length;
drawCall.blend = spriteBlendMode;
}
if (start < finish)
{
drawCall.size = iIndex - drawCall.start;
++dcIndex;
}
this._dcIndex = dcIndex;
this._aIndex = aIndex;
this._iIndex = iIndex;
}
/**
* Bind textures for current rendering
* @param texArray
*/
bindAndClearTexArray(texArray: BatchTextureArray): void
{
const textureSystem = this.renderer.texture;
for (let j = 0; j < texArray.count; j++)
{
textureSystem.bind(texArray.elements[j], texArray.ids[j]);
texArray.elements[j] = null;
}
texArray.count = 0;
}
updateGeometry(): void
{
const {
_packedGeometries: packedGeometries,
_attributeBuffer: attributeBuffer,
_indexBuffer: indexBuffer,
} = this;
if (!settings.CAN_UPLOAD_SAME_BUFFER)
{ /* Usually on iOS devices, where the browser doesn't
like uploads to the same buffer in a single frame. */
if (this._packedGeometryPoolSize <= this._flushId)
{
this._packedGeometryPoolSize++;
packedGeometries[this._flushId] = new (this.geometryClass)();
}
packedGeometries[this._flushId]._buffer.update(attributeBuffer.rawBinaryData);
packedGeometries[this._flushId]._indexBuffer.update(indexBuffer);
this.renderer.geometry.bind(packedGeometries[this._flushId]);
this.renderer.geometry.updateBuffers();
this._flushId++;
}
else
{
// lets use the faster option, always use buffer number 0
packedGeometries[this._flushId]._buffer.update(attributeBuffer.rawBinaryData);
packedGeometries[this._flushId]._indexBuffer.update(indexBuffer);
this.renderer.geometry.updateBuffers();
}
}
drawBatches(): void
{
const dcCount = this._dcIndex;
const { gl, state: stateSystem } = this.renderer;
const drawCalls = AbstractBatchRenderer._drawCallPool;
let curTexArray = null;
// Upload textures and do the draw calls
for (let i = 0; i < dcCount; i++)
{
const { texArray, type, size, start, blend } = drawCalls[i];
if (curTexArray !== texArray)
{
curTexArray = texArray;
this.bindAndClearTexArray(texArray);
}
this.state.blendMode = blend;
stateSystem.set(this.state);
gl.drawElements(type, size, gl.UNSIGNED_SHORT, start * 2);
}
}
/** Renders the content _now_ and empties the current batch. */
flush(): void
{
if (this._vertexCount === 0)
{
return;
}
this._attributeBuffer = this.getAttributeBuffer(this._vertexCount);
this._indexBuffer = this.getIndexBuffer(this._indexCount);
this._aIndex = 0;
this._iIndex = 0;
this._dcIndex = 0;
this.buildTexturesAndDrawCalls();
this.updateGeometry();
this.drawBatches();
// reset elements buffer for the next flush
this._bufferSize = 0;
this._vertexCount = 0;
this._indexCount = 0;
}
/** Starts a new sprite batch. */
start(): void
{
this.renderer.state.set(this.state);
this.renderer.texture.ensureSamplerType(this.MAX_TEXTURES);
this.renderer.shader.bind(this._shader);
if (settings.CAN_UPLOAD_SAME_BUFFER)
{
// bind buffer #0, we don't need others
this.renderer.geometry.bind(this._packedGeometries[this._flushId]);
}
}
/** Stops and flushes the current batch. */
stop(): void
{
this.flush();
}
/** Destroys this `AbstractBatchRenderer`. It cannot be used again. */
destroy(): void
{
for (let i = 0; i < this._packedGeometryPoolSize; i++)
{
if (this._packedGeometries[i])
{
this._packedGeometries[i].destroy();
}
}
this.renderer.off('prerender', this.onPrerender, this);
this._aBuffers = null;
this._iBuffers = null;
this._packedGeometries = null;
this._attributeBuffer = null;
this._indexBuffer = null;
if (this._shader)
{
this._shader.destroy();
this._shader = null;
}
super.destroy();
}
/**
* Fetches an attribute buffer from `this._aBuffers` that can hold atleast `size` floats.
* @param size - minimum capacity required
* @returns - buffer than can hold atleast `size` floats
*/
getAttributeBuffer(size: number): ViewableBuffer
{
// 8 vertices is enough for 2 quads
const roundedP2 = nextPow2(Math.ceil(size / 8));
const roundedSizeIndex = log2(roundedP2);
const roundedSize = roundedP2 * 8;
if (this._aBuffers.length <= roundedSizeIndex)
{
this._iBuffers.length = roundedSizeIndex + 1;
}
let buffer = this._aBuffers[roundedSize];
if (!buffer)
{
this._aBuffers[roundedSize] = buffer = new ViewableBuffer(roundedSize * this.vertexSize * 4);
}
return buffer;
}
/**
* Fetches an index buffer from `this._iBuffers` that can
* have at least `size` capacity.
* @param size - minimum required capacity
* @returns - buffer that can fit `size` indices.
*/
getIndexBuffer(size: number): Uint16Array
{
// 12 indices is enough for 2 quads
const roundedP2 = nextPow2(Math.ceil(size / 12));
const roundedSizeIndex = log2(roundedP2);
const roundedSize = roundedP2 * 12;
if (this._iBuffers.length <= roundedSizeIndex)
{
this._iBuffers.length = roundedSizeIndex + 1;
}
let buffer = this._iBuffers[roundedSizeIndex];
if (!buffer)
{
this._iBuffers[roundedSizeIndex] = buffer = new Uint16Array(roundedSize);
}
return buffer;
}
/**
* Takes the four batching parameters of `element`, interleaves
* and pushes them into the batching attribute/index buffers given.
*
* It uses these properties: `vertexData` `uvs`, `textureId` and
* `indicies`. It also uses the "tint" of the base-texture, if
* present.
* @param {PIXI.DisplayObject} element - element being rendered
* @param attributeBuffer - attribute buffer.
* @param indexBuffer - index buffer
* @param aIndex - number of floats already in the attribute buffer
* @param iIndex - number of indices already in `indexBuffer`
*/
packInterleavedGeometry(element: IBatchableElement, attributeBuffer: ViewableBuffer, indexBuffer: Uint16Array,
aIndex: number, iIndex: number): void
{
const {
uint32View,
float32View,
} = attributeBuffer;
const packedVertices = aIndex / this.vertexSize;
const uvs = element.uvs;
const indicies = element.indices;
const vertexData = element.vertexData;
const textureId = element._texture.baseTexture._batchLocation;
const alpha = Math.min(element.worldAlpha, 1.0);
const argb = (alpha < 1.0
&& element._texture.baseTexture.alphaMode)
? premultiplyTint(element._tintRGB, alpha)
: element._tintRGB + (alpha * 255 << 24);
// lets not worry about tint! for now..
for (let i = 0; i < vertexData.length; i += 2)
{
float32View[aIndex++] = vertexData[i];
float32View[aIndex++] = vertexData[i + 1];
float32View[aIndex++] = uvs[i];
float32View[aIndex++] = uvs[i + 1];
uint32View[aIndex++] = argb;
float32View[aIndex++] = textureId;
}
for (let i = 0; i < indicies.length; i++)
{
indexBuffer[iIndex++] = packedVertices + indicies[i];
}
}
/**
* Pool of `BatchDrawCall` objects that `flush` used
* to create "batches" of the objects being rendered.
*
* These are never re-allocated again.
* Shared between all batch renderers because it can be only one "flush" working at the moment.
* @member {PIXI.BatchDrawCall[]}
*/
static _drawCallPool: Array<BatchDrawCall> = [];
/**
* Pool of `BatchDrawCall` objects that `flush` used
* to create "batches" of the objects being rendered.
*
* These are never re-allocated again.
* Shared between all batch renderers because it can be only one "flush" working at the moment.
* @member {PIXI.BatchTextureArray[]}
*/
static _textureArrayPool: Array<BatchTextureArray> = [];
}