《Unity Shader 入门精要读书笔记--初级篇--第五章》
顶点/片元着色器的基本架构
顶点/片元着色器不能说是Unity Shader族群中最闪耀的那一个,但却是最为强大的一个。在Unity中,顶点/片元着色器的英文名称是Unlit Shader
(以下简称为US),尽管拥有着较为复杂原始的代码,但是US的功能可谓是王者级别的存在。除了US之外,在剩余三种着色器中,最常用的当属标准表面着色器Standard Surface Shader
(以下简称SSS)了,而SSS可以实现的,US也全部都能实现。
US与GPU管线的关系相较于SSS看起来更为紧密。在GPU管线中,顶点着色器和片元着色器分属于几何阶段与光栅化阶段;而在US中,顶点着色器由顶点函数实现,片元着色器由片元函数实现。因此,虽然SSS广为人知,但想要真正一窥Unity实时渲染的奥妙与精髓,则需要掌握US的使用说明。
一、 US基本架构:
Shader "ShaderName"{
Properties{
//各种面板属性
}
SubShader{
//显卡A的Subshader
//标签设置
Pass{
//标签设置
CGPRAGMA
#......
#......//各种预编译指令
...
...
ENDCG
}
//一个Pass为一个渲染模块
//其他pass
}
SubShader{}//其他显卡的
//回调方法
Fallback "VertexLit"
}
二、 代码详解
- Shader “ShaderName” 是整个shader文件的开头,告诉Unity本shader的名字和相对位置,如
Shader "Unity Shaders Book/Chapter 5/Simple Shader"
我们可以在如下位置找到这个shader
- properties属性并不是Unity Shader中一个必要的组件,但却能帮助开发者灵活地调整shader属性。任何写在Properties中的属性都会开放在Unity可视化的组件面板“Inspector”中,供开发者随时调整。
如:Properties { _Color("Color Tint",Color) = (1.0,1.0,1.0) }
则:
- Subshader中的Tags设置了属于Subshader中所有pass共享的标签属性,具体的标签设置将会在后序介绍。
- Pass是Shader的灵魂所在,相当于是Shader最小执行单元。
- 在pass内部也可以设置一系列Tags来控制pass的行为,另外,其他所有代码被包含在CGPROGRAM和ENDCG 之中。
-
#include指令设置了该pass所包含的头文件;而 #pragma定义了一系列预编译指令,其中,最为关键的是:
#pragma vertex vert_func_name //声明顶点着色器函数
#pragma fragment frag_func_name //声明片元着色器函数
-
其次,定义用于在顶点着色器和片元着色器之间通信的结构体与变量:
a2v-----application to vertex
v2f------vertex to fragment -
之后定义之前声明的顶点和片元函数,片元函数输出最终调制好的像素颜色(格式为fixed4)
-
- 在 SubShader之后声明备用的着色器,以防先前的subshader不可用。例如:
Fallback "Specular"
- 需要特别注意的是:片元着色器的输入是顶点着色器的输出经过插值之后的结果!
三、 数据类型
ShaderLab与Cg变量类型匹配关系
ShaderLab属性类型 | Cg变量类型 |
---|---|
Color,Vector | float4,half4,fixed4 |
Range,Float | float,half,fixed |
2D | sampler2D |
Cube | samplerCube |
3D | sampler3D |
- 数据宽度:float>half>fixed
四、 语义
语义用于告知系统所声明的变参数的意义。
- a2v:POSITION、NORMAL、TANGENT、TEXCOORDn、COLOR
- v2f:SV_POSITION、COLOR0、COLOR1、TEXCOORD0~7
- fragment:SV_TARGET
渲染平台的差异
DirectX | OpenGL |
---|---|
屏幕坐标系原点位于左上角 | 屏幕坐标系原点位于左下角 |
不允许缺省参数 | 一些情况下允许缺省参数 |
不支持在顶点着色器中使用tex2D | 支持在定点着色器中使用tex2D |
左手坐标系 | 右手坐标系 |
矩阵行优先 | 矩阵列优先 |
裁剪空间z坐标[0,1] | 裁剪空间z坐标[-1,1] |
示例代码
Shader "Unity Shaders Book/Chapter 5/Simple Shader" {
Properties{
_Color("Color Tint",Color) = (1.0,1.0,1.0)
}
SubShader{
Pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
fixed4 _Color;
struct a2v{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct v2f{
float4 pos : SV_POSITION;
fixed3 color : COLOR0;
};
v2f vert(a2v v){
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.color = v.normal*0.5 + fixed3(0.5, 0.5, 0.5);
return o;
}
fixed4 frag(v2f i) : SV_Target{
fixed3 c = i.color;
c *= _Color.rgb;
return fixed4(c,1.0);
}
ENDCG
}
}
}
效果如下: