@@ -37,79 +37,91 @@ var _batchedInfo = {
37
37
shader : null
38
38
} ,
39
39
40
- _quadIndexBuffer = null ,
41
- _quadVertexBuffer = null ,
40
+ _batchBroken = false ,
41
+ _indexBuffer = null ,
42
+ _vertexBuffer = null ,
42
43
// Total vertex size
43
- _vertexSize = 0 ,
44
+ _maxVertexSize = 0 ,
44
45
// Current batching vertex size
45
46
_batchingSize = 0 ,
47
+ // Current batching index size
48
+ _indexSize = 0 ,
49
+ // Float size per vertex
46
50
_sizePerVertex = 6 ,
47
51
// buffer data and views
48
52
_vertexData = null ,
49
53
_vertexDataSize = 0 ,
50
54
_vertexDataF32 = null ,
51
55
_vertexDataUI32 = null ,
56
+ _indexData = null ,
57
+ _prevIndexSize = 0 ,
58
+ _pureQuad = true ,
52
59
_IS_IOS = false ;
53
60
54
61
55
62
// Inspired from @Heishe 's gotta-batch-them-all branch
56
63
// https://github.com/Talisca/cocos2d-html5/commit/de731f16414eb9bcaa20480006897ca6576d362c
57
- function updateQuadBuffer ( numQuads ) {
64
+ function updateBuffer ( numVertex ) {
58
65
var gl = cc . _renderContext ;
59
- // Update index buffer and fill up
60
- if ( _quadIndexBuffer ) {
61
- gl . bindBuffer ( gl . ELEMENT_ARRAY_BUFFER , _quadIndexBuffer ) ;
62
-
63
- var indices = new Uint16Array ( numQuads * 6 ) ;
66
+ // Update index buffer size
67
+ if ( _indexBuffer ) {
68
+ var indexCount = Math . ceil ( numVertex / 4 ) * 6 ;
69
+ gl . bindBuffer ( gl . ELEMENT_ARRAY_BUFFER , _indexBuffer ) ;
70
+ _indexData = new Uint16Array ( indexCount ) ;
64
71
var currentQuad = 0 ;
65
- for ( var i = 0 , len = numQuads * 6 ; i < len ; i += 6 ) {
66
- indices [ i ] = currentQuad + 0 ;
67
- indices [ i + 1 ] = currentQuad + 1 ;
68
- indices [ i + 2 ] = currentQuad + 2 ;
69
- indices [ i + 3 ] = currentQuad + 1 ;
70
- indices [ i + 4 ] = currentQuad + 2 ;
71
- indices [ i + 5 ] = currentQuad + 3 ;
72
+ for ( var i = 0 , len = indexCount ; i < len ; i += 6 ) {
73
+ _indexData [ i ] = currentQuad + 0 ;
74
+ _indexData [ i + 1 ] = currentQuad + 1 ;
75
+ _indexData [ i + 2 ] = currentQuad + 2 ;
76
+ _indexData [ i + 3 ] = currentQuad + 1 ;
77
+ _indexData [ i + 4 ] = currentQuad + 2 ;
78
+ _indexData [ i + 5 ] = currentQuad + 3 ;
72
79
currentQuad += 4 ;
73
80
}
74
- gl . bufferData ( gl . ELEMENT_ARRAY_BUFFER , indices , gl . STATIC_DRAW ) ;
81
+ gl . bufferData ( gl . ELEMENT_ARRAY_BUFFER , _indexData , gl . DYNAMIC_DRAW ) ;
75
82
}
76
-
77
- if ( _quadVertexBuffer ) {
78
- _vertexDataSize = numQuads * 4 * _sizePerVertex ;
83
+ // Update vertex buffer size
84
+ if ( _vertexBuffer ) {
85
+ _vertexDataSize = numVertex * _sizePerVertex ;
79
86
var byteLength = _vertexDataSize * 4 ;
80
87
_vertexData = new ArrayBuffer ( byteLength ) ;
81
88
_vertexDataF32 = new Float32Array ( _vertexData ) ;
82
89
_vertexDataUI32 = new Uint32Array ( _vertexData ) ;
83
90
// Init buffer data
84
- gl . bindBuffer ( gl . ARRAY_BUFFER , _quadVertexBuffer ) ;
91
+ gl . bindBuffer ( gl . ARRAY_BUFFER , _vertexBuffer ) ;
85
92
gl . bufferData ( gl . ARRAY_BUFFER , _vertexDataF32 , gl . DYNAMIC_DRAW ) ;
86
93
}
87
- _vertexSize = numQuads * 4 ;
94
+ // Downsize by 200 to avoid vertex data overflow
95
+ _maxVertexSize = numVertex - 200 ;
88
96
}
89
97
90
98
// Inspired from @Heishe 's gotta-batch-them-all branch
91
99
// https://github.com/Talisca/cocos2d-html5/commit/de731f16414eb9bcaa20480006897ca6576d362c
92
- function initQuadBuffer ( numQuads ) {
100
+ function initQuadBuffer ( numVertex ) {
93
101
var gl = cc . _renderContext ;
94
- if ( _quadIndexBuffer === null ) {
102
+ if ( _indexBuffer === null ) {
95
103
// TODO do user need to release the memory ?
96
- _quadVertexBuffer = gl . createBuffer ( ) ;
97
- _quadIndexBuffer = gl . createBuffer ( ) ;
98
-
99
- updateQuadBuffer ( numQuads ) ;
100
- }
101
- else {
102
- updateQuadBuffer ( numQuads ) ;
104
+ _vertexBuffer = gl . createBuffer ( ) ;
105
+ _indexBuffer = gl . createBuffer ( ) ;
103
106
}
107
+ updateBuffer ( numVertex ) ;
104
108
}
105
109
110
+ var VertexType = {
111
+ QUAD : 0 ,
112
+ TRIANGLE : 1 ,
113
+ CUSTOM : 2
114
+ } ;
115
+
106
116
return {
107
117
mat4Identity : null ,
108
118
109
119
childrenOrderDirty : true ,
110
120
assignedZ : 0 ,
111
121
assignedZStep : 1 / 100 ,
112
122
123
+ VertexType : VertexType ,
124
+
113
125
_transformNodePool : [ ] , //save nodes transform dirty
114
126
_renderCmds : [ ] , //save renderer commands
115
127
@@ -126,14 +138,14 @@ return {
126
138
127
139
this . mat4Identity = new cc . math . Matrix4 ( ) ;
128
140
this . mat4Identity . identity ( ) ;
129
- initQuadBuffer ( 500 ) ;
141
+ initQuadBuffer ( 2000 ) ;
130
142
if ( cc . sys . os === cc . sys . OS_IOS ) {
131
143
_IS_IOS = true ;
132
144
}
133
145
} ,
134
146
135
147
getVertexSize : function ( ) {
136
- return _vertexSize ;
148
+ return _maxVertexSize ;
137
149
} ,
138
150
139
151
getRenderCmd : function ( renderableObject ) {
@@ -249,7 +261,7 @@ return {
249
261
} ,
250
262
251
263
pushRenderCommand : function ( cmd ) {
252
- if ( ! cmd . needDraw ( ) )
264
+ if ( ! cmd . rendering && ! cmd . uploadData )
253
265
return ;
254
266
if ( this . _isCacheToBufferOn ) {
255
267
var currentId = this . _currentID , locCmdBuffer = this . _cacheToBufferCmds ;
@@ -263,25 +275,76 @@ return {
263
275
}
264
276
} ,
265
277
266
- _increaseBatchingSize : function ( increment ) {
278
+ _increaseBatchingSize : function ( increment , vertexType , indices ) {
279
+ vertexType = vertexType || VertexType . QUAD ;
280
+ var i , curr ;
281
+ switch ( vertexType ) {
282
+ case VertexType . QUAD :
283
+ for ( i = 0 ; i < increment ; i += 4 ) {
284
+ curr = _batchingSize + i ;
285
+ _indexData [ _indexSize ++ ] = curr + 0 ;
286
+ _indexData [ _indexSize ++ ] = curr + 1 ;
287
+ _indexData [ _indexSize ++ ] = curr + 2 ;
288
+ _indexData [ _indexSize ++ ] = curr + 1 ;
289
+ _indexData [ _indexSize ++ ] = curr + 2 ;
290
+ _indexData [ _indexSize ++ ] = curr + 3 ;
291
+ }
292
+ break ;
293
+ case VertexType . TRIANGLE :
294
+ _pureQuad = false ;
295
+ for ( i = 0 ; i < increment ; i += 3 ) {
296
+ curr = _batchingSize + i ;
297
+ _indexData [ _indexSize ++ ] = curr + 0 ;
298
+ _indexData [ _indexSize ++ ] = curr + 1 ;
299
+ _indexData [ _indexSize ++ ] = curr + 2 ;
300
+ }
301
+ break ;
302
+ case VertexType . CUSTOM :
303
+ // CUSTOM type increase the indices data
304
+ _pureQuad = false ;
305
+ var len = indices . length ;
306
+ for ( i = 0 ; i < len ; i ++ ) {
307
+ _indexData [ _indexSize ++ ] = _batchingSize + indices [ i ] ;
308
+ }
309
+ break ;
310
+ default :
311
+ return ;
312
+ }
267
313
_batchingSize += increment ;
268
314
} ,
269
315
316
+ _updateBatchedInfo : function ( texture , blendFunc , shaderProgram ) {
317
+ if ( texture ) {
318
+ _batchedInfo . texture = texture ;
319
+ }
320
+
321
+ if ( blendFunc ) {
322
+ _batchedInfo . blendSrc = blendFunc . src ;
323
+ _batchedInfo . blendDst = blendFunc . dst ;
324
+ }
325
+
326
+ if ( shaderProgram ) {
327
+ _batchedInfo . shader = shaderProgram ;
328
+ }
329
+ } ,
330
+
331
+ _breakBatch : function ( ) {
332
+ _batchBroken = true ;
333
+ } ,
334
+
270
335
_uploadBufferData : function ( cmd ) {
271
- if ( _batchingSize >= _vertexSize ) {
336
+ if ( _batchingSize >= _maxVertexSize ) {
272
337
this . _batchRendering ( ) ;
273
338
}
274
339
275
340
// Check batching
276
341
var node = cmd . _node ;
277
342
var texture = node . _texture || ( node . _spriteFrame ? node . _spriteFrame . _texture : null ) ;
278
- if ( ! texture ) {
279
- return ;
280
- }
281
343
var blendSrc = node . _blendFunc . src ;
282
344
var blendDst = node . _blendFunc . dst ;
283
345
var shader = cmd . _shaderProgram ;
284
- if ( _batchedInfo . texture !== texture ||
346
+ if ( _batchBroken ||
347
+ _batchedInfo . texture !== texture ||
285
348
_batchedInfo . blendSrc !== blendSrc ||
286
349
_batchedInfo . blendDst !== blendDst ||
287
350
_batchedInfo . shader !== shader ) {
@@ -292,11 +355,43 @@ return {
292
355
_batchedInfo . blendSrc = blendSrc ;
293
356
_batchedInfo . blendDst = blendDst ;
294
357
_batchedInfo . shader = shader ;
358
+ _batchBroken = false ;
295
359
}
296
360
297
361
// Upload vertex data
298
362
var len = cmd . uploadData ( _vertexDataF32 , _vertexDataUI32 , _batchingSize * _sizePerVertex ) ;
299
363
if ( len > 0 ) {
364
+ var i , curr , type = cmd . vertexType || VertexType . QUAD ;
365
+ switch ( type ) {
366
+ case VertexType . QUAD :
367
+ for ( i = 0 ; i < len ; i += 4 ) {
368
+ curr = _batchingSize + i ;
369
+ _indexData [ _indexSize ++ ] = curr + 0 ;
370
+ _indexData [ _indexSize ++ ] = curr + 1 ;
371
+ _indexData [ _indexSize ++ ] = curr + 2 ;
372
+ _indexData [ _indexSize ++ ] = curr + 1 ;
373
+ _indexData [ _indexSize ++ ] = curr + 2 ;
374
+ _indexData [ _indexSize ++ ] = curr + 3 ;
375
+ }
376
+ break ;
377
+ case VertexType . TRIANGLE :
378
+ _pureQuad = false ;
379
+ for ( i = 0 ; i < len ; i += 3 ) {
380
+ curr = _batchingSize + i ;
381
+ _indexData [ _indexSize ++ ] = curr + 0 ;
382
+ _indexData [ _indexSize ++ ] = curr + 1 ;
383
+ _indexData [ _indexSize ++ ] = curr + 2 ;
384
+ }
385
+ break ;
386
+ case VertexType . CUSTOM :
387
+ _pureQuad = false ;
388
+ if ( cmd . uploadIndexData ) {
389
+ _indexSize += cmd . uploadIndexData ( _indexData , _indexSize , _batchingSize ) ;
390
+ }
391
+ break ;
392
+ default :
393
+ return ;
394
+ }
300
395
_batchingSize += len ;
301
396
}
302
397
} ,
@@ -309,7 +404,7 @@ return {
309
404
var gl = cc . _renderContext ;
310
405
var texture = _batchedInfo . texture ;
311
406
var shader = _batchedInfo . shader ;
312
- var count = _batchingSize / 4 ;
407
+ var uploadAll = _batchingSize > _maxVertexSize * 0.5 ;
313
408
314
409
if ( shader ) {
315
410
shader . use ( ) ;
@@ -319,9 +414,9 @@ return {
319
414
cc . glBlendFunc ( _batchedInfo . blendSrc , _batchedInfo . blendDst ) ;
320
415
cc . glBindTexture2DN ( 0 , texture ) ; // = cc.glBindTexture2D(texture);
321
416
322
- gl . bindBuffer ( gl . ARRAY_BUFFER , _quadVertexBuffer ) ;
417
+ gl . bindBuffer ( gl . ARRAY_BUFFER , _vertexBuffer ) ;
323
418
// upload the vertex data to the gl buffer
324
- if ( _batchingSize > _vertexSize * 0.5 ) {
419
+ if ( uploadAll ) {
325
420
gl . bufferData ( gl . ARRAY_BUFFER , _vertexDataF32 , gl . DYNAMIC_DRAW ) ;
326
421
}
327
422
else {
@@ -336,12 +431,28 @@ return {
336
431
gl . vertexAttribPointer ( cc . VERTEX_ATTRIB_COLOR , 4 , gl . UNSIGNED_BYTE , true , 24 , 12 ) ;
337
432
gl . vertexAttribPointer ( cc . VERTEX_ATTRIB_TEX_COORDS , 2 , gl . FLOAT , false , 24 , 16 ) ;
338
433
339
- gl . bindBuffer ( gl . ELEMENT_ARRAY_BUFFER , _quadIndexBuffer ) ;
340
- gl . drawElements ( gl . TRIANGLES , count * 6 , gl . UNSIGNED_SHORT , 0 ) ;
434
+ gl . bindBuffer ( gl . ELEMENT_ARRAY_BUFFER , _indexBuffer ) ;
435
+ if ( ! _prevIndexSize || ! _pureQuad || _indexSize > _prevIndexSize ) {
436
+ if ( uploadAll ) {
437
+ gl . bufferData ( gl . ELEMENT_ARRAY_BUFFER , _indexData , gl . DYNAMIC_DRAW ) ;
438
+ }
439
+ else {
440
+ gl . bufferData ( gl . ELEMENT_ARRAY_BUFFER , _indexData . subarray ( 0 , _indexSize ) , gl . DYNAMIC_DRAW ) ;
441
+ }
442
+ }
443
+ gl . drawElements ( gl . TRIANGLES , _indexSize , gl . UNSIGNED_SHORT , 0 ) ;
341
444
342
445
cc . g_NumberOfDraws ++ ;
343
446
447
+ if ( _pureQuad ) {
448
+ _prevIndexSize = _indexSize ;
449
+ }
450
+ else {
451
+ _prevIndexSize = 0 ;
452
+ _pureQuad = true ;
453
+ }
344
454
_batchingSize = 0 ;
455
+ _indexSize = 0 ;
345
456
} ,
346
457
347
458
/**
@@ -350,14 +461,15 @@ return {
350
461
*/
351
462
rendering : function ( ctx , cmds ) {
352
463
var locCmds = cmds || this . _renderCmds ,
353
- i , len , cmd , next , batchCount ,
464
+ i , len , cmd ,
354
465
context = ctx || cc . _renderContext ;
355
466
356
467
// Reset buffer for rendering
357
468
context . bindBuffer ( gl . ARRAY_BUFFER , null ) ;
358
469
359
470
for ( i = 0 , len = locCmds . length ; i < len ; ++ i ) {
360
471
cmd = locCmds [ i ] ;
472
+ if ( ! cmd . needDraw ( ) ) continue ;
361
473
362
474
if ( cmd . uploadData ) {
363
475
this . _uploadBufferData ( cmd ) ;
0 commit comments