mirror of
https://github.com/smallmain/cocos-enhance-kit.git
synced 2024-12-25 11:18:30 +00:00
[engine] service pack 命名空间、多纹理渲染基础
This commit is contained in:
parent
f31cb598e3
commit
7d0519ed68
@ -80,10 +80,52 @@ var builtins = {
|
||||
}
|
||||
|
||||
this._loadBuiltins('effect', () => {
|
||||
this._loadBuiltins('material', cb);
|
||||
this._loadBuiltins('material', () => {
|
||||
this._loadBuiltinsSP(cb);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
_loadBuiltinsSP(cb) {
|
||||
cc.sp.MAX_MULTITEXTURE_NUM = 8;
|
||||
// cc.renderer.device.caps.maxTextureUnits
|
||||
|
||||
this._loadMultiEffect('multi-2d-sprite', (effect) => {
|
||||
cc.sp.multi2dSpriteEffectAsset = effect;
|
||||
effect.addRef();
|
||||
cc.sp.inited = true;
|
||||
cc.sp.multiBatcher.init();
|
||||
|
||||
cb();
|
||||
});
|
||||
},
|
||||
|
||||
_loadMultiEffect(name, cb) {
|
||||
if (CC_EDITOR) {
|
||||
cc.assetManager.loadAny(Editor.assetdb.remote.urlToUuid('db://service-pack-resources/sp/effects/' + name + '.effect'), function (err, effect) {
|
||||
if (err) {
|
||||
return Editor.error(err);
|
||||
} else {
|
||||
cb(effect);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
cc.assetManager.loadBundle('sp', (err, bundle) => {
|
||||
if (err) {
|
||||
cc.error(err);
|
||||
} else {
|
||||
bundle.load('effects/' + name, cc.EffectAsset, (err, effect) => {
|
||||
if (err) {
|
||||
cc.error(err);
|
||||
} else {
|
||||
cb(effect);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Get the built-in asset using specific type and name.
|
||||
|
@ -470,6 +470,9 @@ var Texture2D = cc.Class({
|
||||
if (CC_EDITOR) {
|
||||
this._exportedExts = null;
|
||||
}
|
||||
|
||||
// multi batcher
|
||||
this._multiMaterial = null;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -688,6 +691,8 @@ var Texture2D = cc.Class({
|
||||
}
|
||||
this._packable && cc.dynamicAtlasManager && cc.dynamicAtlasManager.deleteAtlasTexture(this);
|
||||
|
||||
this.unlinkMaterial();
|
||||
|
||||
this._image = null;
|
||||
this._texture && this._texture.destroy();
|
||||
this._super();
|
||||
@ -1054,7 +1059,43 @@ var Texture2D = cc.Class({
|
||||
else {
|
||||
cb();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
linkMaterial(material, index) {
|
||||
const handler = material.getMultiHandler();
|
||||
if (handler) {
|
||||
if (index == null) {
|
||||
if (handler.autoSetTexture(this) === -1) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
handler.setTexture(index, this);
|
||||
}
|
||||
this.unlinkMaterial();
|
||||
this._multiMaterial = material;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
unlinkMaterial() {
|
||||
if (this._multiMaterial) {
|
||||
const handler = this._multiMaterial.getMultiHandler();
|
||||
const _texture = this.getImpl();
|
||||
handler.removeTexture(_texture);
|
||||
this._multiMaterial = null;
|
||||
}
|
||||
},
|
||||
|
||||
getLinkedMaterial() {
|
||||
return this._multiMaterial;
|
||||
},
|
||||
|
||||
hasLinkedMaterial() {
|
||||
return !!this._multiMaterial;
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -72,6 +72,7 @@ let Material = cc.Class({
|
||||
this._manualHash = false;
|
||||
this._dirty = true;
|
||||
this._effect = null;
|
||||
this._multiHandler = null;
|
||||
},
|
||||
|
||||
properties: {
|
||||
@ -124,6 +125,8 @@ let Material = cc.Class({
|
||||
}
|
||||
|
||||
this._effect = this._effectAsset.getInstantiatedEffect();
|
||||
|
||||
this.updateMultiSupport();
|
||||
}
|
||||
},
|
||||
|
||||
@ -140,6 +143,7 @@ let Material = cc.Class({
|
||||
set (v) {
|
||||
this._techniqueIndex = v;
|
||||
this._effect.switchTechnique(v);
|
||||
this.updateMultiSupport();
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -401,7 +405,39 @@ let Material = cc.Class({
|
||||
}
|
||||
}
|
||||
|
||||
this.updateMultiSupport();
|
||||
if (this._multiHandler) this._multiHandler.syncTextures();
|
||||
},
|
||||
|
||||
updateMultiSupport() {
|
||||
const passes = this._effect.technique.passes;
|
||||
if (passes.length > 0 && passes[0].getDefine("USE_MULTI_TEXTURE")) {
|
||||
this.setMultiSupport(true);
|
||||
} else {
|
||||
this.setMultiSupport(false);
|
||||
}
|
||||
},
|
||||
|
||||
isMultiSupport() {
|
||||
return !!this._multiHandler;
|
||||
},
|
||||
|
||||
setMultiSupport(bool) {
|
||||
if (bool) {
|
||||
if (this._multiHandler) {
|
||||
this._multiHandler.syncTextures();
|
||||
} else {
|
||||
this._multiHandler = new cc.sp.MultiHandler(this);
|
||||
}
|
||||
} else if (!bool) {
|
||||
this._multiHandler = null;
|
||||
}
|
||||
},
|
||||
|
||||
getMultiHandler() {
|
||||
return this._multiHandler;
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
export default Material;
|
||||
|
@ -40,6 +40,8 @@ if (!CC_EDITOR || !Editor.isMainProcess) {
|
||||
require('./physics');
|
||||
require('./camera/CCCamera');
|
||||
require('./geom-utils');
|
||||
|
||||
require('./sp');
|
||||
}
|
||||
|
||||
require('./mesh');
|
||||
|
3
engine/cocos2d/core/sp/index.js
Normal file
3
engine/cocos2d/core/sp/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
require('./sp');
|
||||
require('./multi-handler');
|
||||
require('./multi-batcher');
|
74
engine/cocos2d/core/sp/multi-batcher.ts
Normal file
74
engine/cocos2d/core/sp/multi-batcher.ts
Normal file
@ -0,0 +1,74 @@
|
||||
import { MultiHandler } from "./multi-handler";
|
||||
|
||||
|
||||
/**
|
||||
* 多纹理合批器
|
||||
*/
|
||||
export class MultiBatcher {
|
||||
|
||||
/**
|
||||
* 多纹理材质管理器数组
|
||||
*/
|
||||
handlers: MultiHandler[] = [];
|
||||
|
||||
/**
|
||||
* 有空槽的材质
|
||||
*/
|
||||
nextHandler!: MultiHandler;
|
||||
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
init() {
|
||||
const handler = new MultiHandler();
|
||||
this.handlers.push(handler);
|
||||
this.nextHandler = handler;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 传入 cc.Texture2D,会关联并返回一个多纹理材质,如果已经有关联的材质则会返回已关联的材质
|
||||
*/
|
||||
requsetMaterial(texture: any) {
|
||||
if (!texture._multiMaterial) {
|
||||
let handler = this.nextHandler;
|
||||
let index = handler.getEmptyIndex();
|
||||
if (index === -1) {
|
||||
// 没有空位,尝试在已有 handlers 里查找
|
||||
for (const _handler of this.handlers) {
|
||||
index = _handler.getEmptyIndex();
|
||||
if (index !== -1) {
|
||||
handler = _handler;
|
||||
this.nextHandler = handler;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 已有的没有空位,创建新材质
|
||||
if (index === -1) {
|
||||
handler = new MultiHandler();
|
||||
this.handlers.push(handler);
|
||||
this.nextHandler = handler;
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
texture.linkMaterial(handler.material, index);
|
||||
}
|
||||
return texture._multiMaterial;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 重置多纹理材质数组,再次使用请先初始化
|
||||
*/
|
||||
reset() {
|
||||
this.handlers.length = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
cc.sp.multiBatcher = new MultiBatcher();
|
||||
cc.sp.MultiBatcher = MultiBatcher;
|
146
engine/cocos2d/core/sp/multi-handler.ts
Normal file
146
engine/cocos2d/core/sp/multi-handler.ts
Normal file
@ -0,0 +1,146 @@
|
||||
/**
|
||||
* 多纹理 Material 管理类
|
||||
*/
|
||||
export class MultiHandler {
|
||||
|
||||
/**
|
||||
* 材质
|
||||
*/
|
||||
material: any;
|
||||
|
||||
/**
|
||||
* Texture 数组
|
||||
*
|
||||
* 注意:不是 cc.Texture2D
|
||||
*/
|
||||
protected textures: any[] = [];
|
||||
|
||||
/**
|
||||
* 有空槽(缓存值,并不是完全正确,只是为了降低当材质没有空槽时避免数组遍历的性能消耗)
|
||||
*/
|
||||
protected hasEmptySlot: boolean = false;
|
||||
|
||||
|
||||
constructor(material?) {
|
||||
if (material) {
|
||||
this.material = material;
|
||||
} else {
|
||||
this.material = (cc.Material as any).create(cc.sp.multi2dSpriteEffectAsset);
|
||||
this.material.name = "multi-2d-sprite";
|
||||
this.material.define('USE_TEXTURE', true);
|
||||
this.material.define('USE_MULTI_TEXTURE', true);
|
||||
}
|
||||
this.material._multiHandler = this;
|
||||
this.syncTextures();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 同步 Material 的纹理插槽数据
|
||||
*
|
||||
* 当自行设置插槽可调用此函数同步数组
|
||||
*/
|
||||
syncTextures() {
|
||||
const effect = this.material['effect'];
|
||||
const properties = effect.passes[0]._properties;
|
||||
|
||||
this.textures[0] = properties.texture.value;
|
||||
this.textures[1] = properties.texture2.value;
|
||||
this.textures[2] = properties.texture3.value;
|
||||
this.textures[3] = properties.texture4.value;
|
||||
this.textures[4] = properties.texture5.value;
|
||||
this.textures[5] = properties.texture6.value;
|
||||
this.textures[6] = properties.texture7.value;
|
||||
this.textures[7] = properties.texture8.value;
|
||||
|
||||
// refresh has empty slot state
|
||||
this.hasEmptySlot = true;
|
||||
this.getEmptyIndex();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置纹理插槽(提供 cc.Texture2D)
|
||||
*/
|
||||
setTexture(index: number, texture: any) {
|
||||
this.textures[index] = texture ? texture.getImpl() : null;
|
||||
this.material.setProperty(cc.sp.propertyIndex2Name(index), texture);
|
||||
if (texture == null) this.hasEmptySlot = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 移除指定纹理
|
||||
*
|
||||
* 注意:不是 cc.Texture2D
|
||||
*/
|
||||
removeTexture(texture: any) {
|
||||
const index = this.getIndex(texture);
|
||||
if (index !== -1) {
|
||||
this.setTexture(index, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 纹理是否在插槽中
|
||||
*
|
||||
* 注意:不是 cc.Texture2D
|
||||
*/
|
||||
hasTexture(texture: any) {
|
||||
return this.textures.indexOf(texture) !== -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取纹理在插槽中的 Index,没有返回 -1
|
||||
*
|
||||
* 注意:不是 cc.Texture2D
|
||||
*/
|
||||
getIndex(texture: any) {
|
||||
return this.textures.indexOf(texture);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定 index 中的纹理
|
||||
*
|
||||
* 注意:不是 cc.Texture2D
|
||||
*/
|
||||
getTexture(index: number) {
|
||||
return this.textures[index];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取空插槽 Index,没有返回 -1
|
||||
*/
|
||||
getEmptyIndex() {
|
||||
if (!this.hasEmptySlot) return -1;
|
||||
const index = this.textures.indexOf(null);
|
||||
if (index !== -1) {
|
||||
return index;
|
||||
} else {
|
||||
this.hasEmptySlot = false;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 自动设置纹理到空插槽,返回插槽下标,失败返回 -1(提供 cc.Texture2D)
|
||||
*/
|
||||
autoSetTexture(texture: any) {
|
||||
const index = this.getEmptyIndex();
|
||||
if (index === -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
this.setTexture(index, texture);
|
||||
return index;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
cc.sp.MultiHandler = MultiHandler;
|
86
engine/cocos2d/core/sp/sp.js
Normal file
86
engine/cocos2d/core/sp/sp.js
Normal file
@ -0,0 +1,86 @@
|
||||
cc.sp = {
|
||||
|
||||
/**
|
||||
* 是否初始化完成
|
||||
*/
|
||||
inited: false,
|
||||
|
||||
/**
|
||||
* 版本号
|
||||
*/
|
||||
version: "1.0.0",
|
||||
|
||||
/**
|
||||
* 最大纹理插槽数量
|
||||
*
|
||||
* 固定为 8
|
||||
*/
|
||||
MAX_MULTITEXTURE_NUM: -1,
|
||||
|
||||
/**
|
||||
* 渲染组件是否默认自动切换至贴图关联的材质
|
||||
*/
|
||||
autoSwitchMaterial: true,
|
||||
|
||||
/**
|
||||
* 渲染组件是否默认参与动态合图
|
||||
*/
|
||||
allowDynamicAtlas: true,
|
||||
|
||||
/**
|
||||
* Label 组件是否默认启用渲染时进行缩放以适配高 DPI 屏幕
|
||||
*/
|
||||
enableLabelRetina: true,
|
||||
|
||||
/**
|
||||
* Label 组件渲染时进行缩放的缩放比例
|
||||
*/
|
||||
labelRetinaScale: 1,
|
||||
|
||||
/**
|
||||
* Char 图集会进行自动多纹理合批的数量
|
||||
*/
|
||||
charAtlasAutoBatchCount: 1,
|
||||
|
||||
/**
|
||||
* Char 图集是否在场景切换时清空
|
||||
*/
|
||||
charAtlasAutoResetBeforeSceneLoad: true,
|
||||
|
||||
/**
|
||||
* 内置的多纹理合批 Effect Asset
|
||||
*/
|
||||
multi2dSpriteEffectAsset: null,
|
||||
|
||||
/**
|
||||
* property index to name map
|
||||
*/
|
||||
i2nMap: ['texture'],
|
||||
|
||||
/**
|
||||
* property name to index map
|
||||
*/
|
||||
n2iMap: { texture: 0 },
|
||||
|
||||
/**
|
||||
* property index to name
|
||||
*/
|
||||
propertyIndex2Name(index) {
|
||||
return this.i2nMap[index];
|
||||
},
|
||||
|
||||
/**
|
||||
* property name to index
|
||||
*/
|
||||
propertyName2Index(name) {
|
||||
return this.n2iMap[name];
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
// 初始化
|
||||
for (let i = 1; i < 8; i++) {
|
||||
const name = "texture" + (i + 1);
|
||||
cc.sp.i2nMap[i] = name;
|
||||
cc.sp.n2iMap[name] = i;
|
||||
}
|
Loading…
Reference in New Issue
Block a user