一、新建一个Shader和一个Material
Shader "Custom/Multi_Compile" {
  SubShader {
    Pass {
    CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag
    #pragma multi_compile MY_multi_1 MY_multi_2 //告诉Unity编译两个不同版本的Shader
    #include "UnityCG.cginc"
    struct vertOut {
      float4 pos:SV_POSITION;
    };
    vertOut vert(appdata_base v)
    {
      vertOut o;
      o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
      return o;
    }
    float4 frag(vertOut i):COLOR
    {
      float4 c = float4(0, 0, 0, 0);
      #ifdef MY_multi_1
      c = float4(0, 1, 0, 0);//输出绿色
      #endif
      #ifdef MY_multi_2
      c = float4(0, 0, 1, 0);//输出蓝色
      #endif
      return c;
    }
    ENDCG
    }
  } 
  FallBack "Diffuse"
}二、新建个Cube, 挂上脚本Multi_Compile.cs
using UnityEngine;
using System.Collections;
public class Multi_Compile : MonoBehaviour {
public bool multi_1;
// Use this for initialization
void Start () {
if (multi_1) {
Shader.EnableKeyword ("MY_multi_1");
Shader.DisableKeyword ("MY_multi_2");
} else {
Shader.EnableKeyword ("MY_multi_2");
Shader.DisableKeyword ("MY_multi_1");
}
}
}
运行效果,当multi_1=true时:

运行效果,当multi_1=false时:

也可以只创建一个关键字,这时候就需要使用__来代替另一个:
#pragma __ TEST_KEY_ON
这样依然会生成两个shader变体,一个什么都没定义,另外一个定义了TEST_KEY_ON。
除了multi_compile之外,还有另外一个类似的指令shader_feature,唯一的区别在于shader_feature不会将不用的shader变体添加到程序中去。shader_feature更适用于材质的关键字,而multi_compile更适用于代码设置的全局关键字。
示例:
#pragma shader_feature TEST_STUFF
Unity自身还内建一些multi_compile的快捷写法:
multi_compile_fwdbase:为基本前向渲染通道编译多个变体,不同的变体可能需要处理不同的光照贴图类型,或者一些使用了主平行光的阴影,而另一些禁用了。(参考Unity渲染管线)
multi_compile_fwdadd:为附加前向渲染通道编译多个变体,不同的变体可能需要处理不同类型的光源——平行光、聚光灯或者点光源,亦或者它们附带cookie纹理的版本。
multi_compile_fwdadd_fullshadows:同上,不过包含了可以让光源拥有实时阴影的功能。
multi_complie_fog:为处理不同的雾效类型(off/linear/exp/exp2)扩展了多个变体。
大部分内建快捷写法会导致许多shader变体,如果某些不需要使用,那么可以使用#pragma skip_variants来忽略它们。
#pragma multi_compile_fwdadd
// will make all variants containing
// "POINT" or "POINT_COOKIE" be skipped
#pragma skip_variants POINT POINT_COOKIE










