Shader targets
‘#pragma target’ 值列表
这是 Unity 使用的着色器模型列表 注意:Unity 的着色器模型与 DirectX 着色器模型和 OpenGL 版本要求类似,但并不完全对应。 仔细阅读说明以确保您了解其中的差异。
值
描述
支持
Equivalent #pragma require values
2.0
相当于 DirectX 着色器模型 2.0。有限数量的算术和纹理指令; 8个内插器; 没有顶点纹理采样; 片段着色器中没有导数; 没有明确的 LOD 纹理采样。
适用于 Unity 支持的所有平台。
N/A
2.5
几乎与 3.0 相同,但只有 8 个插值器,并且没有显式 LOD 纹理采样。
DirectX 11 功能等级 9+OpenGL 3.2+OpenGL ES 2.0VulkanMetal
derivatives
3.0
相当于 DirectX 着色器模型 3.0..
DirectX 11 功能级别 10 +OpenGL 3.2+OpenGL ES 3.0+VulkanMetal 可能适用于某些 OpenGL ES 2.0 设备,具体取决于驱动程序扩展和功能。
Everything in 2.5, plus:interpolators10 samplelod fragcoord
3.5
相当于 OpenGL ES 3.0。
DirectX 11 功能等级 10+OpenGL 3.2+OpenGL ES 3+VulkanMetal
Everything in 3.0, plus:interpolators15 mrt4 integers 2darray instancing
4.0
相当于 DirectX 着色器模型 4.0,但不需要支持 8 个 MRT。
DirectX 11 功能级别 10+OpenGL 3.2+OpenGL ES 3.1+AEPVulkanMetal(如果未定义几何阶段)
Everything in 3.5, plus:geometry
4.5
相当于 OpenGL ES 3.1。
DirectX 11 功能级别 11+OpenGL 4.3+OpenGL ES 3.1VulkanMetal
Everything in 3.5, plus:compute randomwrite msaatex
4.6
相当于 OpenGL 4.1。这是 Mac 支持的最高 OpenGL 级别。
DirectX 11 功能级别 11+OpenGL 4.1+OpenGL ES 3.1+AEPVulkanMetal(如果没有定义几何阶段,也没有定义外壳或域阶段)
Everything in 4.0, plus:cubearray tesshw tessellation msaatex
5.0
相当于 DirectX 着色器模型 5.0,但不需要支持 32 个插值器或立方体贴图数组。
DirectX 11 功能级别 11+OpenGL 4.3+OpenGL ES 3.1+AEPVulkanMetal(如果没有定义几何阶段,也没有定义外壳或域阶段)
Everything in 4.0, plus:compute randomwrite msaatex tesshw tessellation
有关控制台平台的着色器模型支持的信息,请参阅特定于平台的文档。 笔记:
- 在 DirectX 定义中,着色器模型 4.0 包括“mrt8”,着色器模型 5.0 包括“interpolators32”和“cubearray”。 Unity 不包括这些,以实现更广泛的兼容性。 要要求这些功能,请使用明确的
#pragma require指令。 - 如果您使用需要
geometry的目标,但您的着色器未定义几何阶段,Unity 会在编译时从要求列表中删除geometry。 - 如果您使用需要“曲面细分”的目标,但您的着色器未定义外壳或域阶段,Unity 会在编译时从要求列表中删除“曲面细分”。
💡 一般来说默认不写shader target默认采用2.0
数据类型
布尔类型
在c语言中非0即为真0即为假,在Cg中有关键字bool可以声明bool变量
bool bl=true;
同时在Cg中也可以支持三目表达式
col=bl?col:fixed4(0,1,0,1);
在Cg中可以由基础的数据类型构建出向量
例如float可以构建出二阶的向量float2
💡 Cg当中最多可以支持4阶的向量
float2 fl2=(1,0);
float3 fl3=(1,0,1);
float4 fl4=(1,0,0,1);
甚至bool类型也可以按照这样的方式去凑成一个向量
bool2 bl2=(true,false);
bool3 bl3=(true,false,true);
bool4 bl4=(true,false,false,true);
Swizzle操作
可以使用Cg语言中的swizzle操作符(.)将一个向量的成员取出组成一个新的向量。 swizzle操作符被GPU硬件高效支持。 💡 swizzle操作符后接x、y、z、w,分别表示原始向量的第一个、第二个、第三个、第四个元素;swizzle操作符后接 r、g、b和a的含义与前者等同。
不过为了程序的易读性,建议对于表示颜色值的向量,使用swizzle操作符后接r、g、b和a的方式。
举例如下:
float4(a, b, c, d).xyz 等价于 float3(a, b, c)
float4(a, b, c, d).xyy 等价于 float3(a, b, b)
float4(a, b, c, d).wzyx 等价于 float4(d, c, b, a)
float4(a, b, c, d).w 等价于 float d
值得注意的是,Cg语言中**float a 和float1 a是基本等价的**,两者可以进行类型转换;float、bool、half等基本类型声明的变量也可以使用swizzle操作符。例如:
float a = 1.0;
float4 b = a.xxxx;
注意:swizzle操作符只能对结构体和向量使用,不能对数组使用,如果对数组使用swizzle操作符则会出现错误信息:error C1010: expression left of .”x” is not a struct or array(其实个人觉得,提示的错误信息中array换成vector更加合适)。 要从数组中取值必须使用[]符号。例如:
float a[3] = {1.0,1.0,0.0};
float b = a[0];//正确
float c = a.x;//编译会提示错误信息
矩阵
在Cg语言当中,声明一个矩阵的格式采用:[数据类型][行数]x[列数]
矩阵声明
矩阵的初始化
float2x2 M2x2;//声明一个2行2列的矩阵
float2x4 M2x4;//声明一个2行4列的矩阵
//fl2 是一个float类型的2维数组
float2x4 M2x4={fl2,fl2,(1,1,0,0)};
//fl4 是一个float类型的4维数组
float2x4 M2x4={fl4,(1,1,0,0)};
/*声明一个2行2列的矩阵,并初始化
*[0,1]
*[0,1]
*/
float2x2 M2x2={0,1,0,1};
/*声明一个2行4列的矩阵,并初始化
*[0,1,0,1]
*[1,1,0,0]
*/
float2x4 M2x4={(0,1,0,1),(1,1,0,0)};
矩阵取值
矩阵赋值
col=M2x4[0];//(0,1,0,1)
col=M2x4[1];//(1,1,0,0)
M2x4[0]=fl4;
M2x4[1]=(1,1,1,1);
M2x4[1]=(fl3,0);
数组
声明数组
初始化赋值
float arr[4];
float arr[4]={1,0.5,0.5,1};
数组取值
数组赋值
arr[0];//1
arr[1];//0.5
col=float4(arr[0],arr[1],arr[2],arr[3]);
float fl=3;
arr[0]=1;
arr[1]=2;
arr[2]=fl;
结构体
结构体的声明
struct v2f
{
float4 pos;
float2 uv;
};
结构体的使用
v2f o;
o.pos=float4(0,1,0,1);
o.uv=float2(1,0);
#define与typedef
#define
💡 ****#define预处理语句**** #define语句通常有以下两种写法:
#define 标识符 字符串
#define 标识符
//例子
#define NUM 0
#define AddNUM (NUM + 0.5)
#define Add(x, y) (x+y)
#define语句为我们的常量(字符串)分配一个有意义的名称的预处理器指令。可以简单理解为:在前两个例子中,我们用NUM去替代0这个数字,并可以通过NUM来直接使用,而 AddNUM会被定义成(NUM + 0.5),也就是(0.5 + 0.5)。注意这个括号很重要,会导致运算顺序的不同。来看下面这个片元着色器的输出:
fixed4 frag(v2f i) : SV_Target
{
**return** fixed4(NUM, AddNum, 1, 1); //实际上输出的是fixed4(0, 1, 1, 1);
}
而相对与上面两种写法,第三种写法可以定义一个函数。Add(x, y)表示将输入进来的两个数值进行相加并返回最终结果。
fixed4 frag(v2f i) : SV_Target
{
**return** fixed4(NUM, AddNum, Add(0.5, 0.5), 1); //实际上输出的是fixed4(0, 1, (0.5+0.5)=1 , 1);
}
例
#define ONEFL4 float4(1,1,1,1);//定义ONEFL4 值为float4(1,1,1,1);
col=ONEFL4//由于ONEFL4中包含了;分号,所以这里可以不写分号
typeof
💡 可以为某一个类型指定类型别名
typedef float4 FL4;//为float4类型指定别名FL4
使用类型别名
FL4 typeofFl4=FL4(0,1,3,2);
float4 buildinFl4=FL4(1,2,3,4);
FL4 typeFl4=float4(4,3,2,1);


...