我看上面修改了engine的代码,那就要自己加载引擎包了,有没有非侵入的方法呢?能不能就是利用现有的api来完成precompile。本人纯萌新,我网上搜了相关的内容都是unity的,不知道cocos咋整。
小游戏这里不用改引擎也可以的,直接调shader.gpuShader的属性即可,这个属性是现有的API。
name 和 define 建议自己加个hook,在游戏运行的时候收集下来存json使用。
原生的要改引擎加接口去显式调用,如果还按直接调gfxShader的getter的方式,在某些backend上无效。
另外里面那个defines.precompile = true 你可以不用加,这个是我内部的一个标志使用。
赞赞赞



大佬,我还有个疑惑,有关于着色器缓存的,我翻了一下文档和源码,以及查看微信小游戏gamecache,都没有找到shader cache,是官方没有做吗?还有就是小游戏做这个的必要性,看网上说的,shader cache非常占空间。
哈哈哈,这张图好眼熟啊 
引擎肯定是有处理的,但是处理的时机是第一次渲染时。这就导致某些物体在第一次出现在场景的时候由于编译导致掉帧,所以我这个方案是将这个过程提前,比如说提前到加载界面,保证后续的流畅性
1.官方没有shader cache,我们这个方式也不算shader cache,顶多是记录下来shader 的定义组合,在合适的loading时间进行初始化。所以不占用多少空间,反而占用loading的时间。
2.小游戏做这个的必要性,主要是看你的项目,有没有大量使用shader变体的地方,如果按引擎功能上来说,3D特效就是这种功能。在引擎编译变体的时候,会出现明显的卡顿,如果你有很多变体,但不想要卡顿,那么就用这个方法预编译,把卡顿集中到loading中。
3.说一个有趣的事情,官方其实也有一个类似预编译的东西,就是shader资源面板上的Precompile Combinations,但是这个功能它有几个问题/bug,导致不可用。
a) 这个预编译是发生在EffectAsset加载的时候,如果你不做这个shader资源的预加载,用到了这个shader的时候,会卡很大一下。
b)这个预编译是手工选择的,远不如游戏内收集的准确,往往会编译很多无效的组合,特别是特效这种有很多组合的时候,如果你都勾上就是指数级别的组合了。
c) 这个预编译有大bug,在某些backend上没效果。这个预编译会调用getGFXShader来创建cocos里面的Shader类对象。但是在某些backend下(例如原生的GLES3),创建该Shader对象并不意味着编译,而是只存了信息/源码进去,这个shader设置到管线中使用才实际编译(cmdFuncGLES3CreateShader),这一点查看一下代码就知道了。
所以我们才会创建自己的一套预编译机制,第c点也是自定义原生引擎加入tryCompile接口的原因。当然如果有unity的那种shader variation收集和预编译是最好的。
感谢楼主分享,如果我创建一个n个Cube,把场景用到的所有材质放到对应Cube上,隐藏到地面以下,保证用户进入场景后所有cube在相机范围内,能用这种办法强行触发shader编译吗
可以的,这是最简单的方式
感恩大佬回复 这就试试
这些坑还没发啊,要发霉了
我也是在加载页面放了一个panel,然后每两帧换一个材质,强行触发编译
感觉第一次场景实例化复杂模型的时候会卡顿,之前以为是shader预编译的问题,但是强制显示材质以后还是第一次卡顿

你可以在这个代码加个时间打印log,看看卡顿的时间是不是触发了shader编译,编译的时间是多少
并不是强制显示后就一定会编译,还有可能被裁减等情况
感谢大佬 了解了
