Skip to content

Commit f9e76f5

Browse files
author
minggo
authored
Merge pull request #1 from natural-law/update-spine
Support Spine Mesh in WebGL.
2 parents 88fa7ff + 320af08 commit f9e76f5

File tree

5 files changed

+352
-211
lines changed

5 files changed

+352
-211
lines changed

cocos2d/core/renderer/RendererWebGL.js

+158-46
Original file line numberDiff line numberDiff line change
@@ -37,79 +37,91 @@ var _batchedInfo = {
3737
shader: null
3838
},
3939

40-
_quadIndexBuffer = null,
41-
_quadVertexBuffer = null,
40+
_batchBroken = false,
41+
_indexBuffer = null,
42+
_vertexBuffer = null,
4243
// Total vertex size
43-
_vertexSize = 0,
44+
_maxVertexSize = 0,
4445
// Current batching vertex size
4546
_batchingSize = 0,
47+
// Current batching index size
48+
_indexSize = 0,
49+
// Float size per vertex
4650
_sizePerVertex = 6,
4751
// buffer data and views
4852
_vertexData = null,
4953
_vertexDataSize = 0,
5054
_vertexDataF32 = null,
5155
_vertexDataUI32 = null,
56+
_indexData = null,
57+
_prevIndexSize = 0,
58+
_pureQuad = true,
5259
_IS_IOS = false;
5360

5461

5562
// Inspired from @Heishe's gotta-batch-them-all branch
5663
// https://github.com/Talisca/cocos2d-html5/commit/de731f16414eb9bcaa20480006897ca6576d362c
57-
function updateQuadBuffer (numQuads) {
64+
function updateBuffer (numVertex) {
5865
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);
6471
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;
7279
currentQuad += 4;
7380
}
74-
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
81+
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, _indexData, gl.DYNAMIC_DRAW);
7582
}
76-
77-
if (_quadVertexBuffer) {
78-
_vertexDataSize = numQuads * 4 * _sizePerVertex;
83+
// Update vertex buffer size
84+
if (_vertexBuffer) {
85+
_vertexDataSize = numVertex * _sizePerVertex;
7986
var byteLength = _vertexDataSize * 4;
8087
_vertexData = new ArrayBuffer(byteLength);
8188
_vertexDataF32 = new Float32Array(_vertexData);
8289
_vertexDataUI32 = new Uint32Array(_vertexData);
8390
// Init buffer data
84-
gl.bindBuffer(gl.ARRAY_BUFFER, _quadVertexBuffer);
91+
gl.bindBuffer(gl.ARRAY_BUFFER, _vertexBuffer);
8592
gl.bufferData(gl.ARRAY_BUFFER, _vertexDataF32, gl.DYNAMIC_DRAW);
8693
}
87-
_vertexSize = numQuads * 4;
94+
// Downsize by 200 to avoid vertex data overflow
95+
_maxVertexSize = numVertex - 200;
8896
}
8997

