5.2 简单顶点/片元着色器
Shader "Unity Shaders Book/Chapter 5/Simple Shader" {
Properties {
// 声明一个Color类型的属性
_Color ("Color Tint", Color) = (1.0,1.0,1.0,1.0)
}
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// 在Cg代码中,我们需要定义一个与属性名称和类型都匹配的变量
fixed4 _Color;
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct v2f {
float4 pos : SV_POSITION;
fixed3 color : COLOR0;
};
// float4 vert1(float4 v : POSITION) : SV_POSITION{
// return UnityObjectToClipPos(v.vertex);
// }
v2f vert(a2v v) : SV_POSITION {
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, 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;
// 使用_Color属性来控制输出颜色
c *= _Color.rgb;
return fixed4(c, 1.0);
}
ENDCG
}
}
}
名词解释
pragma:预编译指令。上述代码中的两个pragma指令分别指定了顶点着色器和片元着色器所使用的函数名称,在进行渲染过程中这两个着色器会自动调用这两个函数。
属性:在Properties语义块内可定义属性。若要在Cg代码中访问某个属性,需要在代码块内提前定义和属性相同的数据类型和名称。
语义:在定义结构体和函数时都要为其指定语义,语义表示这个变量的数据的输入来源或者其输出的目的。例如上述注释掉的vert1函数表示v来自当前处理顶点的坐标数据,返回值自动输入到裁剪空间的坐标值。
数据类型:
float4(3):表示一个4维向量,在Cg中默认为列向量
fixed3:数据表示范围为-2.0~+2.0,可以用来表示颜色或者单位向量,一般用half来代替fixed
float4x4:一个4x4的矩阵,默认为行优先填入。
结构体:定义的结构体,其成员变量在指定了语义后在执行过程中会自动填充。
顶点着色器与片元着色器的通信:可以通过一个结构体作为媒介来通信。
表5.1 ShaderLab属性类型和Cg变量类型的匹配关系
uniform关键词是Cg中修饰变量和参数的一种修饰词,它仅仅用于提供一些关于该变量的初始值是如何指定和存储的相关信息(这和其他一些图像编程接口中的uniform关键词的作用不太一样)。在Unity Shader中,uniform关键词是可以省略的。
5.3 Unity内置文件和变量
包含文件
可以像c语言那样包含进外部文件进来,后缀为cginc。例:
CGPROGRAM
// ...
#include "UnityCG.cginc"
// ...
ENDCG
本地有的包含文件位于:D:\unity\2022.3.53f1c1\Editor\Data\CGIncludes
表5.2 Unity中一些常用的包含文件
表5.3 UnityCG.cginc中一些常用的结构体
表5.4 UnityCG.cginc中一些常用的帮助函数
5.4 Unity提供的Cg/HLSL语义
语义semantics:时一个赋给Shader输入和输出的字符串,表达了这个参数的含义,一般情况下用一个语义来描述一个变量时,这个变量到底存储了什么是无所谓的。
系统数值语义(System-value Semantics):一些具有特殊意义的语义,不能随便赋值,一般是系统用于一些渲染阶段的。以SV作为前缀,例如SV_POSITION,对于这类数据,有些平台可以不用加SV前缀,但为了跨平台性最好都加上
表5.5 从应用阶段传递模型数据给顶点着色器时Unity支持的常用语义
其中TEXCOORDn 中n的数目是和Shader Model有关的,例如一般在Shader Model 2(即Unity默认编译到的Shader Model版本)和Shader Model 3中,n 等于8,而在Shader Model 4和Shader Model 5中,n 等于16。通常使用时不超过2。
表5.6 从顶点着色器传递数据给片元着色器时Unity使用的常用语义
5.5 debug工具
visual studio插件:Graphics Debugger,Unity - Manual: Debug shaders with Visual Studio
Unity编辑器的Fram Debugger:Window->Analysis->Frame Debugger
5.6 不同平台渲染差异
官方文档Unity - Manual: Write HLSL for different graphics APIs
Shader语义
使用SV_POSITION 来描述顶点着色器输出的顶点位置
使用SV_Target 来描述片元着色器的输出颜色‘
5.7 注意事项
5.7.3 Shader Target
当shader内需要的运算量过大时,需要指定使用更高级的shader target。
Shader Model:决定了Shader各个特性的能力,等级越高Shader越强大。但最好根据所需要的运算力来指定最低的model。
表5.9 Unity支持的Shader Target
5.7.4 流程控制语句
流程控制语句在gpu中的消耗较大,最好遵循:
分支判断语句中使用的条件变量最好是常数,即在Shader运行过程中不会发生变化;
每个分支中包含的操作指令数尽可能少;
分支的嵌套层数尽可能少。