您的位置:首页 > 移动开发 > Unity3D

MaterialPropertyDrawer自定义Unity材质Inspector之关键字枚举(KeywordEnum)

2017-03-03 16:10 525 查看
在这一篇文章中,我们要介绍关键字的枚举类型。

在平时我们书写Shader的过程中都会定义很多的关键字来区分shader的不同用途和功能,当然Unity内置的关键字宏也很多,比如如下代码摘自Lighting.cginc

C#

1234567891011121314151617181920inline fixed4 LightingLambert (SurfaceOutput s, UnityGI gi){ fixed4 c; c = UnityLambertLight (s, gi.light); #if defined(DIRLIGHTMAP_SEPARATE) #ifdef LIGHTMAP_ON c += UnityLambertLight (s, gi.light2); #endif #ifdef DYNAMICLIGHTMAP_ON c += UnityLambertLight (s, gi.light3); #endif #endif #ifdef UNITY_LIGHT_FUNCTION_APPLY_INDIRECT c.rgb += s.Albedo * gi.indirect.diffuse; #endif return c;}
但这简单的几句代码里就定义了 DIRLIGHTMAP_SEPARATE,LIGHTMAP_ON,DYNAMICLIGHTMAP_ON,UNITY_LIGHT_FUNCTION_APPLY_INDIRECT 这4个关键字宏。通常定义这些编译宏的好处就是在最少的代码完成最多的功能,而这些宏是给编译器看的。对于这些宏的开启与关闭,我们最常见的就是直接在代码里面对齐进行关闭,但这样的操作往往是依赖图形工程师或技术美术的支持,普通的美工和其他人是不敢随便动的。那有没有一种方式,提供一个简单的选择界面,让普通美工或策划来控制这些宏的开启和关闭呢?答案当然是有,这就是今天的介绍内容。内容依然来自Unity的官方文档(MaterialPropertyDrawer),pass:官方文档中有不少错误的地方,希望博友注意哦!
1、最简单的一种:Toggle 无参C#

1

2

//当勾选上时,定义_FANCY_ON这个宏

[Toggle]_Fancy("Fancy?",Int)=0

也就是当勾选这个参数时,就表示定义了_FANCY_ON这个宏,在代码中使用时#if _FANCY_ON 或 #if defined(_FANCY_ON) 或 #ifdef _FANCY_ON 结果为真,完整源码如下:

C#

123456789101112131415161718192021222324252627282930313233343536373839404142Shader "MaterialPropertyDrawer/MaterialPropertyDrawerKeywordEnumToggleNull" { Properties { //当勾选上时,定义_FANCY_ON这个宏 [Toggle] _Fancy ("Fancy?", Int) = 0 } SubShader { pass { Tags{ "LightMode"="ForwardBase"} CGPROGRAM #pragma shader_feature _FANCY_ON #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct vertOut{ float4 pos:SV_POSITION; float4 color:COLOR; }; vertOut vert(appdata_base v) { vertOut o = (vertOut)0; o.pos=mul(UNITY_MATRIX_MVP,v.vertex); o.color=float4(1,0,0,1);//红 #if _FANCY_ON o.color=float4(0,1,0,1);//绿 #endif return o; } float4 frag(vertOut i):COLOR { return i.color; } ENDCG }//end pass }}
2、看上去更易理解的Toggle:有参其实这种跟上面的那种是一样的,只是Toggle里面带有宏参数,在Toggle里面定义宏的名字,可以跟外面的不一样C#

1

2

// Will set "ENABLE_FANCY" shader keyword when set

[Toggle(ENABLE_FANCY)]_Fancy("Fancy?",Float)=0

还是上面类似的例子,源码如下:

C#

12345678910111213141516171819202122232425262728293031323334353637Shader "MaterialPropertyDrawer/MaterialPropertyDrawerKeywordEnumToggleNull" { Properties { [Toggle(FANCY_ON)] _Fancy ("Fancy?", Int) = 0 } SubShader { pass{ Tags{ "LightMode"="ForwardBase"} CGPROGRAM #pragma shader_feature FANCY_ON #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include "Lighting.cginc" struct vertOut{ float4 color:COLOR; }; vertOut vert(appdata_base v) { vertOut o = (vertOut)0; o.color=float4(1,0,0,1);//红 #if FANCY_ON o.color=float4(0,1,0,1);//绿 #endif return o; } float4 frag(vertOut i):COLOR { return i.color; } ENDCG }//end pass }}
3、更多状态的关键字定义在上面的示例中都只定义了一个关键字的开和关,那要定义更多状态的关键字要怎么处理呢?使用KeywordEnumC#

1

2

3

// Display a popup with None,Add,Multiply choices.

// Each option will set _OVERLAY_NONE, _OVERLAY_ADD, _OVERLAY_MULTIPLY
shader keywords.

[KeywordEnum(None,Add,Multiply)]_Overlay("Overlay
mode",Float)=0

使用_Overlay一个变量来定义_OVERLAY_NONE,_OVERLAY_ADD, _OVERLAY_MULTIPLY三个关键字的互斥使用。

我们的示例如下:

Shader"MaterialPropertyDrawer/MaterialPropertyDrawerKeywordEnum"{
Properties{
[KeywordEnum(Red,Green,Blue)]_ColorMode("Color Mode",Float)=0
}
SubShader{
pass{
Tags{"LightMode"="ForwardBase"}
CGPROGRAM
#pragma shader_feature _COLORMODE_RED _COLORMODE_GREEN _COLORMODE_BLUE
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"

structvertOut{
float4pos:SV_POSITION;
float4color:COLOR;
};
vertOutvert(appdata_basev)
{
vertOuto=(vertOut)0;
o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
o.color=float4(0,0,0,1);

#if _COLORMODE_RED
o.color=float4(1,0,0,1);

#elif _COLORMODE_GREEN
o.color=float4(0,1,0,1);

#elif _COLORMODE_BLUE
o.color=float4(0,0,1,1);
#endif

returno;
}
float4frag(vertOuti):COLOR
{
returni.color;
}
ENDCG
}//end pass
}
}


这样的使用,就给用户提供了一个下拉框来选择要激活哪一个关键字,如下所示:



这就可以任意切换了,O(∩_∩)O哈哈~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: