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、ba的含义与前者等同。

不过为了程序的易读性,建议对于表示颜色值的向量,使用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);