本文以Shader山下(十一)纹理混合中的shader为例子,来介绍一下这些标记。
Shader "Custom/Frag/Blend" {
Properties {
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_BlendTex ("Blend Texture", 2D) = "white" {}
_Opacity ("Blend Opacity", Range(0, 1)) = 1
[Space(50)][Header(MaterialPropertyDrawer)]
[KeywordEnum(None, Add, Multiply, Screen)] _BlendMode ("Blend Mode", Float) = 0
// [Enum(None, 0, Add, 1, Multiply, 2, Screen ,3)] _BlendMode ("Blend Mode", Float) = 0
[Space]
[Toggle] _Invert ("Invert?", Float) = 0
[Toggle(ENABLE_DOUBLE)] _Double ("Double?", Float) = 0
[PowerSlider(3.0)] _Power ("Power", Range(1,1024)) = 1
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
Pass
{
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
uniform sampler2D _MainTex;
sampler2D _BlendTex;
fixed _Opacity;
int _BlendMode;
bool _Invert;
bool _Double;
fixed4 getBlended(fixed4 renderTex, fixed4 blendTex)
{
fixed4 blended;
switch (_BlendMode)
{
case 0:
blended = renderTex;
break;
case 1:
blended = renderTex + blendTex;
break;
case 2:
blended = renderTex * blendTex;
break;
case 3:
blended = (1.0 - ((1.0 - renderTex) * (1.0 - blendTex)));
break;
}
if (_Invert)
{
blended = 1 - blended;
}
if (_Double)
{
blended *= 2;
}
return blended;
}
fixed4 frag(v2f_img i) : COLOR
{
fixed4 renderTex = tex2D(_MainTex, i.uv);
fixed4 blendTex = tex2D(_BlendTex, i.uv);
fixed4 blended = getBlended(renderTex, blendTex);
renderTex = lerp(renderTex, blended, _Opacity);
return renderTex;
}
ENDCG
}
}
FallBack "Diffuse"
}
首先是space标记,可以带参数也可以不带。不带参数时,默认产生如图中Blend Mode与Invert?之间的距离。
然后是Header标记,产生了一行加粗的文本,要注意参数不能加引号,包括后面的一些标记(一个奇怪的设定)。
KeywordEnum是产生一个下拉框
对应数值从0开始保存到_BlendMode里面。修改这些值,就会出现Shader山下(十一)纹理混合中各种不同的混合效果。
并且在这里,它跟被注释掉的哪一行Enum是等同的。而Enum与之区别在于,设置的数值可以不是连续并有序的。
Enum最多支持7对值,而KeywordEnum最多支持9个值。
Toggle会创建一个开关,把bool值保存到_Invert和_Double里面,至于带参数和不带参数之间的区别,我们稍后会讲到。
最后一个PowerSlider只做展示用,它创建了一个指数增长的滑动条,我们可以把值改为512:
你会发现本来应该在中间位置的滑动按钮跑到了右边。
其实还有另外一种形式可以使用,增加下面这些代码:
#pragma shader_feature _INVERT_ON
#pragma shader_feature ENABLE_DOUBLE
#pragma multi_compile _BLENDMODE_NONE _BLENDMODE_ADD _BLENDMODE_MULTIPLY _BLENDMODE_SCREEN
fixed4 getBlendedMacro(fixed4 renderTex, fixed4 blendTex)
{
fixed4 blended;
#if _BLENDMODE_NONE
blended = renderTex;
#elif _BLENDMODE_ADD
blended = renderTex + blendTex;
#elif _BLENDMODE_MULTIPLY
blended = renderTex * blendTex;
#elif _BLENDMODE_SCREEN
blended = (1.0 - ((1.0 - renderTex) * (1.0 - blendTex)));
#endif
#if _INVERT_ON
blended = 1 - blended;
#endif
#if ENABLE_DOUBLE
blended *= 2;
#endif
return blended;
}
并把frag方法里面获取混合色彩值的方法改为:
fixed4 blended = getBlendedMacro(renderTex, blendTex);
其中_INVERT_ON对应于[Toggle] _Invert,命名规则是变量名的大写形式+_ON。
ENABLE_DOUBLE对应于[Toggle(ENABLE_DOUBLE)] _Double ,ENABLE_DOUBLE替换了_DOUBLE_ON(再声明这个宏也是没用的)。
_BLENDMODE_NONE _BLENDMODE_ADD _BLENDMODE_MULTIPLY _BLENDMODE_SCREEN对应于[KeywordEnum(None, Add, Multiply, Screen)] _BlendMode,命名规则为变量名的大写形式+枚举名的大写形式。
而需要注意的是,Enum标记无法使用这些宏。
最后看看材质效果(貌似并没有什么意义)
(Blend Model=Screen,Invert?=On,Double?=On,Power=whatever)