[LayaAirIDE 2.0]Shader预编译解决方案

 
ver2.5.0 
 

{laya.d3.js} 源码分析
BaseRender.material : Laya.Material
material._shaderValues  :  Laya.ShaderData
material._shaderValues._defineDatas :Laya.DefineDatas 
参考接口
_render(context) {
    ...
    this._material._shaderValues._defineDatas.cloneTo(comDef);
    var shader = context.shader = this._material._shader.getSubShaderAt(0)._passes[0].withCompile(comDef);
    ...

Laya.ShaderPass -> withCompile(compileDefine) { 
    if (Shader3D.debugMode)//开启debug编译shader时生成打印shader参数
        this._addDebugShaderVariantCollection(compileDefine);
        

debugShader : Laya.Shader
debugShader : Laya.SubShader 
Laya.ShaderPass -> _addDebugShaderVariantCollection(compileDefine) { 
    var dbugShaderVariantInfo = Shader3D._debugShaderVariantInfo;
    var debugSubShader = this._owner;
    var debugShader = debugSubShader._owner;
    var deugDefines = ShaderPass._debugDefineString;
    //将defineDatas抓换成宏定义数组
    Shader3D._getNamesByDefineData(compileDefine, deugDefines);
    if (!Config3D._config._multiLighting) {
        var index = deugDefines.indexOf("LEGACYSINGLELIGHTING");
        (index !== -1) && (deugDefines.splice(index, 1));
    }
        
    //保存参数
    if (dbugShaderVariantInfo)
        dbugShaderVariantInfo.setValue(debugShader, debugShader._subShaders.indexOf(debugSubShader), debugSubShader._passes.indexOf(this), deugDefines);
    else
        Shader3D._debugShaderVariantInfo = dbugShaderVariantInfo = new ShaderVariant(debugShader, debugShader._subShaders.indexOf(debugSubShader), debugSubShader._passes.indexOf(this), deugDefines);
        Shader3D.debugShaderVariantCollection.add(dbugShaderVariantInfo);   

Laya预编译 shader 接口
Laya.Shader3D.compileShaderByDefineNames(shaderName:string,subShaderIndex:number,passIndex:number,defines:Laya.):void; 
material : BaseRender.material
shader : material._shader
shaderName :shader.name
subShaders : shader._subShaders : Laya.SubShader 
subShaderIndex : shader._subShaders.indexOf(subShader) : number
shaderPassses : subShader._passes : Laya.ShaderPass
passIndex : subShader._passes.indexOf(shaderPass) : number
defineNames :宏定义名称 
static compileShaderByDefineNames(shaderName, subShaderIndex, passIndex, defineNames) {
    var shader = Shader3D.find(shaderName);
    if (shader) {
        var subShader = shader.getSubShaderAt(subShaderIndex);
        if (subShader) {
            var pass = subShader._passes[passIndex];
            if (pass) {
                var compileDefineDatas = Shader3D._compileDefineDatas;
                compileDefineDatas.clear();
                for (var i = 0, n = defineNames.length; i < n; i++)
                    //将宏定义名称转换为  Laya.DefineDatas
                    compileDefineDatas.add(Shader3D.getDefineByName(defineNames));
                (Config3D._config._multiLighting) || (compileDefineDatas.add(Shader3D.SHADERDEFINE_LEGACYSINGALLIGHTING));
                //预编译shader  compileDefineDatas : Laya.DefineDatas
                pass.withCompile(compileDefineDatas);
            }
            else {
                console.warn("Shader3D: unknown passIndex.");
            }
        }
        else {
            
            console.warn("Shader3D: unknown subShaderIndex.");
            
            }
        }
            else {
                console.warn("Shader3D: unknown shader name.");
            }
        }
}

===============================================
方案1:官方接口编译
   
    private $compileShader(model: Laya.Sprite3D) {
        if (model instanceof Laya.ShuriKenParticle3D) {
            var shuriKenParticle3D: Laya.ShuriKenParticle3D = model as Laya.ShuriKenParticle3D;
            var render: Laya.ShurikenParticleRenderer = shuriKenParticle3D.particleRenderer;
            var materials: Array<Laya.Material> = render.materials;
            for (var i: number = 0; i < materials.length; i++) {
                var mater: Laya.Material = materials[i] as Laya.Material;
                let defineDatas: Laya.DefineDatas = mater._defineDatas;
                var deugDefines = Laya.ShaderPass["_debugDefineString"];
                if (!deugDefines) { deugDefines = ; }
                //将defineDatas转换成宏定义数组
                Laya.Shader3D["_getNamesByDefineData"](defineDatas, deugDefines);
                if (!Config3D["_config"] && Config3D["_config"]["_multiLighting"]) {
                    var index = deugDefines.indexOf("LEGACYSINGLELIGHTING");
                    (index !== -1) && (deugDefines.splice(index, 1));
                }
                let shader: Laya.Shader3D = mater["_shader"];
                if (!shader) continue;
                let subShaders: Laya.SubShader[] = shader["_subShaders"];
                if (subShaders && subShaders.length > 0) {
                    for (let j = 0; j< subShaders.length; j++) {
                        let subShader: Laya.SubShader = subShaders[i];
                        let passes: Laya.ShaderPass[] = subShader["_passes"];
                        if (passes && passes.length > 0) {
                            for (let k = 0; k < passes.length; k++) {
                                let pass: Laya.ShaderPass = passes[i];
                                pass && Laya.Shader3D.compileShaderByDefineNames(shader.name, j, k, deugDefines);
                            }
                        }
                    }
                }
            }
        }
        //递归获取子对象
        if (model.numChildren) {
            let len: number = model.numChildren;
            for (var i: number = 0; i < len; i++) {
                this.$compileShader(model.getChildAt(i) as Laya.Sprite3D);
            }
        }
    }
[/i][/i][/i]
 
 
===============================================
[i][i][i]方案2:绕过宏定义名称转换直接编译
    private $compileShader2(model: Laya.Sprite3D) {
        if (model instanceof Laya.ShuriKenParticle3D) {
            var shuriKenParticle3D: Laya.ShuriKenParticle3D = model as Laya.ShuriKenParticle3D;
            var render: Laya.ShurikenParticleRenderer = shuriKenParticle3D.particleRenderer;
            var materials: Array<Laya.Material> = render.materials;
            for (var i: number = 0; i < materials.length; i++) {
                var mater: Laya.Material = materials[i] as Laya.Material;
                let defineDatas: Laya.DefineDatas = mater._defineDatas;
                let shader: Laya.Shader3D = mater["_shader"];
                if (!shader) continue;
                let subShaders: Laya.SubShader[] = shader["_subShaders"];
                if (!subShaders || subShaders.length <= 0) continue;
                subShaders.forEach((subShader: Laya.SubShader) => {
                    if (subShader) {
                        let passes: Laya.ShaderPass[] = subShader["_passes"];
                        if (passes && passes.length > 0) {
                            passes.forEach((pass: Laya.ShaderPass) => { pass && pass["withCompile"](defineDatas); })
                        }
                    }
                });
            }
        }
        //递归获取子对象
        if (model.numChildren) {
            let len: number = model.numChildren;
            for (var i: number = 0; i < len; i++) {
                this.$compileShader(model.getChildAt(i) as Laya.Sprite3D);
            }
        }
    }
 
[/i][/i][/i][/i]
已邀请:

要回复问题请先

商务合作
商务合作