实现不同颜色的图片合批渲染

engine/core/renderer/webgl/sprite/simple.js改造

const vfmtPosUvColor = require('../../vertex-format').vfmtPosUvColor;

fillBuffers: function (sprite, renderer) {
        var data = sprite._renderData._data,
            node = sprite.node,
            matrix = node._worldMatrix,
            a = matrix.m00,
            b = matrix.m01,
            c = matrix.m04,
            d = matrix.m05,
            tx = matrix.m12,
            ty = matrix.m13;
    
        var buffer = renderer.getBuffer('quad', vfmtPosUvColor),
        // var buffer = renderer._quadBuffer,
            vertexOffset = buffer.byteOffset >> 2;
    
        buffer.request(4, 6);
    
        // buffer data may be realloc, need get reference after request.
        var vbuf = buffer._vData;
    
        // get uv from sprite frame directly
        var uv = sprite._spriteFrame.uv;
        vbuf[vertexOffset + 2] = uv[0];
        vbuf[vertexOffset + 3] = uv[1];
        vbuf[vertexOffset + 7] = uv[2];
        vbuf[vertexOffset + 8] = uv[3];
        vbuf[vertexOffset + 12] = uv[4];
        vbuf[vertexOffset + 13] = uv[5];
        vbuf[vertexOffset + 17] = uv[6];
        vbuf[vertexOffset + 18] = uv[7];
    
        var data0 = data[0],
            data3 = data[3],
            vl = data0.x,
            vr = data3.x,
            vb = data0.y,
            vt = data3.y;
    
        var al = a * vl,
            ar = a * vr,
            bl = b * vl,
            br = b * vr,
            cb = c * vb,
            ct = c * vt,
            db = d * vb,
            dt = d * vt;
    
        // left bottom
        vbuf[vertexOffset + 0] = al + cb + tx;
        vbuf[vertexOffset + 1] = bl + db + ty;
        // right bottom
        vbuf[vertexOffset + 5] = ar + cb + tx;
        vbuf[vertexOffset + 6] = br + db + ty;
        // left top
        vbuf[vertexOffset + 10] = al + ct + tx;
        vbuf[vertexOffset + 11] = bl + dt + ty;
        // right top
        vbuf[vertexOffset + 15] = ar + ct + tx;
        vbuf[vertexOffset + 16] = br + dt + ty;
    
        // color
        var val = node.color._val;
        var ibuf = buffer._uintVData;
        ibuf[vertexOffset + 4] = val;
        ibuf[vertexOffset + 9] = val;
        ibuf[vertexOffset + 14] = val;
        ibuf[vertexOffset + 19] = val;
    }

改造engine\cocos2d\core\components\CCSprite.js

    _activateMaterial: function () {
        let spriteFrame = this._spriteFrame;

        // WebGL
        if (cc.game.renderType !== cc.game.RENDER_TYPE_CANVAS) {
            // Get material
            let material;
            if (this._state === State.GRAY) {
                if (!this._graySpriteMaterial) {
                    this._graySpriteMaterial = new GraySpriteMaterial();
                }
                material = this._graySpriteMaterial;
            }
            else {
                if (!this._spriteMaterial) {
                    this._spriteMaterial = new SpriteMaterial();
                }
                material = this._spriteMaterial;
            }
            
            material._mainTech._parameters = [{ name: 'texture', type: 13 }]; // 不要color属性,避免不同颜色material的hash值不同导致不能合批,cc.renderer.renderEngine.renderer.PARAM_TEXTURE_2D的值就是13
            material._effect.define('useColor', false); // 不使用片段着色器的的color字段,开启顶点着色器的a_color
            
            // Set texture
            if (spriteFrame && spriteFrame.textureLoaded()) {
                let texture = spriteFrame.getTexture();
                if (material.texture !== texture) {
                    material.texture = texture;
                    this._updateMaterial(material);
                }
                else if (material !== this._material) {
                    this._updateMaterial(material);
                }
                if (this._renderData) {
                    this._renderData.material = material;
                }

                this.node._renderFlag |= RenderFlow.FLAG_COLOR;
                this.markForUpdateRenderData(true);
                this.markForRender(true);
            }
            else {
                this.disableRender();
            }
        }
        else {
            this.markForUpdateRenderData(true);
            this.markForRender(true);
        }
    }

然后再对引擎进行重新编译即可。

改造前


改造后

这只是对普通的sprite进行了修改,即Type为Simple的渲染策略进行了修改

如果要完整覆盖还需要修改sliced.js、tiled.js等,如果项目的Sprite的Type属性都是simple那就按照上面的方式改就行了。

注意:

  1. 上面的修改方式仅仅是在浏览器上进行了简单测试。
  2. 实验引擎版本为2.0.5
1赞

膜拜啊

点赞啊

如果项目能够愿意升级的话,可以升级到2.0.9版本,也可以。

升级不了了,已经对现有的引擎做了些修改,日子久了都忘了改了哪些东西。
只是感兴趣研究了一下。:stuck_out_tongue:

小海 你咋回事啊

兄弟 兄弟