https://catlikecoding.com/unity/tutorials/rendering/part-9/
when using a multi-compile directive, unity generates shader variants for all possible combinations.
compiling all permutations can take a lot of time, when many keywords are used.
all these variants are also included in builds, which might be unnecessary.
an alternative is to define a shader feature, instead of multi-compile directive.
the difference is that permutations of shader features are only compiled when needed.
if no material uses a certain keyword, then no shader variants for that keyword are compiled. Unity also checks which keywords are used in builds, only including the necessary shader variants.
上面的这段话已经写的很明白了。经过我的测试:
1、在编辑器下你使用shader_feature,不会有任何的影响。在运行的时候,unity会自动根据EnableKeyword和DisableKeyword去生成对应的变体。
2、however,但是,在打包成exe、apk、ipa时,就不能这么随意了。例如:
Shader "Unlit/NewUnlitShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
[Toggle(_NEAR_FADE)] _NearFade("Near Fade", Float) = 0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma shader_feature _NEAR_FADE
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
#if defined(_NEAR_FADE)
return fixed4(1,0,0,1); //红色
#else
return fixed4(0, 1, 0, 1); //绿色
#endif
}
ENDCG
}
}
}
在编辑下创建一个材质球:
此时,我们没有勾选Near Fade,
查看shader生成的变体:
此时没有生成关键字。
那么C#中我们使用这样的代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
public GameObject cube;
public void OnClickButton()
{
MeshRenderer mr = cube.GetComponent<MeshRenderer>();
mr.material.EnableKeyword("_NEAR_FADE");
Debug.LogError("Enable");
}
public void OnClickButton2()
{
Debug.LogError("Disable");
MeshRenderer mr = cube.GetComponent<MeshRenderer>();
mr.material.DisableKeyword("_NEAR_FADE");
}
}
然后我们打包成exe,结果,无论你执行EnableKeyword还是DisableKeyword都是显示的绿色。
这是为啥呢?
因为我们在编辑器下,没有勾选Near Fade,所以unity也就未给我们生成_NEAR_FADE的变体。在打包成exe之后,也就没有这个变体的shader。所以你开启这个关键字也就不起作用了。
那么怎么办呢?
1、在编辑器下勾选Near Fade,生成对应变体:
这样查看shader变体:
就有FadeNear的变体了。在打包成exe之后,也就能通过开启关键字和关闭关键字了。
2、使用multi_compile
#pragma multi_compile _ _NEAR_FADE
这样无论你勾选材质球上的Fade Near与否,都会生成两个变体:
这样在打包成exe之后,开启和关闭关键字都是起效果的。
所以上面的一段话,建议最好使用multi_compile进行编译,因为不用关心是否有对应的变体。但是与之带来的坏处是,shader多了很多变体。
比如:
将会有8个变体:
所以读者自己斟酌选用吧。