Skip to content

Implementation of auto batch #3265

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Apr 20, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CCBoot.js
Original file line number Diff line number Diff line change
Expand Up @@ -2595,6 +2595,9 @@ cc.game = /** @lends cc.game# */{
cc.shaderCache._init();
cc._drawingUtil = new cc.DrawingPrimitiveWebGL(this._renderContext);
cc.textureCache._initializingRenderer();
// cc.glExt = {};
// cc.glExt.instanced_arrays = gl.getExtension("ANGLE_instanced_arrays");
// cc.glExt.element_uint = gl.getExtension("OES_element_index_uint");
} else {
cc.renderer = cc.rendererCanvas;
this._renderContext = cc._renderContext = new cc.CanvasContextWrapper(localCanvas.getContext("2d"));
Expand Down
3 changes: 1 addition & 2 deletions cocos2d/clipping-nodes/CCClippingNodeWebGLRenderCmd.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,9 @@

if (node.alphaThreshold < 1) { //TODO desktop
var program = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURECOLORALPHATEST);
var alphaValueLocation = gl.getUniformLocation(program.getProgram(), cc.UNIFORM_ALPHA_TEST_VALUE_S);
// set our alphaThreshold
cc.glUseProgram(program.getProgram());
program.setUniformLocationWith1f(alphaValueLocation, node.alphaThreshold);
program.setUniformLocationWith1f(cc.UNIFORM_ALPHA_TEST_VALUE_S, node.alphaThreshold);
cc.setProgram(node._stencil, program);
}
};
Expand Down
1 change: 1 addition & 0 deletions cocos2d/core/CCDirector.js
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ cc.Director = cc.Class.extend(/** @lends cc.Director# */{
if (this._runningScene) {
if (renderer.childrenOrderDirty === true) {
cc.renderer.clearRenderCommands();
cc.renderer.assignedZ = 0;
this._runningScene._renderCmd._curLevel = 0; //level start from 0;
this._runningScene.visit();
renderer.resetFlag();
Expand Down
2 changes: 1 addition & 1 deletion cocos2d/core/CCDirectorWebGL.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () {
size.width - ox,
-oy,
size.height - oy,
-1024, 1024);
-1, 1);
cc.kmGLMultMatrix(orthoMatrix);
cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
cc.kmGLLoadIdentity();
Expand Down
26 changes: 13 additions & 13 deletions cocos2d/core/CCDrawingPrimitivesWebGL.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL#
_renderContext:null,
_initialized:false,
_shader: null,
_colorLocation:-1,
_colorLocation: "u_color",
_colorArray: null,
_pointSizeLocation:-1,
_pointSizeLocation: "u_pointSize",
_pointSize:-1,
/**
* contructor of cc.DrawingPrimitiveWebGL
Expand All @@ -59,8 +59,8 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL#
// Position and 1 color passed as a uniform (to similate glColor4ub )
//
_t._shader = cc.shaderCache.programForKey(cc.SHADER_POSITION_UCOLOR);
_t._colorLocation = _t._renderContext.getUniformLocation(_t._shader.getProgram(), "u_color");
_t._pointSizeLocation = _t._renderContext.getUniformLocation(_t._shader.getProgram(), "u_pointSize");
_t._shader._addUniformLocation(this._colorLocation);
_t._shader._addUniformLocation(this._pointSizeLocation);

_t._initialized = true;
}
Expand All @@ -84,7 +84,7 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL#
this._shader.use();
this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
glContext.uniform4fv(this._colorLocation, this._colorArray);
this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray);
this._shader.setUniformLocationWith1f(this._pointSizeLocation, this._pointSize);

var pointBuffer = glContext.createBuffer();
Expand Down Expand Up @@ -113,7 +113,7 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL#
this._shader.use();
this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
glContext.uniform4fv(this._colorLocation, this._colorArray);
this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray);
this._shader.setUniformLocationWith1f(this._pointSizeLocation, this._pointSize);

var pointBuffer = glContext.createBuffer();
Expand Down Expand Up @@ -148,7 +148,7 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL#
this._shader.use();
this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
glContext.uniform4fv(this._colorLocation, this._colorArray);
this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray);

var pointBuffer = glContext.createBuffer();
glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
Expand Down Expand Up @@ -203,7 +203,7 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL#
this._shader.use();
this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
glContext.uniform4fv(this._colorLocation, this._colorArray);
this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray);

var pointBuffer = glContext.createBuffer();
glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
Expand Down Expand Up @@ -234,7 +234,7 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL#
this._shader.use();
this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
glContext.uniform4fv(this._colorLocation, this._colorArray);
this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray);

var pointBuffer = glContext.createBuffer();
glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
Expand Down Expand Up @@ -282,7 +282,7 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL#
this._shader.use();
this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
glContext.uniform4fv(this._colorLocation, this._colorArray);
this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray);

var pointBuffer = glContext.createBuffer();
glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
Expand Down Expand Up @@ -320,7 +320,7 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL#
this._shader.use();
this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
glContext.uniform4fv(this._colorLocation, this._colorArray);
this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray);

var pointBuffer = glContext.createBuffer();
glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
Expand Down Expand Up @@ -359,7 +359,7 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL#
this._shader.use();
this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
glContext.uniform4fv(this._colorLocation, this._colorArray);
this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray);

var pointBuffer = glContext.createBuffer();
glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
Expand Down Expand Up @@ -419,7 +419,7 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL#
this._shader.use();
this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
glContext.uniform4fv(this._colorLocation, this._colorArray);
this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray);

var pointBuffer = glContext.createBuffer();
glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
Expand Down
48 changes: 35 additions & 13 deletions cocos2d/core/base-nodes/CCNodeCanvasRenderCmd.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ cc.CustomRenderCmd = function (target, func) {
if (!this._callback)
return;
this._callback.call(this._target, ctx, scaleX, scaleY);
}
};
};

cc.Node._dirtyFlags = {transformDirty: 1 << 0, visibleDirty: 1 << 1, colorDirty: 1 << 2, opacityDirty: 1 << 3, cacheDirty: 1 << 4,
Expand All @@ -41,6 +41,7 @@ cc.Node._dirtyFlags = {transformDirty: 1 << 0, visibleDirty: 1 << 1, colorDirty:
//-------------------------Base -------------------------
cc.Node.RenderCmd = function(renderable){
this._dirtyFlag = 1; //need update the transform at first.
this._savedDirtyFlag = true;

this._node = renderable;
this._needDraw = false;
Expand Down Expand Up @@ -85,7 +86,7 @@ cc.Node.RenderCmd.prototype = {
},

getParentToNodeTransform: function(){
if(this._dirtyFlag & cc.Node._dirtyFlags.transformDirty)
if (this._dirtyFlag & cc.Node._dirtyFlags.transformDirty)
this._inverse = cc.affineTransformInvert(this.getNodeToParentTransform());
return this._inverse;
},
Expand Down Expand Up @@ -217,6 +218,8 @@ cc.Node.RenderCmd.prototype = {
var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
var colorDirty = locFlag & flags.colorDirty,
opacityDirty = locFlag & flags.opacityDirty;
this._savedDirtyFlag = this._savedDirtyFlag || locFlag;

if(colorDirty)
this._updateDisplayColor();

Expand Down Expand Up @@ -325,8 +328,14 @@ cc.Node.RenderCmd.prototype = {
_syncStatus: function (parentCmd) {
// In the visit logic does not restore the _dirtyFlag
// Because child elements need parent's _dirtyFlag to change himself
var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
var parentNode = parentCmd ? parentCmd._node : null;
var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag, parentNode = null;
if (parentCmd) {
parentNode = parentCmd._node;
this._savedDirtyFlag = this._savedDirtyFlag || parentCmd._savedDirtyFlag || locFlag;
}
else {
this._savedDirtyFlag = this._savedDirtyFlag || locFlag;
}

// There is a possibility:
// The parent element changed color, child element not change
Expand Down Expand Up @@ -368,24 +377,38 @@ cc.Node.RenderCmd.prototype = {
},

visitChildren: function(){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not know the relation between this code and batch rendering. Does this solve another issue? Or just an optimisation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's for setting correctly the vertexZ as depth value which will be used in the matrix.

Previously, the vertexZ of a Node is always 0

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With proper z values for all the nodes, it would be possible to render some nodes out-of-order and therefor do more batching. For example, if you have sets of sprites with (different) opaque textures that can't be batched because they are mixed in the render order, you could still batch them and it would end up looking correct because the z buffer values make sure that they end up in the correct order in the depth buffer. More specifically I think it would be possible to batch sprites even when text (cc.LabelTTF or something else) breaks up the batching. Since text (with node alpha of 1) only use alpha for anti-aliasing or maybe don't use it at all, I think it might be possible to draw them out of order with sprites using a special shader or maybe just a specific blending mode (not sure) and still have it end up looking correct. I mention the text thing because it's a very common case in our game, for example UI that has a lot of sprites and a few text's that break up an otherwise perfect batch order.

Again regarding the z-thing: If you want to keep node draw order 100% correct (i.e. renderCmds are always drawn in the order in which they appear in the renderCmdList of the renderer) then this is not necessary and can be removed I think (unless I missed something).

var renderer = cc.renderer;
var node = this._node;
var i, children = node._children, child;
var i, children = node._children, child, cmd;
var len = children.length;
if (len > 0) {
node.sortAllChildren();
// draw children zOrder < 0
for (i = 0; i < len; i++) {
child = children[i];
if (child._localZOrder < 0)
child._renderCmd.visit(this);
else
if (child._localZOrder < 0) {
cmd = child._renderCmd;
cmd.visit(this);
}
else {
break;
}
}

var z = renderer.assignedZ;
node._vertexZ = z;
renderer.assignedZ += renderer.assignedZStep;

renderer.pushRenderCommand(this);
for (; i < len; i++) {
child = children[i];
child._renderCmd.visit(this);
}
cc.renderer.pushRenderCommand(this);
for (; i < len; i++)
children[i]._renderCmd.visit(this);
} else {
cc.renderer.pushRenderCommand(this);
node._vertexZ = renderer.assignedZ;
renderer.assignedZ += renderer.assignedZStep;

renderer.pushRenderCommand(this);
}
this._dirtyFlag = 0;
}
Expand All @@ -399,7 +422,6 @@ cc.Node.RenderCmd.prototype = {
cc.Node.RenderCmd.call(this, renderable);
this._cachedParent = null;
this._cacheDirty = false;

};

var proto = cc.Node.CanvasRenderCmd.prototype = Object.create(cc.Node.RenderCmd.prototype);
Expand Down
36 changes: 9 additions & 27 deletions cocos2d/core/base-nodes/CCNodeWebGLRenderCmd.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
this._shaderProgram = null;

this._camera = null;

// Current index in the command list for improving auto batching perf
this._currId = -1;
};

var proto = cc.Node.WebGLRenderCmd.prototype = Object.create(cc.Node.RenderCmd.prototype);
Expand Down Expand Up @@ -80,37 +83,16 @@
t4x4Mat[5] = trans.d;
t4x4Mat[13] = trans.ty;

// Update Z vertex manually
t4x4Mat[14] = node._vertexZ;

//optimize performance for Javascript
cc.kmMat4Multiply(stackMatrix, parentMatrix, t4x4);

// XXX: Expensive calls. Camera should be integrated into the cached affine matrix
if (node._camera !== null && !(node.grid !== null && node.grid.isActive())) {
var apx = this._anchorPointInPoints.x, apy = this._anchorPointInPoints.y;
var translate = (apx !== 0.0 || apy !== 0.0);
if (translate){
if(!cc.SPRITEBATCHNODE_RENDER_SUBPIXEL) {
apx = 0 | apx;
apy = 0 | apy;
}
//cc.kmGLTranslatef(apx, apy, 0);
var translation = cc.math.Matrix4.createByTranslation(apx, apy, 0, t4x4); //t4x4 as a temp matrix
stackMatrix.multiply(translation);

node._camera._locateForRenderer(stackMatrix);

//cc.kmGLTranslatef(-apx, -apy, 0); optimize at here : kmGLTranslatef
translation = cc.math.Matrix4.createByTranslation(-apx, -apy, 0, translation);
stackMatrix.multiply(translation);
t4x4.identity(); //reset t4x4;
} else {
node._camera._locateForRenderer(stackMatrix);
}
}
if(!recursive || !node._children || node._children.length === 0)
// Update Z depth
t4x4Mat[14] = node._vertexZ;

if (!recursive || !node._children) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed expensive call for Camera, as it's never used in JS and can't be used.

return;
}

var i, len, locChildren = node._children;
for(i = 0, len = locChildren.length; i< len; i++){
locChildren[i]._renderCmd.transform(this, recursive);
Expand Down
4 changes: 3 additions & 1 deletion cocos2d/core/labelttf/CCLabelTTFWebGLRenderCmd.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@
this.setShaderProgram(cc.shaderCache.programForKey(cc.LabelTTF._SHADER_PROGRAM));
};
var proto = cc.LabelTTF.WebGLRenderCmd.prototype = Object.create(cc.Sprite.WebGLRenderCmd.prototype);
proto._supportBatch = false;

cc.inject(cc.LabelTTF.CacheRenderCmd.prototype, proto);
proto.constructor = cc.LabelTTF.WebGLRenderCmd;
proto._updateColor = function () {
this._updateTexture();
cc.Sprite.WebGLRenderCmd.prototype._updateColor.call(this);
}
};
})();
32 changes: 31 additions & 1 deletion cocos2d/core/platform/CCMacro.js
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,27 @@ cc.VERTEX_ATTRIB_TEX_COORDS = 2;
* @constant
* @type {Number}
*/
cc.VERTEX_ATTRIB_MAX = 3;
cc.VERTEX_ATTRIB_MVMAT0 = 3;
/**
* @constant
* @type {Number}
*/
cc.VERTEX_ATTRIB_MVMAT1 = 4;
/**
* @constant
* @type {Number}
*/
cc.VERTEX_ATTRIB_MVMAT2 = 5;
/**
* @constant
* @type {Number}
*/
cc.VERTEX_ATTRIB_MVMAT3 = 6;
/**
* @constant
* @type {Number}
*/
cc.VERTEX_ATTRIB_MAX = 7;

//------------Uniforms------------------
/**
Expand Down Expand Up @@ -626,6 +646,11 @@ cc.SHADER_POSITION_TEXTURECOLOR = "ShaderPositionTextureColor";
* @type {String}
*/
cc.SHADER_POSITION_TEXTURECOLORALPHATEST = "ShaderPositionTextureColorAlphaTest";
/**
* @constant
* @type {String}
*/
cc.SHADER_POSITION_TEXTURECOLORALPHATEST_BATCHED = "ShaderPositionTextureColorAlphaTestBatched";
/**
* @constant
* @type {String}
Expand Down Expand Up @@ -720,6 +745,11 @@ cc.ATTRIBUTE_NAME_POSITION = "a_position";
* @type {String}
*/
cc.ATTRIBUTE_NAME_TEX_COORD = "a_texCoord";
/**
* @constant
* @type {String}
*/
cc.ATTRIBUTE_NAME_MVMAT = "a_mvMatrix";


/**
Expand Down
Loading