利用shader_feature打造最小版本Shader

微信扫一扫,分享到朋友圈

利用shader_feature打造最小版本Shader

这个月终于腾出手为新项目做了一些Shader调整和优化工作,不知不觉就整出一个功能略多的”肥”Shader。 所以我就在思考这么一个事情:如何维护这个Shader,以及如何在运行时尽可能减少无用的消耗。

举俩栗子:

  • 有的材质球里贴了法线贴图,那么就必须计算切空间,但有的材质球只要读取模型的顶点法线就足够了
  • 有的材质球贴了自发光贴图,但是没贴的材质球完全就可以跳过这个tex2D(就算是一张小的黑色也是浪费啊)

后来在官方文档里找到了答案: Making multiple shader program variants 。之前我主要使用的是multi_compile在运行时切换,现在发现shader_feature对应自定义的CustomEditor能很好的完成这个需求。下表为同一个材质球配合不同贴图的参数,以及对应GLES版本的Compiled Code的指令数:

完整版本(vert 43, frag 81)

精简版本(vert 43, frag 50)

Shader部分

#pragma shader_feature _EMISSIONMAP
#if _EMISSIONMAP
sampler2D _EmissionMap;
#endif
fixed4 sgpbr_frag(v2f i) : SV_Target
{
  fixed3 Color = 0;
#if _EMISSIONMAP
  Color += tex2D(_EmissionMap, i.tex).rgb;
#endif
  return fixed4(Color, 1);
}

这里比较好理解,相当于自发光相关的代码都利用_EMISSIONMAP这个宏包起来了。

ps.记得在最后加上CustomEditor “SGPBRInspector”…

C#部分

这里参考了官方的Standard的编辑器代码S tandardShaderGUI.cs。其实和其他inspector一样,最核心的几行就是根据某个属性是否贴了贴图,打开或关闭对应的宏…

override public void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
{
  MaterialProperty emissionMap = ShaderGUI.FindProperty("_EmissionMap", props);
  bool emissionEnabled = emissionMap.textureValue != null;

  Material material = materialEditor.target as Material;
  if (emissionEnabled)
      material.EnableKeyword("_EMISSIONMAP");
  else
      material.DisableKeyword("_EMISSIONMAP");
}

简单粗暴,完成~

微信扫一扫,分享到朋友圈

利用shader_feature打造最小版本Shader

Intersection Impls

上一篇

What podcasters get wrong about advertising

下一篇

你也可能喜欢

利用shader_feature打造最小版本Shader

长按储存图像,分享给朋友