import { AbstractBatchRenderer , ViewableBuffer , BatchTextureArray } from '@pixi/core' ; import { Dict , premultiplyBlendMode } from '@pixi/utils' ; import { Sprite } from '@pixi/sprite' ; export class UniformBatchRenderer extends AbstractBatchRenderer { _iIndex : number ; _aIndex : number ; _dcIndex : number ; _bufferedElements : Array < any > ; _attributeBuffer : ViewableBuffer ; _indexBuffer : Uint16Array ; vertexSize : number ; forceMaxTextures = 0 ; getUniforms ( sprite ) { return this . defUniforms ; } syncUniforms ( obj ) { if ( ! obj ) return ; const sh = this . _shader ; for ( const key in obj ) { sh . uniforms [ key ] = obj [ key ] ; } } defUniforms = { } ; buildDrawCalls ( texArray , start , finish ) { const thisAny = this as any ; 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 ] as any ; 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 ] ; const uniforms = this . getUniforms ( sprite ) ; elements [ i ] = null ; if ( start < i && ( drawCall . blend !== spriteBlendMode || drawCall . uniforms !== uniforms ) ) { 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 ; drawCall . uniforms = uniforms ; } if ( start < finish ) { drawCall . size = iIndex - drawCall . start ; ++ dcIndex ; } thisAny . _dcIndex = dcIndex ; thisAny . _aIndex = aIndex ; thisAny . _iIndex = iIndex ; } drawBatches ( ) { const dcCount = this . _dcIndex ; const { gl , state : stateSystem , shader : shaderSystem } = this . renderer ; const drawCalls = AbstractBatchRenderer . _drawCallPool ; let curUniforms = null ; let curTexArray = null ; for ( let i = 0 ; i < dcCount ; i ++ ) { const { texArray , type , size , start , blend , uniforms } = drawCalls [ i ] as any ; if ( curTexArray !== texArray ) { curTexArray = texArray ; this . bindAndClearTexArray ( texArray ) ; } if ( curUniforms !== uniforms ) { curUniforms = uniforms ; this . syncUniforms ( uniforms ) ; ( shaderSystem as any ) . syncUniformGroup ( ( this . _shader as any ) . uniformGroup ) ; } this . state . blendMode = blend ; stateSystem . set ( this . state ) ; gl . drawElements ( type , size , gl . UNSIGNED_SHORT , start * 2 ) ; } } contextChange ( ) { if ( ! this . forceMaxTextures ) { super . contextChange ( ) ; this . syncUniforms ( this . defUniforms ) ; return ; } const thisAny = this as any ; thisAny . MAX_TEXTURES = this . forceMaxTextures ; this . _shader = thisAny . shaderGenerator . generateShader ( this . MAX_TEXTURES ) ; this . syncUniforms ( this . defUniforms ) ; for ( let i = 0 ; i < thisAny . _packedGeometryPoolSize ; i ++ ) { thisAny . _packedGeometries [ i ] = new ( this . geometryClass ) ( ) ; } this . initFlushBuffers ( ) ; } }