HLSL着色器由变量和函数组成,函数又由语句组成,它的语法和c++十分相似
变量
HLSL变量类似于c++中的变量,具有命名限制、取决于声明它们的位置的范围属性、标准数据类型,不同的是,定义其他数据类型用以提高使用3d数据的性能
声明模板
[Storage_Class] [Type_Modifier] Type Name [Index] [: Semantic] [: Packoffset] [:Register];
-
Storage_Class(存储类型)
-
用于为编译器提供关于变量范围和生存期的提示
-
可以按任意顺序指定修饰符
-
value description extern 与c++一样,将全局变量标记为着色器的外部输入 nointerpolation 将顶点着色器的输出传递给像素着色器之前,不要对它们进行插值 shared 标记一个用于在效果之间共享的变量; 这是对编译器的提示 groupshared 为计算着色器的线程组共享内存标记一个变量 static 与c++一样,标记一个局部变量,使其初始化一次。若声明不对其进行显式初始化,将默认初始化为0 volatile 与c++一样,标记经常更改的变量;仅适用于局部变量 uniform 标记一个变量,该变量在整个着色器执行过程中是恒定的。此值可在c++应用层改变,但在着色器执行时,其值不变
uniform变量在着色器程序外进行初始化
-
-
Type_Modifier(类型修饰符)
- 若未指定类型修饰符,则编译器使用 column _ main 作为
默认值
value description const 与c++一样,标记一个不能被着色器更改的变量,必须在变量声明中初始化 row_major 标记一个变量,该变量在一行中存储4个组件 column_major 标记一个变量,该变量在一列中存储4个组件,以优化矩阵运算 - 若未指定类型修饰符,则编译器使用 column _ main 作为
-
Type
HLSL支持的内部数据类型
-
标量类型
类型名 含义 bool ture or false int 32位有符号整数 uint 32位无符号整数 dword 32位无符号整数 half 半数据类型,16位浮点值。仅用于语言兼容性
半数据类型不能用于统一的全局变量(若有需要,请使用/Gec 标志)float 32位浮点值 double 64位浮点值。不能用于流的输入和输出,请使用一对uint数据类型,再使用 asuint 函数将每个 double 打包到这对 uint 中,并使用 asdouble()将这对 uint 解压至 double 中 min16float 最小16位浮点值 min10float 最小10位浮点值 min16int 最小16位有符号整数 min12int 最小12位有符号整数 min16uint 最小16位无符号整数 string ASCII 字符串。没有接受字符串的操作或状态,但是可以查询字符串参数和注释 -
向量类型
-
向量类型由两部分组成,一个向量的每个分量必须具有相同的类型
-
标量类型
-
分量的数量,在1-4间
如:
向量类型 含义 float2 2d向量,每个分量都是float类型 float3 3d向量 float4 4d向量 -
-
初始化向量
-
以类似数组或构造函数的语法来初始化向量
float3 v = {1.0f, 2.0f, 3.0f}; float2 w = float(x,y); float4 u = float4(w, 3.0f, 4,0f)
-
-
访问分量
-
以数组下表语法来访问
vec[i] = 1.0f;
-
以规定的分量名x、y、z、w、r、g、b、a像访问结构体成员一样来访问分量
vec.x = vec.r = 1.0f;
-
-
重组
(swizzleing)将向量u的分量复制到向量v的分量,可以乱序方式进行
float4 u = {1.0f, 2.0f, 3.0f, 4.0f}; float4 v = {0.0f, 0.0f, 5.0f, 6.0f}; v = u.wyyx; //v = {4.0f, 2.0f, 2.0f, 1.0f}
-
-
矩阵类型
-
包含1-16个分量,每个分量类型必须相同
-
矩阵类型由三部分组成
- 标量类型
- 行数,1-4的正整数
- 列数,1-4的正整数
如:
类型名称 含义 float2x2 2x2矩阵,每个元素类型都为float float3x3 3x3矩阵 float4x4 4x4矩阵 float3x4 3x4矩阵
-
-
访问
-
以二维数组的双下标进行访问
M[i][j] = value;
-
以访问结构体成员的方式进行访问
//以1作为起始值的索引 M._11 = M._12 = M._13 = M._14 = 0.0f; M._41 = M._42 = M._43 = M._44 = 0.0f; //以0作为基准值的索引 M._m00 = M._m01 = M._m02 = M._m03 = 0.0f; M._m30 = M._m31 = M._m32 = M._m33 = 0.0f;
-
引用矩阵中特定的行向量。以数组的单下标实现
float3 row = M[i];
-
-
-
struct
与c++的struct定义方式基本相同,区别在于HLSL的struct不含有成员函数
-
typedef
与c++的typedef功能完全相同
typedef float3 point;
-
array(数组)
与c++相同
half p[3]; float M[4][4];
-
-
Semantic(语义)
-
可选参数,语义是附加在着色器输入或输出上的字符串,它传递有关参数预期用途的信息
-
由编译器用于链接着色器输入和输出
-
在着色器阶段之间传递的所有变量都需要语义
-
一般来说,流水线阶段之间传递的数据是完全通用的,系统不进行唯一的解释
-
System-Value Semantic(系统值语义)
-
所有系统值都以 SV _ 前缀开头,如SV _ POSITION
-
为什么需要系统值?
因为系统值用于指出输入输出变量的意图
-
系统值在管道的其他部分也是有效的
-
如:
顶点着色器语义
input description type COLOR[n] 镜面反射颜色 float4 NORMAL[n] 法线向量 float4 POSITION[n] 空间中的顶点位置 float4 TEXCOORD[n] 纹理坐标 float4 PSIZE[n] 点大小 float Output Description Type COLOR[n] 漫反射或镜面反射颜色 float4 POSITION[n] 齐次空间中顶点的位置 float4 PSIZE 点大小 float 像素着色器语义
Input Description Type COLOR[n] 漫反射或镜面反射颜色 float4 TEXCOORD[n] 纹理坐标 float4 VPOS 屏幕空间中的像素位置(x,y) float2 Output Description Type COLOR[n] 输出颜色 float4 DEPTH[n] 输出深度 float -
-
Packoffset
可选参数,用于手动打包着色器常量
-
Register
可选参数,用于手动将着色器变量分配给特定寄存器
强制类型转换
HLSL中的强制类型转换与c相同
float f = 5.0f;
float4x4 m = (float4x4)f; //将标量复制给m中每个元素
float3 n = float3(...);
float3 v = 2.0f * n - 1.0f; //等同于 float3 v = 2.0f * n - float3(1.0f, 1.0f, 1.0f);
常用关键字
asm, bool, break, case, class, compile, const, continue, default, do, double, dword,
else, extern, false, true, float, for, half, if, in, inline, inout, int, matrix, namespace, NULL, out, pass, return, register, sampler, shared, static, string, struct, switch, typedef, uint, uniform, unsigned, vector, vertexshader, void, volatile, while,
texture, technique, pixelshader, discard
运算符
HLSL的运算符规则与c++基本相同,除了以下几种
取模运算符%
可用于整数和浮点数,且操作数的正负号相同- HLSL的部分运算以分量为基准
- 对于二元运算
- 若操作符左右操作数
维度
不同,维度较小的变量类型被转换为维度较大的变量类型 - 若操作符左右操作数
类型
不同,低精度变量被转换为高精度变量
- 若操作符左右操作数
如:
//乘法
float4x4 A;
float4x4 B;
A*B; //分量式乘法
mul(A,B); //矩阵乘法
//比较运算符
float4 u = {1.0f, 0.0f, -3.0f, 1.0f};
float4 v = {-4.0f, 0.0f, 1.0f, 1.0f};
float4 b = (u == v); // b = (false, true, false, true)
控制流
HLSL支持的控制流与c++相似.以下语句语法与c++完全相同
- return
- if & if...else
- while
- for
- do...while
- break
- continue
- switch
函数
-
HLSL中函数的属性
-
函数采用类c++语法
-
参数只能按值传递
-
不支持递归
-
只有内联函数
-
与c++相较下,多了in、out、inout关键字
-
in:目标函数执行前,此修饰符所指定的参数应从调用此函数的程序中复制有输入的数据.所有参数默认为in
-
out:目标函数返回时,此修饰符所指定的参数应当已经复制该函数中的最后计算结果
-
因为HLSL没有引用和指针,需要用out返回数值
-
若一个参数被out修饰,此参数只能用于输出数据,不可用于输入数据,也就是说不能被复制
void func(float x, out float y) { y = x * x; }
-
inout:表示参数兼有in和out属性
-
-
-
-
内置函数
常用函数如下
函数 描述 abs(x) 返回|x| length(v) 返回向量v的长度 cos(x) 返回x的余弦值,x单位为弧度 clamp(x, a, b) 将x限制在[a,b]内,并返回结果 saturate(x) 返回clamp(x, 0.0, 1.0) clip(x) 仅用于像素着色器。若x < 0,就将当前像素从后续流程中丢弃 cross(u, v) 返回u和v的叉积 dot(u, v) 返回u和v的点积 ddx(p) 估算屏幕空间中的偏导数δp/δx
确定屏幕空间x轴上,相邻像素间某属性值p的变化量ddy(p) 估算屏幕空间中的偏导数δp/δy
确定屏幕空间y轴上,相邻像素间某属性值p的变化量determinant(m) 返回矩阵的行列式 distance(u,v) 返回点u和点v间的距离 floor(x) 返回≤x的最大整数 ceil(x) 返回≥x的最小整数 frac(x) 返回目标浮点数的小数部分 lerp(u, v, t) 基于参数t∈[0, 1],在u、v间进行线性插值 log(x) 返回ln(x) log10(x) 返回log10(x) log2(x) 返回log2(x) max(x, y) 返回x,y中的较大者 min(x, y) 返回x,y中的较小者 mul(m, n) 返回矩阵乘积mn normalize(v) 对v进行规范化处理 pow(b, n) 返回b^n radians(x) 将x从角度转化为弧度 degrees(x) 将x从弧度转化为角度 sqrt(x) 返回根号x rsqrt(x) 返回1/根号x reflect(v, n) 根据表面法线n与入射向量v,计算反射向量 refract(v, n, eta) 根据表面法线n与入射向量v,计算反射向量及两种材质的折射率之比eta来计算折射向量 transpose(m) 返回矩阵m的转置矩阵 Texture2D::Sample(X, texC) 根据SamplerState对象S与2D纹理坐标texC,返回2D纹理图中相应的颜色数据 Texture2D::SampleLevel(S, texC, mipLevel) 根据SamplerState对象S、2D纹理坐标texC和mipmap层级mipLevel,从2D纹理图中返回相应的颜色数据 TextureCube::Sample(S, V) 根据SamplerState对象S、3D查找向量v来返回立方体图中相应的颜色数据 Texture2DArray::Sample(S, texC) 根据SamplerState对象S、3D纹理坐标texC,返回2D纹理数组中相应的颜色 -
常量缓冲区的封装规则
HLSL中,常量缓冲区会以padding(补齐填充)的方式,将其中的元素都包装在4D向量。但
一个单独的元素不能被分开并横跨两个4D向量
cbuffer cb : register(b0) { float3 Pos; float3 Dir; } //封装如下 vector 1 : (Pos.x, Pos.y, Pos.z, empty) vector 2 : (Dir.x, Dir.y, Dir.z, empty)
reference
High-level shader language (HLSL) - Win32 apps | Microsoft Learn
Directx12 3D 游戏开发实战
标签:返回,HLSL,基础,c++,语法,._,float4,着色器,向量 From: https://www.cnblogs.com/chenglixue/p/17074041.html