Unity3D Shader 入门学习
Unity3D 的所有渲染工作离不开着色器.
一些基本的概念
Shader和Material
Shader 着色器其实是一小段程序,它负责将输入的 Mesh
网格. 以指定的方式和输入的贴图或者颜色等组合作用.然后输出.绘图单元可以依据这个输出来将图像绘制到屏幕上
输入的贴图或颜色等,加上对应的shader,以及对Shader的特定参数设置,将这些内容(Shader及输入参数)打包存储在一起,得到的就是一个Material(材质)。
Shader大体可以分为两类:
- 表面着色器(Surface Shader)
- 片段着色器(Fragment Shader)
Shader程序的基本结构
一个普通的着色器结果如下:
属性定义
- 用来指定这段代码有哪些输入.
子着色器
- 子着色器是代码的主体.
- 每一个子着色器中包含一个或者多个的Pass.
- 在计算着色时,平台先选择最优先可以使用的着色器,然后依次运行其中的Pass,然后得到输出的结果
回滚
- 用来处理所有Subshader都不能运行的情况(比如目标设备实在太老,所有Subshader中都有其不支持的特性)。
着色器例子
Shader "Custom/Diffuse Texture" {
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"
}
属性
在Properties{}
中定义着色器属性
每一条属性的定义的语法是这样的
_Name("Display Name", type) = defaultValue[{options}]
- _Name - 属性的名字
- Display Name - 这个字符串将显示在Unity的材质编辑器中作为Shader的使用者可读的内容
- type - 这个属性的类型 , 可能的type所表示的内容有以下几种:
- Color - 一种颜色,由RGBA(红绿蓝和透明度)四个量来定义
- 2D - 一张2的阶数大小(256,512之类)的贴图
- Rect - 一个非2阶数大小的贴图
- Cube - 即Cube map texture(立方体纹理),简单说就是6张有联系的2D贴图的组合,主要用来做反射效果(比如天空盒和动态反射),也会被转换为对应点的采样
- Range(min, max) - 一个介于最小值和最大值之间的浮点数,一般用来当作调整Shader某些特性的参数(比如透明度渲染的截止值可以是从0至1的值等)
- Float - 任意一个浮点数
- Vector - 一个四维数
- defaultValue 定义了这个属性的默认值
- 另外还有一个{option},它只对2D,Rect或者Cube贴图有关,在写输入时我们最少要在贴图之后写一对什么都不含的空白的{}
Tgas
-
表面着色器可以被若干的标签(tags)所修饰,而硬件将通过判定这些标签来决定什么时候调用该着色器。比如我们的例子中SubShader的第一句
Tags { "RenderType"="Opaque" }
告诉了系统应该在渲染非透明物体时调用.在这里Tags其实暗示了你的Shader输出的是什么,如果输出中都是非透明物体,那写在Opaque里;如果想渲染透明或者半透明的像素,那应该写在Transparent中。
LOD
- LOD很简单,它是Level of Detail的缩写
- 这个数值决定了我们能用什么样的Shader。
Shader本体
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
-
CGPROGRAM
这是一个开始标记,表明从这里开始是一段CG程序
最后一行的ENDCG与CGPROGRAM是对应的,表明CG程序到此结束。
-
pragma surface surf Lambert
它声明要写一个表面的shader. 并指定了光照模型
-
sampler2D就是GLSL中的2D贴图的类型
-
对于这段CG程序,要想访问在
Properties
中所定义的变量的话,必须使用和之前变量相同的名字进行声明。 -
UV mapping的作用是将一个2D贴图上的点按照一定规则映射到3D模型上,是3D渲染中最常见的一种顶点处理手段。
struct SurfaceOutput {
half3 Albedo; //像素的颜色
half3 Normal; //像素的法向值
half3 Emission; //像素的发散颜色
half Specular; //像素的镜面高光
half Gloss; //像素的发光强度
half Alpha; //像素的透明度
};
- 这里的half和我们常见float与double类似,都表示浮点数 . 这里的half指的是半精度浮点数,精度最低,运算性能相对比高精度浮点数高一些