此笔记用于记录D3D中的HLSL学习过程和重点
============================================================================
HLSL : High Level Shader Language 译为:高级着色语言
HLSL语言的语法类似于C语言
1. 数据类型
HLSL中的数据类型有:标准数据类型、向量、矩阵和复杂数据类型。
———|———————————————————————————————————|
类型 取值
———|———————————————————————————————————|
bool TRUE或FALSE
———|———————————————————————————————————|
int 32位signed整形
———|———————————————————————————————————|
half 16位float数值
———|———————————————————————————————————|
double 64位float数值
———|———————————————————————————————————|
float 32位float数值
———|———————————————————————————————————|
1.1 变量声明
常规声明 float fVar ;
声明时初始化 float fVar = 1.0f ;
数组声明 int iVar[3] = {1 ,2 ,3} ; // 声明一个大小为3的整型数组,并初始化为1 ,2,3.
1.2 类型修饰符
(1) const 常量 其值不可改
此类型修饰符表明一个变量的数值不可被渲染代码修改。例如:
const float fConstant = 2.0f ;
同C语言一样,其声明时徐初始化。
1.3 row_major与col_major
这一对修饰符出现在定义一个矩阵时。将其放在矩阵之前,例如:
row_major float 4x4 WorldMatrix ;
其作用在于指定当前定义的矩阵中的元素,使用行主序还是列主序进行存放(矩阵的行列式)。
示例:
col_major 11 12 13 14
21 22 23 24
31 32 33 34
41 42 43 44
row_major 11 21 31 41
12 22 32 42
13 23 33 43
14 24 34 44
行或者列主序决定了从常量表或从渲染器输入中读取矩阵元素的顺序。
1.4 寄存器类型修饰符
寄存器类型修饰符用于高速编译器变量的作用域和生命期
(1) static
static float fVale = 1.11f ;
具全局作用。Static关键字防止渲染器变量暴露给应用程序。
同C语言一样,在函数内部的变量,其值保存到下一次调用。
(2) extern
extern float4 fExternal ;
与Static相反。其义同C语言关键字。
(3) uniform
uniform float fUniforVal = 3.0f ;
只可使用API方法改变它,且只在两次绘制间改变。
(4) shared
shared修饰全局Shader变量表明它在不同的效果中被共享。
shared float fSharedVal ;
2 向量
(1) 向量类型是一种特殊的数据结构,一个向量可能包含1-4个元素。例如:
注意:数据类型后跟的数字,表明向量的维度。
声明1
bool bVector ; 标量 1个bool型数据
bool1 bVector ; 向量,包含一个bool变量
int1 iVector ; 向量,包含一个int变量
half2 hVector ; 向量,包含两个half变量
float3 fVector ; 向量,包含三个float变量
double4 fVector ; 向量,包含四个double变量
变量声明初始化可以同时进行
bool1 bVector = FALSE ;
int1 iVector = 1 ;
half2 hVector = {0.2 ,0.3} ;
float3 fVector = {0.3f ,0.4f ,0.5f} ;
double4 dVector = {0.2 ,0.3 ,0.4 ,0.5} ;
声明2
当声明向量时,可以在一个尖括号中指定该向量的类型和向量中的元素个数。
vector<bool ,1> bVector = TRUE ;
vector<int ,1> iVector = 1 ;
vector<half ,2> hVector = {0.2 ,0.3 } ;
vector<float ,3> fVector = {1.0f ,2.0f ,3.0f} ;
vector<double ,4> dVector = {1.0 ,2.0 ,3.0 ,4.0} ;
(2)向量元素的存取
一个向量最多包含4个元素。可使用位置x、y、z、w和颜色r、g、b、a进行寻址。
float4 Pos = float4{0.0f ,1.0f ,2.0f ,3.0f} ;
对于向量Pos,使用Pos.z和Pos.b都返回第三个元素,即2.0f。
在一次存取过程中,可以使用一个命名集合获取一个或多个元素,但命名集合不能混用。
如:
float4 Pos = float4(1.0f ,2.0f ,3.0f ,4.0f) ;
float2 Temp ;
Temp = Pos.xy ; // 正确 x y命名相同
Temp = Pos.rg ; // 正确 r g命名相同
Temp = Pos.xb ; // 错误x b命名混用
Temp = Pos.xb ; // 错误x b命名混用
(3)向量元素的混合存取
将读取一个或多个指定的向量元素,称之为混合存取(swizzling).
存取示例:
float4 pos = float4(0 , 0 , 2 ,1) ;
float2 f_2D ;
f_2D = pos.xy ; // 读取两个元素x和y,并赋值给f_2D
f_2D = pos.xz ; // 读取pos的x和z,赋值给f_2D,可以以任何顺序读取元素
f_2D = pos.zx ; // 元素可逆序读取
f_2D = pos.xx ; // 重复读取,元素可以多次读取
f_2D = pos.yy ; // 同上
赋值操作
float4 pos = float4(0 ,0 ,2 ,1) ;
float4 f_4D ;
f_4D = pos ; // 相当于f_4D.x = pos.x ; f_4D.y = pos.y ; f_4D.z = pos.z ;f_4D.w = pos.w ;
f_4D.xz = pos.xz ; // 等同于f_4D.x = pos.x ; f_4D.z = pos.z ;
f_4D.zx = pos.xz ; // 等同于f_4D.z = pos.x ; f_4D.x = pos.z ;
f_4D.xyzw = pos.w ;// 等同于f_4D.x = pos.w ; f_4D.y = pos.y ;f_4D.z = pos.z ;
f_4D.wzyx = pos ; //等同于 f_4D.w = pos.x ; f_4D.z = pos.y ;f_4D.y = pos.z ; f_4D.x = pos.x ;
以下语句无效
f_4D.xx = pos.xy ;
f_4D.xg = pos.rg ;
(4)向量的数学运算
乘法符号为“*“
假设a ,b都为float4类型
float4 v = a * b ;
可视为:
v.x = a.x * b.x ;
v.y = a.y * b.y ;
v.z = a.z * b.z ;
v.w = a.w * b.w ;
此为点乘
3 矩阵
(1)
矩阵是一种以行和列将数据组织起来的数据结构。
矩阵数据类型后紧跟x指明该矩阵的行和列。例如:
int1x1 iMatrix 整形矩阵,1行1列
int2x1 iMatrix 整形矩阵,2行1列
int4x1 iMatrix 整形矩阵,4行1列
int1x4 iMatrix 整形矩阵,1行4列
double1x1 dMatrix double型矩阵,1行1列
double2x2 dMatrix double型矩阵,2行2列
double3x3 dMatrix double型矩阵,3行3列
double4x4 dMatrix double型矩阵,4行4列
HLSL中矩阵的行和列数最大为4,最小为1
矩阵的声明和初始化
float2x2 fMatrix ={0.0f ,0.1f , // 第一行
2.1f ,2.2f} ; // 第二行
matrix <float ,2 ,2> fMatrix ={0.0f ,0.1 // 第一行
2.1f ,2.2f } ; // 第二行
使用关键字matrix声明。这是一个矩阵,其类型为float,行数和列数都为2。
(2) 矩阵元素的存取
矩阵时以行和列将数据组织起来的,可以通过结构体操作符"."来存取其中的数据。
存取方法有两种
1. 0基准行列位置法_m00, _m01, _m02 ,_m03_m10 ,m_11 ,_m12 ,_m13_m20 ,m_21 ,_m22 ,_m23_m30 ,m_31 ,_m32 ,_m332. 1基准行列位置法_11 ,_12 ,_13 ,_14_21 ,_22 ,_23 ,_24_31 ,_32 ,_33 ,_34_41 ,_42 ,_43 ,_44
两种方法中,每个元素的标识都是以下划线开始的,后跟行号和列号。
0基准位置法中,行号和列号前还有一个字母m。
访问示例:
float2x2 fMatrix ={1.0f ,1.1f ,2.0f ,2.1f} ;
float f_1D ;
f_1D = fMatrix._m00 ; // 取行1、列1数据 1.0f
f_1D = fMatrix._m11 ; // 取行2、列2数据 2.1f
f_1D = fMatrix._11 ; // 取行1、列1数据 1.0f
f_1D = fMatrix._22 ; // 取行2,、列2数据 2.1f
访问矩阵多个元素
float2x2 fMatrix ={1.0f ,1.1f ,2.0f ,2.1f} ;
float temp ;
temp = fMatrix._m00_m11 ;
temp = fMatrix._m11_m00 ;
temp = fMatrix._11_22 ;
temp = fMatrix._22_11 ;
(3) 矩阵的混合存取
与向量类似,对矩阵一个以上的元素进行读取或复制操作,称为混合存取(swizzling)。
float4x4 worldMatrix= float4({0 ,0 ,0 ,0} ,{1 ,1 ,1 ,1} ,{2 ,2 ,2 ,2} ,{3 ,3 ,3 ,3}) ;
float4x4 tempMatrix ;
tempMatrix._m00_m11 = worldMatrix._m00_m11 ;
tempMatrix._m00_m11 = worldMatrix._m13_m33 ;
tempMatrix._11_22_33 = worldMatrix._11_22_33 ;
tempMatrix._11_22_33 = worldMatrix._24_23_22 ;
不正确的赋值
tempMatrix._11_m23 = worldMatrix._11_12 ; // 两种基准方式混用
tempMatrix._m00_m00 = worldMatrix.m_00_m11 ; // 不可在一次赋值对一个元素进行两次赋值
(4) 矩阵的数组存取方式
矩阵也可以使用类似访问数组的方式对其进行访问,此时基准为0,不是1.
4X4矩阵,可通过如下索引来访问其中的每个元素
[0][0], [0][1] , [0][2], [0][3]
[1][0], [1][1], [1][2], [1][3]
[2][0], [2][1], [2][2], [2][3],
[3][0], [3][1], [3][2], [3][3],
赋值
float2x2 fMatrix ={1.0f ,1.1.f ,2.0f ,2.1f} ;
float temp ;
temp = fMatrix[0][0] ;
temp = fMatrix[0][1] ;
数组存取方式可以用来存取多元素的向量
float2 temp ;
float2x2 fMatrix ;
temp = fMatrix[0] ; // 将矩阵fMatrix的第一行赋值给向量temp
(5) 矩阵的存放顺序
矩阵中数据的存放方式具体采用行主序还是列主序可以在编译的指定。
使用语句 #pragma pack_matrix(row_major) 或 #pragma pack_matrix(col_major)指定。
列主序效率高于行主序
(6) 矩阵的数学运算
HLSL中,矩阵的数学原酸也是逐元素进行的
float3x3 mat1 ,mat2 ;
float3x3 mat3 = mat1 * mat2 ;
其结果mat3中的值,是两个矩阵mat1和mat2的元素逐个进行相乘后的值
mat3.m00 = mat1._m00 * mat._m00 ;
(7) 复杂数据类型
HLSL支持复杂的数据类型来处理类似采样器(sampler)、结构体(structure)、渲染器(shader)这样的对象
采样器