Unity 材质的创建
我们可以在Unity的菜单栏中选择Assets->Create->Material来创建。当创建了一个材质后,就可以把它赋给一个对象,将材质直接拖拽到Scene视图中的对象上。
Unity Shader的创建
我们可以在Unity的菜单栏中选择Assets->Create->Shader来创建。同时Unity给我们提供了4种Unity Shader模板来供我们选择。
- Standard Surface Shader会产生一个包含了标准光照模型的表面着色器模板。
- Unlit Shader则会产生一个不包含光照(但包含雾效)的基本的顶点/片元着色器。
- Image Effect Shader则为我们实现各种屏幕后处理效果提供了一个基本模板。
- Compute Shader会产生一种特殊的Shader文件,这类Shader利用GPU的并行性来进行一些与常规渲染流水线无关的计算。
Unity Shader的导入
在Project视图中选中某个Unity Shader即可看到该Shader的导入设置面版。
Default Maps可以指定该Unity Shader使用的默认纹理。
Surface shader是否是一个表面着色器。
Fixed function是否是一个固定函数着色器。
Compiled code下拉列表可以让开发者检查该Unity Shader针对不同图像编程接口(列如OpenGL、D3D9、D3D11等)最终编译成的Shader代码。
Render queue使用的渲染队列。
Disable batching是否关闭批处理。
Properties属性列表。
Shader Lab
Unity Shader是Unity为开发者提供的高级层渲染抽象层。Unity希望通过这种方式来让开发者更加轻松的控制渲染。在Unity中所有的Unity Shader都是使用ShaderLab来编写的。
Unity Shader的结构
1.Shader的起名
每个Unity Shader文件的第一行都需要通过Shader语义来指定该Unity Shader的名字。
当为材质选择使用的Unity Shader是,这些名称就会出现在材质面板的下拉列表里。
Shader "Custom/MyShader" {}
那么这个Unity Shader在材质面板中的位置就是
Shader->Custom->MyShader。
2.Properties
Properties语义块中包含了一系列的属性,这些属性将会出现在材质面板中。
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
}
在Unity中这些属性的名字通常由一个下划线开始。显示的名称会出现在材质面板上。我们需要指定每个属性的类型。除此之外,我们还需要给每个属性指定一个默认值,我们第一次把这个Unity Shader赋给某个材质是,材质面板上显示的就是这些默认值。
Shader "Unity Shaders Book/Chapter 3/MyShader" {
Properties {
// Numbers and Sliders
_Int ("Int", Int) = 2
_Float ("Float", Float) = 1.5
_Range("Range", Range(0.0, 5.0)) = 3.0
// Colors and Vectors
_Color ("Color", Color) = (1,1,1,1)
_Vector ("Vector", Vector) = (2, 3, 6, 1)
// Textures
_2D ("2D", 2D) = "" {}
_Cube ("Cube", Cube) = "white" {}
_3D ("3D", 3D) = "black" {}
}
3.SubShader
SubShader中定义了一系列的Pass以及可以选的状态和标签设置。每个Pass定义了一次完整的渲染流程。
-
状态设置
Shader Lab提供了一系列渲染状态的设置指令。当在SubShader块中设置了渲染状态时,将会应用到所有的Pass,如果我们希望这样,可以在Pass语义块中单独的进行设置。
-
SubShader的标签
SubShader的标签是一个键值对,他的键和值都是字符串类型。它们用来告诉Unity的渲染引擎:SubShader我希望怎样以及何时渲染这个对象。
- Pass语义块
Pass{
[Name]
[Tags]
[RenderSetup]
//Other code
}
首先,我们可以在Pass中定义该Pass的名称
Name "MyPassName"
通过这个名字,我们可以使用Shader Lab的UsePass来直接使用其他的Unity Shader中的Pass来提高代码的复用性。在Unity内部会把所有的Pass名称转换为大写字母,所以使用UsePass必须使用大写形式的名字。
UsePass "MyShader/MYPASSNAME"
我们也可以对Pass设置渲染状态,SubShader的渲染状态同样适用于Pass。在Pass中我们还可以使用固定渲染管线着色器。
Pass同样可以设置标签,但是它不同于SubShader的标签,这些标签适用于告诉渲染引擎我们希望如何来渲染物体。
4.Fallback
Fallback用于告诉Unity,“如果上面的所有SubShader在这块显卡上都不能运行,那么就用这个最低级的Shader吧!”
Fallback "Name"
//或者关闭
Fallback off
Unity Shader的形式
在Unity中,我们可以使用下面三种形式来编写Unity Shader。
Shader "MyShader"
ProPerties{
//各种所需的属性
}
SubShader{
//真正意义上的Shader代码
//表面着色器(Surface Shader)或者
//顶点/片元着色器(Vertex/Fragment Shader)或者
//固定函数着色器(Fixed Function Shader)
}
SubShader{
//和上一个一样
}
}
-
表面着色器
表面着色器是Unity自己创造的一种着色器代码类型,但它在背后仍旧要转换成对应的顶点/片元着色器。它存在的价值在于Unity帮我们处理了很多光照细节,让我们不用心焦这些琐事。
从代码中可以看出表面着色器被定义在SubShader语义块内(非Pass语义块)的CGPROFGAM和ENDCG中,CGPROFGAM和ENDCG中的代码时使用CG/HLSL来编写的。。
- 顶点/片元着色器
和表面着色器类似,顶点/片元着色器的代码也需要定义在CGPROFGAM和ENDCG中,不同的是,顶点/片元着色器是写在Pass语义块内,而非SubShader内。
-
固定函数着色器
上面的两种Unity Shader形式都使用了可编程管线,而对一些比较老旧的设备,其GPU支持DirectX 7.0或OpenGL 1.5或OpenGL ES1.1),这时候我们就需要使用固定函数着色器来完成渲染,这些着色器往往只能完成一些非常简单的效果。固定函数着色器是定义在Pass语义块中的,且不需要定义在CGPROFGAM和ENDCG中,完全使用Shader Lab的语法。
-
选择哪种Shader形式
1.如果与各种光源打交道,可以使用表面着色器,但需要担心它在移动平台的表现。
2.如果光照数目非常少,或者需要自定义很多渲染效果,那么请选择顶点/片元着色器。