一、新建一个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