本书版本为“占红来 译”版,笔记会持续更新,有错误的地方欢迎指正,谢谢!
引言
着色器就是Shader,它是一种特殊的程序,主要用来模拟光照效果。
创建基本的标准着色器
渲染器决定了物体在屏幕上呈现出来的外观,每个3D模型都有一个名为MeshRenderer的渲染器。一个物体只能有一个渲染器,但一个渲染器可以有多种材质。每一种材质就是一个着色器呈现出来的外观,因此着色器也就是3D图像食物链的最后一环。
新建一个标准着色器(也就是漫反射着色器)已有一些基础代码(Cg语言):
///着色器的路径。在给材质指定着色器时,该着色器会出现在指定的下拉菜单中。
Shader "BookShaders/1-2 StandardDiffuse"
{
Properties//制定类型并初始化属性。
{
_Color ("Color", Color) = (1,1,1,1)
//有了这个2D类型,便可在Inspector中添加Texture(纹理)。
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
}
SubShader {
//标签RenderType设置为Opaque,指明渲染的物体不透明。
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM//从这开始,到ENDCG的代码段,为表面着色器代码。
//使用surf()作为表面着色器的输入输出函数,并使用了Standard fullforwardshadows光照模型。
#pragma surface surf Standard fullforwardshadows
//选择模型目标为3.0,2.0能使用 传递的参数 比较少,以防Shader崩溃。
#pragma target 3.0
//创建了与属性变量同名的变量,并声明了他们的数据类型。
//也就创建了surf()访问属性的桥梁。
sampler2D _MainTex;
half _Glossiness;
half _Metallic;
fixed4 _Color;
//输入结构,里面装的是表面函数(surf())的输入参数。
struct Input {
//获取图片的uv坐标的固定格式,即为 图片名前加uv。
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutputStandard o) {
//使用tex2D()对_MainTex的uv_MainTex坐标进行采样,获取颜色值,该采样值再与_Color混合。
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
//输出到Unity的预置输出结构SurfaceOutputStandard的Albedo中。
o.Albedo = c.rgb;
o.Metallic = _Metallic;//金属质感
o.Smoothness = _Glossiness;//光滑度
o.Alpha = c.a;//对透明度的操作无效,因为已指定为不透明物体。
}
ENDCG
}
FallBack "Diffuse"//回滚。如果Pass无法运行,则使用该备用的Shader。
}
这是表面着色器,基于物理基础渲染,通过模拟光照到物体上,来获得真实感。创建好着色器后,需要把它关联到一个材质上,接下来就可以将这个材质指定给物体使用了。
从Unity4到Unity5迁移
如果Unity版本大升级,在源文件升级时,最安全的方式是将包含项目的整个文件夹先拷贝一份或者github。
拟实效果好的着色器需要占用大量的计算资源,所以特效最好用在一些却之不可的地方。Unity5的标准着色器集合了法线映射、透明和反射功能,如果你的材质没有用到反射,那么Unity5是不会计算这一部分的。
给着色器添加属性
Properties代码段中的属性,会显示在Inspector面板中方便开发者调值。属性归属于着色器,而属性的值归属于材质!因为:同一个着色器可用于不同的材质。另外,修改某一个材质的属性值,会影响到所有应用了该材质的物体。
定义属性的语法:
_CircleColor("Circle Color",Color)=(1,1,1,1)
分别对应:
变量名(供Cg用、在Inspector中显示的名字 、类型(也就是类型)、默认值
表面着色器属性类型 | 功能(将在Inspector面板中显示) |
---|---|
Range(min,max) | 创建一个范围从min到max的浮点型属性值(Cg的浮点数不需要在末尾加f) |
Color | 创建一个有4位参数的颜色控件 |
2D | 创建一个纹理样本 |
Float | 创建一个浮点值 |
Vector | 创建4位浮点数构成的向量,一般用于表示方向或颜色 |
在表面着色器中使用属性
绝大部分着色器都从标准着色器开始,然后逐步调整为想要的漫反射组件。
材质是一种资源,所以,运行时的修改也是永久性的。
着色器的错误不会阻止游戏的运行,但都呈现为洋红色的样子。
总结:
- 使用表面着色器方便实现多种效果,而且不用考虑光照模型的具体实现,但方便意味着局限,所以 它仅仅是顶点和片元着色器的一个子集。
- 在手游中少用表面着色器,因为:它是顶点和片元着色器在上一层的一个抽象,它实际上也是顶点和片元着色器,Unity会根据编写的表面着色器代码自动生成为顶点和片元着色器,所以性能浪费大。
- 顶点和片元着色器(和GPU的渲染流水线有关)是GPU拥有的书写方式,在Pass中编写vert和frag函数;
表面着色器是Unity原创的书写方式,在SubShader中的CGPROGRAM和ENDCG区间内编写surf函数。