123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- import { getMaterialHash } from "./MultUtils";
- const _textrue = {
- texture: null,
- defalut: new cc.Texture2D(),
- getImpl: function () {
- return this.texture;
- },
- };
- //@ts-ignore
- cc.gfx.Texture2D.prototype.texID = -1;
- //多纹理缓存
- let _cachdUseCount: number = 0;
- let _isMultTexture: boolean = false;
- let _cacheMaterials: Array<cc.Material> = [];
- export const MultBatch2D: any = {
- enable: false,
- parent: null,
- curID: 0,
- incID: 0,
- count: 0,
- hash: 0,
- reset: function () {
- if(this.count > 0)this.curID++;
- this.incID += this.count;
- this.count = 0;
- },
-
- clear: function () {
- let materials = _cacheMaterials;
- for (let i = 0; i < materials.length; i++) {
- let m: any = materials[i];
- m.destroy();
- m.decRef();
- }
- _cacheMaterials.length = 0;
- }
- };
- //提前加载多纹理材质
- const loadMultTextures = function () {
- MultBatch2D.enable = false;
- //@ts-ignore
- cc.resources.load("multTextures/Mult-material", cc.Material, (err, material) => {
- if (!err) {
- //@ts-ignore
- let cacheMat = cc.Material.getBuiltinMaterial("2d-sprite");;
- if (cacheMat) {
- //@ts-ignore
- MultBatch2D.hash = getMaterialHash(cacheMat);
- MultBatch2D.parent = material;
- MultBatch2D.enable = true;
- material.addRef();
- }
- }
- });
- }
- //使用多纹理材质缓存
- export const getMultMaterial = function (oldMat: any) {
- MultBatch2D.reset();
- _isMultTexture = false;
- if (!MultBatch2D.enable ||
- !oldMat || !oldMat.isMultTextures) {
- return oldMat;
- }
- if (!MultBatch2D.parent
- || !MultBatch2D.parent.isValid) {
- loadMultTextures();
- return oldMat;
- }
- let newMat: any = _cacheMaterials[_cachdUseCount++];
- if (!newMat || !newMat.isValid) {
- let MaterialVariant: any = cc.MaterialVariant;
- newMat = new MaterialVariant(MultBatch2D.parent);
- _cacheMaterials[_cachdUseCount - 1] = (newMat);
- for (let i = 0; i < 8; i++) {
- newMat.setProperty("texture" + i, _textrue.defalut);
- }
- newMat.updateHash(MultBatch2D.hash);
- newMat.define("USE_TEXTURE", true);
- newMat['isMultTextures'] = true;
- newMat['cacheTextures'] = [-1];
- newMat.addRef();
- }
- _isMultTexture = true;
- return newMat;
- }
- const fillRenderDataTexID = function (cmp: any, texID: number) {
- let renderData = cmp._assembler._renderData;
- if (!renderData) return false;
- let uvX = 0;
- let vbuf = renderData.vDatas[0];
- if (cmp.dataDirty) {
- cmp.dataDirty = false;
- for (let i = 0, length = vbuf.length; i < length; i += 5) {
- uvX = ~~(vbuf[i + 2] * 100000);
- vbuf[i + 2] = uvX * 10 + texID;
- }
- } else {
- if (cmp.texID != texID) {
- for (let i = 0, length = vbuf.length; i < length; i += 5) {
- uvX = ~~(vbuf[i + 2] * 0.1);
- vbuf[i + 2] = uvX * 10 + texID;
- }
- }
- }
- cmp.texID = texID;
- }
- const bindMultTexture = function (cmp: cc.RenderComponent, material: cc.Material, renderer: any) {
- if (!_isMultTexture || !material) return;
- //@ts-ignore
- let texture: any = material.effect.passes[0].getProperty("texture");
- if (!texture) return; //_textrue.defalut; //
- const MB = MultBatch2D;
- //@ts-ignore
- let effect = material.effect;
- let id = texture.texID - MB.incID;
- if (id < 0) {
- if (MB.count >= 8) {
- if (!CC_JSB) renderer._flush();
- renderer.material = getMultMaterial(material);
- renderer.node = material.getDefine("CC_USE_MODEL") ? cmp.node : renderer._dummyNode;
- }
- id = MB.count++;
- texture.texID = id + MB.incID;
- //绑定上传纹理->多纹理材质
- let curMaterial = renderer.material;
- let cache = curMaterial['cacheTextures'];
- if (cache[id] !== texture._id) {
- cache[id] = texture._id;
- _textrue.texture = texture;
- curMaterial.setProperty("texture" + id, _textrue);
- curMaterial.effect._dirty = false;
- curMaterial._dirty = false;
- }
- if (id == 0 && CC_JSB) {
- let obj = curMaterial._effect._nativeObj;
- if (material['_obj'] !== obj) {
- material['_obj'] = obj;
- effect._nativeObj.setEffect(obj);
- }
- }
- }
- if (CC_JSB) {
- let hash = MB.curID + 0.5;
- if (material['_hash'] !== hash) {
- material['_hash'] = hash;
- effect._nativeObj.updateHash(hash);
- }
- }
- //记录上传纹理id->顶点数据
- fillRenderDataTexID(cmp, id);
- }
- if (!CC_EDITOR) {//&& !CC_JSB
- const RenderCmp: any = cc.RenderComponent.prototype;
- RenderCmp.texID = -1;
- RenderCmp.vDitry = true;
- RenderCmp.dataDirty = true;
- //顶点数据更改检测
- Object.defineProperty(RenderCmp, "_vertsDirty", {
- get: function () {
- return this.vDitry;
- },
- set: function (flag) {
- if (!flag && this.vDitry) {
- this.dataDirty = true;
- }
- this.vDitry = flag;
- },
- });
- //材质切换检测
- const setMaterial = RenderCmp.setMaterial;
- RenderCmp.setMaterial = function (index, material) {
- let isMultTextures = false;
- let oldMat = this._materials[index];
- if (oldMat) {
- isMultTextures = oldMat.isMultTextures;
- }
- let newMat = setMaterial.call(this, index, material);
- this.setVertsDirty(); //isMultTextures &&
- return newMat;
- }
- //多纹理材质hash检测
- const Material: any = cc.Material.prototype;
- const getHash = Material.getHash;
- Material.getHash = function () {
- let effect: any = this._effect;
- if (MultBatch2D.enable && effect && effect._dirty) {
- this['isMultTextures'] = false;
- let uir = this._owner;
- if (uir && (uir instanceof cc.Sprite || uir instanceof cc.Label)) {
- let hash = getMaterialHash(this);
- if (hash == MultBatch2D.hash) {
- this['isMultTextures'] = true;
- effect._dirty = false;
- effect._hash = hash;
- return hash;
- }
- }
- }
- return getHash.call(this);
- }
- //重写 _checkBacth 合批分发函数
- RenderCmp._checkBacth = function (renderer, cullingMask) {
- let material: any = this._materials[0];
- if ((material && material.getHash() !== renderer.material.getHash()) || renderer.cullingMask !== cullingMask) {
- if (!CC_JSB) renderer._flush();
- renderer.node = material.getDefine("CC_USE_MODEL") ? this.node : renderer._dummyNode;
- renderer.material = getMultMaterial(material);
- renderer.cullingMask = cullingMask;
- }
- bindMultTexture(this, material, renderer);
- };
- cc.game.on(cc.game.EVENT_GAME_INITED, () => {
- loadMultTextures();
- });
- cc.game.on(cc.game.EVENT_ENGINE_INITED, () => {
- });
- cc.director.on(cc.Director.EVENT_BEFORE_DRAW, () => {
- _cachdUseCount = 0;
- MultBatch2D.reset();
- MultBatch2D.curID = 0;
- });
- }
|