一 Properties 类型
首先介绍下shader的属性类型,Properties属性会暴露给unity 的 inspactor面板,相当于程序接口
属性的结构:_CG变量名 (“unity可见的变量名”, 属性类型) = 值
例:_Color (“My Color”, Color) = (1, 1, 1, .5)
属性表
类型 | 说明 | 属性值 |
---|---|---|
Int | 整型 | (.1, 2) |
Float | 浮点数 | .5 |
Vector | 四维向量 | (.5, 1 , 1, 0.5) |
Range | 范围1-2.3的浮点数 | (1, 2.3) |
Color | RGBA颜色 | (1,1,1,.5) |
2D | 2d贴图, 2d纹理,默认值可以为一个代表默认tint颜色的字符串,可以是空字符串或者”white”,”black”,”gray”,”bump”中的一个 | ”white”{} |
3D | 3d贴图 | |
Cube | 6面立方贴图 | ”white”{} |
Rect | 矩形贴图 | ”white”{} |
二 Shader Inspactor面板
在材质中指定相关的shader后,点击材质就可以在unity的Inspactor面板中查看相关属性并作设置。
每个Shader属性在Inspactor面板里都有自己的UI表现形式。比如range是个滑杆,vector是四个输入框。但也有无法直接实现的。比如shader里是没有bool类型属性的,所以想要实现toggle这类的功能就需要配合宏和inspactor声明,通过声明一个Float参数来实现一个伪bool值。Inspactor面板会提供相应的toggle UI
Inspactor UI 定义方法
Properties
{
//在inspactor面板中隐藏该属性
[HideInInspector] _WorkflowMode("WorkflowMode", Float) = 1.0
//材质输入框,包含uv输入框
_MainTex ("Texture", 2D) = "white" {}
//该材质不会现实uv设置框
[NoScaleOffset] _MainTex1 ("Texture", 2D) = "white" {}
//该材质需要输入法线贴图
[Normal] _Normal ("Normal", 2D) = "white" {}
//该材质需要高动态范围HDR纹理
[HDR] _HDR ("HDR", 2D) = "white" {}
// 在UI中将一个float/vector属性指定为sRGB值(就像颜色一样),并且可能需要根据使用的颜色空间进行转换
[Gamma] _Vector("Vector", Vector) = (1, 1, 1, 1)
//颜色输入框,分量值为r,g,b,a
_Color ("Target Color", Color) = (1, 1, 1, 1)
//值为0-1的滑杆 Range(0, 1)里面的位数决定滑杆的颗粒度。
_Range ("Range", Range(0, 1)) = 0.01
//指数滑杆
[PowerSlider(3.0)] _Brightness ("Brightness", Range (0.01, 1)) = 0.1
//整数输入框
_Int("Int", Int) = 1
// 四维向量,分量值为x,y,z,w
_Vector("Vector", Vector) = (1, 1, 1, 1)
}
toggle勾选框
shader中没有bool类型,相关功能是靠float类型实现的。值得一提的是在shader中对比两个float是否相等是不可靠的。有可能会发生1.0 != 1.00 != 1/1的情况。所以最好使用相关函数帮助处理。详情请查看shader内置函数。
toggle勾选框
Properties
{
//声明开关
[Toggle] _Toggle("_Toggle", Float) = 1.0
}
fixed4 frag (v2f i) : SV_Target
{
//使用
if(_Toggle){
col = fixed4(1,0,0,1);
}else{
col = fixed4(0,1,0,1);
}
}
MaterialToggle开关勾选框
Material布尔开关勾选框定义一个值为为1or0。该值可以在c#中通过material.setkey来控制
Properties{
[HideInInspector] _WorkflowMode("WorkflowMode", Float) = 1.0
// bool开关
[MaterialToggle] _Toggle("Enable", Float) = 1
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
// 作相应处理
if(_Toggle==0){
col = fixed4(1,0,0,1);
}else{
col = fixed4(0,1,0,1);
}
Material宏开关勾选框
宏开关勾选框。勾选框的值是一个定义好的宏。宏不仅可以在pass中的任意位置使用,还可以在c#中通过material.setkey来控制
//第一步 声明开关
Properties{
//声明ui开关:MaterialToggle,显示名为"Enable",值类型为Float,shader中使用的bool值:_TEX_ON
[MaterialToggle(_TEX_ON)] _Toggle("Enable", Float) = 0
}
//第二步 声明宏
Pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// 声明bool宏:_TEX_ON。 这个_TEX_ON宏不仅可以在pass中使用,还可以在c#中通过Material.setKey使用
#pragma multi_compile _TEX_ON
// 第三步 在pass中的任意处使用
//动态声明变量
#if _TEX_ON
sampler2D _MainTex;
fixed4 _TargetColor;
#endif
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
//动态处理代码片段
#if _TEX_ON
col = fixed4(1,0,0,1);
#else
col = fixed4(0,1,0,1);
#endif
};
下拉框
枚举属性会在inspactor面板下生成下拉框,值为浮点类型
使用unity内置的枚举
使用诸如blend 、cull 的内置属性生成下拉框。返回相应的foat值
Properties
{
// 声明Unity内置的枚举类
[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("Src Blend Mode", Float) = 1
[Enum(UnityEngine.Rendering.BlendMode)] _DstBlend ("Dst Blend Mode", Float) = 1
[Enum(UnityEngine.Rendering.CullMode)] _Cull ("Cull Mode", Float) = 1
[Enum(UnityEngine.Rendering.CompareFunction)] _ZTest ("ZTest", Float) = 0
}
SubShader
{
//使用枚举
Tags { "Queue"="Transparent" "RenderType"="Transparent" }
Blend [_SrcBlend] [_DstBlend]
Cull [_Cull]
ZTest [_ZTest]
ZWrite [_ZWrite]
}
使用自定义枚举
Properties
{
// 自定义枚举的名称数值对,最多支持7对
[Enum(Off, 0, On, 1)] _Cull("ZWrite", Float) = 0
}
SubShader
{
Cull [_Cull]
}
使用关键字枚举
Properties
{
// 声明枚举
// 关键词格式为:"name" + _ + "枚举名称",必须大写。最多支持9个
[KeywordEnum(None, A, B)] _Opt ("Opt mode", Float) = 0
}
SubShader
{
// 声明枚举关键字
#pragma multi_compile _Opt_NONE _Opt_A _Opt_B
fixed4 frag (v2f i) : SV_Target
{
fixed4 secCol = tex2D(_SecondTex, i.uv.zw);
// 使用关键字枚举
#if _Opt_NONE
col += secCol;
#elif _Opt_A
col *= secCol;
#endif
return col;
}
}
使用cs脚本扩展shader面板ui
使用cs脚本也可以控制shader gui
首先建立shader gui的edtor脚本
using System;
using UnityEngine;
using UnityEditor;
public class MyShaderGUI : ShaderGUI
{
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
{
// 渲染shader自带的ui
base.OnGUI(materialEditor, properties);
// 当前关联的材质
Material targetMat = materialEditor.target as Material;
// 定义勾选框变量
bool CS_BOOL = Array.IndexOf(targetMat.shaderKeywords, "CS_BOOL") != -1;
// 发生改变后
EditorGUI.BeginChangeCheck();
CS_BOOL = EditorGUILayout.Toggle("CS_BOOL", CS_BOOL);
if (EditorGUI.EndChangeCheck())
{
//控制shader中的变量
if (CS_BOOL)
targetMat.EnableKeyword("CS_BOOL");
else
targetMat.DisableKeyword("CS_BOOL");
}
}
}
然后在shader中引用edtor脚本和shader变量
Shader "Custom/MyShaderGUI"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
}
SubShader
{
Tags{ "RenderType" = "Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Lambert addshadow
// 创建被cs脚本引用的宏
#pragma shader_feature CS_BOOL
sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
};
void surf(Input IN, inout SurfaceOutput o)
{
half4 c = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
// 使用 脚本宏控制bool变量
#if CS_BOOL
o.Albedo.a = 0;
#endif
}
ENDCG
}
// 关联gui cs脚本
CustomEditor "MyShaderGUI"
}