9098
// Inspired from @Heishe's gotta-batch-them-all branch
9199
// https://github.com/Talisca/cocos2d-html5/commit/de731f16414eb9bcaa20480006897ca6576d362c
92-
function initQuadBuffer (numQuads) {
100+
function initQuadBuffer (numVertex) {
93101
var gl = cc._renderContext;
94-
if (_quadIndexBuffer === null) {
102+
if (_indexBuffer === null) {
95103
// 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();
103106
}
107+
updateBuffer(numVertex);
104108
}
105109

110+
var VertexType = {
111+
QUAD : 0,
112+
TRIANGLE : 1,
113+
CUSTOM: 2
114+
};
115+
106116
return {
107117
mat4Identity: null,
108118

109119
childrenOrderDirty: true,
110120
assignedZ: 0,
111121
assignedZStep: 1 / 100,
112122

123+
VertexType: VertexType,
124+
113125
_transformNodePool: [], //save nodes transform dirty
114126
_renderCmds: [], //save renderer commands
115127

@@ -126,14 +138,14 @@ return {
126138

127139
this.mat4Identity = new cc.math.Matrix4();
128140
this.mat4Identity.identity();
129-
initQuadBuffer(500);
141+
initQuadBuffer(2000);
130142
if (cc.sys.os === cc.sys.OS_IOS) {
131143
_IS_IOS = true;
132144
}
133145
},
134146

135147
getVertexSize: function () {
136-
return _vertexSize;
148+
return _maxVertexSize;
137149
},
138150

139151
getRenderCmd: function (renderableObject) {
@@ -249,7 +261,7 @@ return {
249261
},
250262

251263
pushRenderCommand: function (cmd) {
252-
if (!cmd.needDraw())
264+
if (!cmd.rendering && !cmd.uploadData)
253265
return;
254266
if (this._isCacheToBufferOn) {
255267
var currentId = this._currentID, locCmdBuffer = this._cacheToBufferCmds;
@@ -263,25 +275,76 @@ return {
263275
}
264276
},
265277

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+
}
267313
_batchingSize += increment;
268314
},
269315

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+
270335
_uploadBufferData: function (cmd) {
271-
if (_batchingSize >= _vertexSize) {
336+
if (_batchingSize >= _maxVertexSize) {
272337
this._batchRendering();
273338
}
274339

275340
// Check batching
276341
var node = cmd._node;
277342
var texture = node._texture || (node._spriteFrame ? node._spriteFrame._texture : null);
278-
if (!texture) {
279-
return;
280-
}
281343
var blendSrc = node._blendFunc.src;
282344
var blendDst = node._blendFunc.dst;
283345
var shader = cmd._shaderProgram;
284-
if (_batchedInfo.texture !== texture ||
346+
if (_batchBroken ||
347+
_batchedInfo.texture !== texture ||
285348
_batchedInfo.blendSrc !== blendSrc ||
286349
_batchedInfo.blendDst !== blendDst ||
287350
_batchedInfo.shader !== shader) {
@@ -292,11 +355,43 @@ return {
292355
_batchedInfo.blendSrc = blendSrc;
293356
_batchedInfo.blendDst = blendDst;
294357
_batchedInfo.shader = shader;
358+
_batchBroken = false;
295359
}
296360

297361
// Upload vertex data
298362
var len = cmd.uploadData(_vertexDataF32, _vertexDataUI32, _batchingSize * _sizePerVertex);
299363
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+
}
300395
_batchingSize += len;
301396
}
302397
},
@@ -309,7 +404,7 @@ return {
309404
var gl = cc._renderContext;
310405
var texture = _batchedInfo.texture;
311406
var shader = _batchedInfo.shader;
312-
var count = _batchingSize / 4;
407+
var uploadAll = _batchingSize > _maxVertexSize * 0.5;
313408

314409
if (shader) {
315410
shader.use();
@@ -319,9 +414,9 @@ return {
319414
cc.glBlendFunc(_batchedInfo.blendSrc, _batchedInfo.blendDst);
320415
cc.glBindTexture2DN(0, texture); // = cc.glBindTexture2D(texture);
321416

322-
gl.bindBuffer(gl.ARRAY_BUFFER, _quadVertexBuffer);
417+
gl.bindBuffer(gl.ARRAY_BUFFER, _vertexBuffer);
323418
// upload the vertex data to the gl buffer
324-
if (_batchingSize > _vertexSize * 0.5) {
419+
if (uploadAll) {
325420
gl.bufferData(gl.ARRAY_BUFFER, _vertexDataF32, gl.DYNAMIC_DRAW);
326421
}
327422
else {
@@ -336,12 +431,28 @@ return {
336431
gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, 24, 12);
337432
gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 24, 16);
338433

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);
341444

342445
cc.g_NumberOfDraws++;
343446

447+
if (_pureQuad) {
448+
_prevIndexSize = _indexSize;
449+
}
450+
else {
451+
_prevIndexSize = 0;
452+
_pureQuad = true;
453+
}
344454
_batchingSize = 0;
455+
_indexSize = 0;
345456
},
346457

347458
/**
@@ -350,14 +461,15 @@ return {
350461
*/
351462
rendering: function (ctx, cmds) {
352463
var locCmds = cmds || this._renderCmds,
353-
i, len, cmd, next, batchCount,
464+
i, len, cmd,
354465
context = ctx || cc._renderContext;
355466

356467
// Reset buffer for rendering
357468
context.bindBuffer(gl.ARRAY_BUFFER, null);
358469

359470
for (i = 0, len = locCmds.length; i < len; ++i) {
360471
cmd = locCmds[i];
472+
if (!cmd.needDraw()) continue;
361473

362474
if (cmd.uploadData) {
363475
this._uploadBufferData(cmd);

extensions/spine/CCSkeleton.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,9 @@ sp.Skeleton = cc.Node.extend(/** @lends sp.Skeleton# */{
216216

217217
for (var i = 0, slotCount = slots.length; i < slotCount; ++i) {
218218
var slot = slots[i];
219-
if (!slot.attachment || ! (attachment instanceof spine.RegionAttachment))
220-
continue;
221219
var attachment = slot.attachment;
220+
if (!attachment || ! (attachment instanceof spine.RegionAttachment))
221+
continue;
222222
vertices = attachment.updateWorldVertices(slot, false);
223223
minX = Math.min(minX, vertices[VERTEX.X1] * scaleX, vertices[VERTEX.X4] * scaleX, vertices[VERTEX.X2] * scaleX, vertices[VERTEX.X3] * scaleX);
224224
minY = Math.min(minY, vertices[VERTEX.Y1] * scaleY, vertices[VERTEX.Y4] * scaleY, vertices[VERTEX.Y2] * scaleY, vertices[VERTEX.Y3] * scaleY);

extensions/spine/CCSkeletonAnimation.js

-18
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,6 @@
2424
THE SOFTWARE.
2525
****************************************************************************/
2626

27-
/**
28-
* @ignore
29-
*/
30-
sp._atlasPage_createTexture_webGL = function (self, path) {
31-
var texture = cc.textureCache.addImage(path);
32-
self.rendererObject = new cc.TextureAtlas(texture, 128);
33-
self.width = texture.getPixelsWide();
34-
self.height = texture.getPixelsHigh();
35-
};
36-
37-
sp._atlasPage_createTexture_canvas = function(self, path) {
38-
self._texture = cc.textureCache.addImage(path);
39-
};
40-
41-
sp._atlasPage_disposeTexture = function (self) {
42-
self.rendererObject.release();
43-
};
44-
4527
sp._atlasLoader = {
4628
spAtlasFile:null,
4729
setAtlasFile:function(spAtlasFile){

0 commit comments

Comments
 (0)