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.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; }); } } ShaderMaterial.getShader = function(name) { return g_shaders[name]; }; ShaderMaterial.pushUpdate = function(mat){ mtArr.push(mat); }; ShaderMaterial.cleanUpdate = function(mat){ for(var i = 0;i