创建 Shader
一个好的Shader总是从一个基本的 diffuse 光照模型开始
因此,我们从 Diffuse 入手开始写 Shader ~
Shader 中的 Diffuse 部分描述从一个表面上向各个方向反射的光
在Unity中创建 Shader 并打开
得到了一个 Unity 的 Shader 模板
Shader "HineNotes/CookbookCh_01/BasicDiffuse" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Lambert
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;
}
ENDCG
}
FallBack "Diffuse"
}
其中 Shader 关键字后的字符串 “Cookbook_01/BasicDiffuse”
为 Shader 名,利用 / 可以为 Shader 设置分级菜单
新建一个 Material, 也起名 BasicDiffuse 把这个Shader赋给它
再把这个 Material 赋给模型,得到的效果就是这样~
这是一个 Surface Shader, Unity 为我们做了很多幕后工作
随着我们深入学习,对于其背后的 Cg 语言,以及 Unity 如何处理背后的底层 GPU 任务,会有更多的了解
有关 Unity 内置的 Cg 函数,参考 Unity安装目录\Editor\Data\CGIncludes
目前值得我们关注的有
UnityCG.cginc, Lighting.cginc, UnityShaderVariables.cginc
我们当前的这个 Shader 用到了这些文件
为 Shader 添加属性
选中刚刚的 BasicDiffuse 材质,在 Inspector 面板中,我们可以看到 Shader 属性 Base (RGB)
也就是 BasicDiffuse 中的这一段
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
定义属性的语法为
Properties { Property [Property …] }
而通常的写法为
_name (“display name”, type) = “defaulttexture” {}
name 为属性名,在Unity中属性名通常以下划线 _开始,display name 为该属性在 Inspector 面板中显示的名字,type 表示属性的类型(具体见下面的表格)赋值符号后面的字符串是默认值,根据不同属性类型来提供,而最后的大括号中则是可选的选项
属性类型 | 描述 |
Range (min, max) | 在 Inspector 面板中创建一个滑条,在最大最小值之间滑动,接受 float 参数 |
Color | 在 Inspector 面板中创建一个颜色面板,可以打开拾色器,获取颜色 float4 = (float,float,float,float) |
2D | 在 Inspector 面板中创建一个贴图面板,允许用户为 Shader 指定贴图对于 2D 和 Cube 类型,默认值可以使用空字符串”“,或“white”,”black”,”gray”,”bump” |
3D | 在 Inspector 面板中创建一个贴图面板,允许用户为 Shader 指定3D贴图 |
Rect | 在 Inspector 面板中创建一个不以2的整数幂为大小的贴图 |
Cube | 在 Inspector 面板中创建一个 cube map 面板,允许用户为 Shader 指定 cube map |
Float | 在 Inspector 面板中创建一个 float 值输入框,但没有滑条 |
Int | 在 Inspector 面板中创建一个 int 值输入框 |
Vector | 在 Inspector 面板中创建一组4个 float 值输入框,可以用来传入方向和颜色 |
将初始 Shader 的标题改为
“HineNotes/CookbookCh_01/UseOfProperties”
其中的属性段改为
Properties {
_Slider ("Slider", Range(0, 10)) = 5
_Float ("Float", Float) = 1.0
_Int ("Int", Int) = 1
_Color ("Clolr", Color) = ( 0.262, 0.612, 1.0, 1.0)
_Vector ("Vector", Vector) = (1.0, 1.0, 1.0, 1.0)
_TwoD("2D", 2D) = "" {}
_Cube("Cube", Cube) = "" {}
_ThreeD("3D", 3D) = "" {}
_MainTex ("Base (RGB)", 2D) = "white" {}
}
存储后切换到 Unity, Unity 会对更改后的 Shder 自动进行编译,我们可以在 Inspector 中看到属性效果
Base( RGB ) 上方就是我们刚刚新添加的属性
对于 Property 部分的介绍,可以参考 Unity 官方文档
http://docs.unity3d.com/Manual/SL-Properties.html
使用 Shader 的属性
想要在 SubShader 块中使用属性,我们需要在其中创建与 Properties 块中同名的属性
将 CGPROGRAM 段修改为
CGPROGRAM
#pragma surface surf Lambert
float4 _Color;
float _Slider;
struct Input {
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o) {
float4 c;
c = pow(_Color, _Slider);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
即可得到由 _Color 和 _Slider 两个属性共同控制的 Shader
其中 _Color 控制漫反射颜色,_Slider 控制强度
最终的 UseOfProperties Shader 如下
Shader "HineNotes/CookbookCh_01/UseOfProperties" {
Properties {
_Slider ("Slider", Range(0, 10)) = 5
_Float ("Float", Float) = 1.0
_Int ("Int", Int) = 1
_Color ("Clolr", Color) = ( 0.262, 0.612, 1.0, 1.0)
_Vector ("Vector", Vector) = (1.0, 1.0, 1.0, 1.0)
_TwoD("2D", 2D) = "" {}
_Cube("Cube", Cube) = "" {}
_ThreeD("3D", 3D) = "" {}
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Lambert
float4 _Color;
float _Slider;
struct Input {
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o) {
float4 c;
c = pow(_Color, _Slider);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
其中 pow(arg1, arg2) 函数是 Cg 语言内置的函数,提供指数运算
关于更多 Cg 内置函数,参考
http://http.developer.nvidia.com/CgTutorial/cg_tutorial_appendix_e.html
经过调整颜色的材质如下