415 lines
12 KiB
JavaScript
415 lines
12 KiB
JavaScript
var renderEngine = cc.renderer.renderEngine;
|
||
var Material = renderEngine.Material;
|
||
|
||
|
||
|
||
|
||
|
||
const MVP = `
|
||
uniform mat4 viewProj;
|
||
#ifdef use2DPos
|
||
attribute vec2 a_position;
|
||
#else
|
||
attribute vec3 a_position;
|
||
#endif
|
||
attribute lowp vec4 a_color;
|
||
#ifdef useModel
|
||
uniform mat4 model;
|
||
#endif
|
||
#ifdef useTexture
|
||
attribute mediump vec2 a_uv0;
|
||
varying mediump vec2 uv0;
|
||
#endif
|
||
#ifndef useColor
|
||
varying lowp vec4 v_fragmentColor;
|
||
#endif
|
||
|
||
attribute mediump vec2 a_uv1;
|
||
attribute mediump vec2 a_uv2;
|
||
attribute mediump vec2 a_uv3;
|
||
|
||
varying mediump vec2 uv1;
|
||
varying mediump vec2 uv2;
|
||
varying mediump vec2 uv3;
|
||
|
||
void main () {
|
||
mat4 mvp;
|
||
#ifdef useModel
|
||
mvp = viewProj * model;
|
||
#else
|
||
mvp = viewProj;
|
||
#endif
|
||
#ifdef use2DPos
|
||
vec4 pos = mvp * vec4(a_position, 0, 1);
|
||
#else
|
||
vec4 pos = mvp * vec4(a_position, 1);
|
||
#endif
|
||
#ifndef useColor
|
||
v_fragmentColor = a_color;
|
||
#endif
|
||
#ifdef useTexture
|
||
uv0 = a_uv0;
|
||
#endif
|
||
uv1 = a_uv1;
|
||
uv2 = a_uv2;
|
||
uv3 = a_uv3;
|
||
|
||
gl_Position = pos;
|
||
}`
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
var ShaderMaterial = cc.Class({
|
||
extends: Material,
|
||
properties: {
|
||
|
||
},
|
||
|
||
setUVoffset(frame,sp)
|
||
{
|
||
let rect = frame.getRect();
|
||
let texture = frame.getTexture();
|
||
let texw = texture.width;
|
||
let texh = texture.height;
|
||
let l = 0, r = 0, b = 1, t = 1;
|
||
l = texw && rect.x / texw;
|
||
t = texh && rect.y / texh;
|
||
if(frame.isRotated())
|
||
{
|
||
r = texw && (rect.x+rect.height)/texw;
|
||
b = texh && (rect.y+rect.width)/texh;
|
||
}
|
||
else
|
||
{
|
||
r = texw && (rect.x+rect.width)/texw;
|
||
b = texh && (rect.y+rect.height)/texh;
|
||
}
|
||
this._UVoffset={}
|
||
this._UVoffset.x = l;
|
||
this._UVoffset.y = t;
|
||
this._UVoffset.z = r;
|
||
this._UVoffset.w = b;
|
||
// this._rotated = frame.isRotated() ? 1.0 : 0.0;
|
||
|
||
this._effect.setProperty('UVoffset', this._UVoffset);
|
||
this._effect.setProperty('rotated', frame.isRotated() ? 1.0 : 0.0);
|
||
|
||
sp.srotated = frame.isRotated() ? 1.0 : 0.0
|
||
sp.sUVoffset = {x:l,y:t,z:r,w:b}
|
||
|
||
},
|
||
initspine(shaderName,params){
|
||
var renderer = renderEngine.renderer;
|
||
var gfx = renderEngine.gfx;
|
||
var pass = new renderer.Pass(shaderName);
|
||
pass.setDepth(false, false);
|
||
pass.setCullMode(gfx.CULL_NONE);
|
||
pass.setBlend(
|
||
gfx.BLEND_FUNC_ADD,
|
||
gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA,
|
||
gfx.BLEND_FUNC_ADD,
|
||
gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA
|
||
);
|
||
|
||
var techParams = [
|
||
{ name: 'texture', type: renderer.PARAM_TEXTURE_2D },
|
||
];
|
||
if (params) {
|
||
techParams = techParams.concat(params);
|
||
}
|
||
|
||
var mainTech = new renderer.Technique(
|
||
['transparent'],
|
||
techParams,
|
||
[pass]
|
||
);
|
||
|
||
this.effect = this._effect = new renderer.Effect(
|
||
[mainTech ],
|
||
{},
|
||
[
|
||
{ name: 'useModel', value: true },
|
||
{ name: 'alphaTest', value: false },
|
||
{ name: 'use2DPos', value: true },
|
||
{ name: 'useTint', value: false } ]
|
||
);
|
||
this.name = shaderName;
|
||
this._mainTech = mainTech;
|
||
this._texture = null;
|
||
|
||
},
|
||
|
||
|
||
init (shaderName,params,defines,passdata) {
|
||
var renderer = renderEngine.renderer;
|
||
var gfx = renderEngine.gfx;
|
||
var pass = new renderer.Pass(shaderName);
|
||
pass.setDepth(false, false);
|
||
pass.setCullMode(gfx.CULL_NONE);
|
||
if(passdata == null){
|
||
pass.setBlend(
|
||
gfx.BLEND_FUNC_ADD,
|
||
gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA,
|
||
gfx.BLEND_FUNC_ADD,
|
||
gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA
|
||
);
|
||
}
|
||
else{
|
||
pass.setBlend(
|
||
passdata[0],
|
||
passdata[1], passdata[2],
|
||
passdata[3],
|
||
passdata[4], passdata[5]
|
||
);
|
||
}
|
||
|
||
var techParams = [
|
||
{ name: 'texture', type: renderer.PARAM_TEXTURE_2D },
|
||
{ name: 'color', type: renderer.PARAM_COLOR4 },
|
||
{ name:'UVoffset', type: renderer.PARAM_FLOAT4 },
|
||
{ name:'rotated', type: renderer.PARAM_FLOAT },
|
||
];
|
||
if (params) {
|
||
techParams = techParams.concat(params);
|
||
}
|
||
var mainTech = new renderer.Technique(
|
||
['transparent'],
|
||
techParams,
|
||
[pass]
|
||
);
|
||
|
||
this.name = shaderName;
|
||
|
||
this.effect = this._effect = new renderer.Effect(
|
||
[ mainTech ],
|
||
{},
|
||
[
|
||
{ name: 'useTexture', value: true },
|
||
{ name: 'useModel', value: false },
|
||
{ name: 'alphaTest', value: false },
|
||
{ name: 'use2DPos', value: true },
|
||
{ name: 'useColor', value: true }
|
||
],
|
||
);
|
||
this._texture = null;
|
||
this._color = { r: 1, g: 1, b: 1, a: 1 };
|
||
|
||
this._mainTech = mainTech;
|
||
},
|
||
// 设置自定义参数的值
|
||
setParamValue(name, value) {
|
||
this._effect.setProperty(name, value);
|
||
},
|
||
|
||
// 获取自定义参数的值
|
||
getParamValue(name) {
|
||
return this._effect.getProperty(name);
|
||
},
|
||
|
||
// 设置定义值
|
||
setDefine(name, value) {
|
||
this._effect.define(name, value);
|
||
},
|
||
|
||
|
||
setTexture(texture) {
|
||
this._texture = texture;
|
||
this._texture.update({ flipY: false, mipmap: false });
|
||
this._effect.setProperty('texture', texture.getImpl());
|
||
this._texIds['texture'] = texture.getId();
|
||
},
|
||
|
||
bindShader(name,parmas,pass){
|
||
var sconfig = ShaderMaterial.getShader(name);
|
||
this.init(name,sconfig.params,sconfig.defines||[],pass);
|
||
sconfig.start&&sconfig.start(this,parmas);
|
||
if(sconfig.update){
|
||
this.needUpdate = true;
|
||
this.isAni = true
|
||
ShaderMaterial.pushUpdate(this);
|
||
}
|
||
},
|
||
|
||
bindShader2(name,parmas,pass){
|
||
var sconfig = ShaderMaterial.getShader(name);
|
||
this.initspine(name,sconfig.params);
|
||
sconfig.start&&sconfig.start(this,parmas);
|
||
if(sconfig.update){
|
||
this.needUpdate = true;
|
||
this.shadercfg = sconfig
|
||
}
|
||
},
|
||
|
||
restartShadre(){
|
||
if(this.isAni){
|
||
ShaderMaterial.pushUpdate(this);
|
||
}
|
||
},
|
||
applaySpine(sp,name,parmas){
|
||
var texture = sp._material._texture
|
||
parmas = parmas||{}
|
||
sp._shaderMeterial = this
|
||
sp._updateMaterial(this)
|
||
this.bindShader2(name,parmas);
|
||
|
||
|
||
this.setTexture(texture);
|
||
this.updateHash();
|
||
|
||
},
|
||
applaySprite(sp,name,parmas){
|
||
// if(sp.node.active ==false){
|
||
// return;
|
||
// }
|
||
if(!sp._renderData){
|
||
return;
|
||
}
|
||
parmas = parmas||{}
|
||
if(sp.node){
|
||
parmas.width = sp.node.width;
|
||
parmas.height = sp.node.height;
|
||
parmas.color = sp.node.color;
|
||
parmas.color.r = parmas.color.r/255;
|
||
parmas.color.g = parmas.color.g/255;
|
||
parmas.color.b = parmas.color.b/255;
|
||
parmas.color.a = parmas.color.a/255;
|
||
}
|
||
this.bindShader(name,parmas);
|
||
|
||
var texture = sp.spriteFrame.getTexture();
|
||
this.setTexture(texture);
|
||
this.updateHash();
|
||
if(sp._shaderMeterial&&sp._shaderMeterial.needUpdate){
|
||
ShaderMaterial.cleanUpdate(sp._shaderMeterial);
|
||
}
|
||
sp._state = 2;
|
||
sp._material = this;
|
||
sp._renderData.material = this;
|
||
sp._shaderMeterial = this
|
||
//this.setUVoffset(sp._spriteFrame,sp)
|
||
},
|
||
applaySpriteOnce(sp,name,parmas){
|
||
if(!this.hasinit){
|
||
this.applaySprite(sp,name,parmas)
|
||
}else{
|
||
sp._state = 2;
|
||
sp._material = this;
|
||
sp._renderData.material = this;
|
||
sp._shaderMeterial = this
|
||
}
|
||
this.hasinit = true
|
||
|
||
},
|
||
|
||
|
||
applayLabel(sp,name,parmas){
|
||
if(sp.node.active ==false||!sp._frame||!sp._frame._texture){
|
||
return;
|
||
}
|
||
parmas = parmas||{}
|
||
if(sp.node){
|
||
parmas.width = sp.node.width;
|
||
parmas.height = sp.node.height;
|
||
parmas.color = sp.node.color;
|
||
parmas.color.r = parmas.color.r/255;
|
||
parmas.color.g = parmas.color.g/255;
|
||
parmas.color.b = parmas.color.b/255;
|
||
parmas.color.a = parmas.color.a/255;
|
||
}
|
||
this.bindShader(name,parmas);
|
||
|
||
var texture = sp._frame._texture;
|
||
this.setTexture(texture);
|
||
this.updateHash();
|
||
if(sp._material&&sp._material.needUpdate){
|
||
ShaderMaterial.cleanUpdate(sp._material);
|
||
}
|
||
sp._material = this;
|
||
sp._renderData.material = this;
|
||
sp._shaderMeterial = this
|
||
},
|
||
|
||
applayButton(btn,name,parmas){
|
||
if(btn.node.active ==false){
|
||
return;
|
||
}
|
||
|
||
this.applaySprite(btn._sprite,name,parmas)
|
||
btn.useShader = true
|
||
|
||
},
|
||
cleanUp(){
|
||
if(this.needUpdate){
|
||
ShaderMaterial.cleanUpdate(this);
|
||
this.needUpdate = false;
|
||
}
|
||
},
|
||
reset(parmas){
|
||
var sconfig = ShaderMaterial.getShader(this.name);
|
||
sconfig.reset&&sconfig.reset(this,parmas);
|
||
},
|
||
});
|
||
|
||
var g_shaders = {};
|
||
var mtArr =[];
|
||
ShaderMaterial.addShader = function(shader){
|
||
|
||
|
||
|
||
|
||
if (g_shaders[shader.name]) {
|
||
console.log("addShader - shader already exist: ", shader.name);
|
||
return;
|
||
}
|
||
var def=[
|
||
{ name: 'useTexture', value: true },
|
||
{ name: 'useModel', value: false },
|
||
{ name: 'alphaTest', value: false },
|
||
{ name: 'use2DPos', value: true },
|
||
{ name: 'useColor', value: true }
|
||
]
|
||
if (cc.renderer._forward) {
|
||
cc.renderer._forward._programLib.define(shader.name, shader.vert||MVP, shader.frag, def);
|
||
g_shaders[shader.name] = shader;
|
||
} else {
|
||
//在微信上初始时cc.renderer._forward不存在,需要等引擎初始化完毕才能使用
|
||
cc.game.once(cc.game.EVENT_ENGINE_INITED, function () {
|
||
cc.renderer._forward._programLib.define(shader.name, shader.vert||MVP, shader.frag, def);
|
||
g_shaders[shader.name] = shader;
|
||
});
|
||
}
|
||
}
|
||
|
||
//取Shader的定义
|
||
ShaderMaterial.getShader = function(name) {
|
||
return g_shaders[name];
|
||
};
|
||
|
||
|
||
ShaderMaterial.pushUpdate = function(mat){
|
||
mtArr.push(mat);
|
||
};
|
||
ShaderMaterial.cleanUpdate = function(mat){
|
||
for(var i = 0;i<mtArr.length;i++){
|
||
if(mtArr[i] == mat){
|
||
mtArr.splice(i,1);
|
||
break;
|
||
}
|
||
}
|
||
};
|
||
ShaderMaterial.cleanAll= function(){
|
||
mtArr.length = 0
|
||
}
|
||
ShaderMaterial.update = function(dt){
|
||
for(var i = 0;i<mtArr.length;i++){
|
||
var sconfig = this.getShader(mtArr[i].name);
|
||
sconfig.update(mtArr[i],dt);
|
||
}
|
||
}
|
||
ShaderMaterial.spinevert = '\n \nuniform mat4 viewProj;\n\n#ifdef use2DPos\n attribute vec2 a_position;\n#else\n attribute vec3 a_position;\n#endif\n\nattribute lowp vec4 a_color;\n#ifdef useTint\n attribute lowp vec4 a_color0;\n#endif\n\n#ifdef useModel\n uniform mat4 model;\n#endif\n\nattribute mediump vec2 a_uv0;\nvarying mediump vec2 uv0;\n\nvarying lowp vec4 v_light;\n#ifdef useTint\n varying lowp vec4 v_dark;\n#endif\n\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n\n #ifdef use2DPos\n vec4 pos = mvp * vec4(a_position, 0, 1);\n #else\n vec4 pos = mvp * vec4(a_position, 1);\n #endif\n\n v_light = a_color;\n #ifdef useTint\n v_dark = a_color0;\n #endif\n\n uv0 = a_uv0;\n\n gl_Position = pos;\n}'
|
||
module.exports = ShaderMaterial;
|