pubgv3/assets/scripts/tools/ShaderMaterial.js
zhuguoqing ff550d5d6a init
2022-05-22 10:32:02 +08:00

415 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;