DirectX 9高层着色语言介绍2——语言基础(1)
语言基础
现在你已经对什么是HLSL顶点和像素着色器以及他们如何与低层汇编着色器相互作用有了了解,我们将讨论一些语言本身的细节。
关键字
关键字是HLSL语言保留的预定义标识符,不能在你的程序中作为标识符使用。标有'*'的关键字不区分大小写。
表2. HLSL语言所保留的关键字
asm* |
bool |
compile |
const |
decl* |
do |
double |
else |
extern |
false |
float |
for |
half |
if |
in |
inline |
inout |
int |
matrix* |
out |
pass* |
pixelshader* |
return |
sampler |
shared |
static |
string* |
struct |
technique* |
texture* |
true |
typedef |
uniform |
vector* |
vertexshader* |
void |
volatile |
while |
下列关键字当前没有使用,不过保留给将来使用:
表3. 当前并没使用的保留关键字
auto |
break |
compile |
const |
char |
class |
case |
catch |
default |
delete |
const_cast |
continue |
explicit |
friend |
dynamic_cast |
enum |
mutable |
namespace |
goto |
long |
private |
protected |
new |
operator |
reinterpret_cast |
short |
public |
register |
static_cast |
switch |
signed |
sizeof |
throw |
try |
template |
this |
typename |
unsigned |
using |
union |
virtual |
数据类型
HLSL支持各种数据类型,从简单的标量到较复杂的类型如向量和矩阵。
标量类型
语言支持以下标量数据类型:
表4. 标量数据类型
bool |
true or false |
int |
32-bit signed integer |
half |
16-bit floating point value |
float |
32-bit floating point value |
double |
64-bit floating point value |
如果你已经熟悉了汇编层编程模型,就会知道并非所有图形处理器天生就支持这些数据类型。因此,整数也许需要由浮点硬件来仿真实现。这意味着并不保证超出整数 (在这些平台上用浮点数表示的)范围的整数运算如期望那样运行。另外,并非所有对象平台支持半精度或双精度值。如果不支持,将使用单精度浮点数来仿真。
向量类型
常常会在HLSL着色器中声明向量变量。声明这些向量有许多方法,包括下列所示:
表5. 向量类型
vector |
一个四维向量; 每一维是浮点类型 |
vector < type, size > |
维数为size的向量; 每一维是type类型 |
声明向量最通常的方法是在类型后跟一个2-4的整数作为名字。例如,要声明一个4元组单精度浮点型,可以如下声明:
float4 fVector0;
float fVector1[4];
vector fVector2;
vector <float, 4> fVector3;
例如,要声明一个3元组布尔型,可以如下声明:
bool3 bVector0;bool bVector1[3];vector <bool, 3> bVector2;
一旦定义了一个向量,就可通过使用类似访问数组的语法或使用一个swizzle来访问其单独的维数。在这个swizzle例子中,维数必须来自于{x. y, z, w}
或{r, g, b, a}
命名空间 (不过不是两者都)。例如:
float value0 = pos[0]; // value0 is 3.0f
float value1 = pos.x; // value1 is 3.0f
float value2 = pos.g; // value2 is 5.0f
float2 vec0 = pos.xy; // vec0 is {3.0f, 5.0f}
float2 vec1 = pos.ry; // INVALID because of bad swizzle
需要注意的是ps_2_0和更低的像素着色器模型并不支持arbitrary swizzles(译者注:Arbitrary swizzle实际上可以看作一个“修正器”(modifier),它用于修改指令和寄存器。其主要功能是减少在一个着色器中使用的指令数目,从而提高效率。)因此,当编译成这些对象时,原本简洁的高层代码(使用swizzle)可能变成相当难理解的二进制汇编代码。你应当熟知这些汇编模型中可以用到的 swizzle。
矩阵类型
HLSL着色器中还常常会用到的变量类型是矩阵,它是二维数组。与标量和向量一样,矩阵由其他一些基本数据类型组成:布尔型,整型,半精度,单精度或双精度浮点型。矩阵可以是任意大小,不过一般都使用4行4列的矩阵。你可以再调用本章开头顶点着色器的例子,在全局范围声明两个4 × 4单精度浮点型矩阵:
float4x4 view_proj_matrix;
float4x4 texture_matrix0;
自然,也可使用其他维数的矩阵。例如,我们用不同方式声明一个3行4列的单精度浮点型矩阵:
float3x4 mat0;
matrix<float, 3, 4> mat1;
和向量一样,可以使用存取数组或结构体/swizzle的语法访问矩阵中的单一元素。例如,要访问矩阵view_proj_matrix的左上角元素可以使用如下面例子中数组下标的方法:
float fValue = view_proj_matrix[0][0];
也有用结构体的语法,定义结构体是由于要访问和swizzling of矩阵元素。从0开始的行列位置,如下:
_m00, _m01, _m02, _m03_m10, _m11, _m12, _m13_m20, _m21, _m22, _m23_m30, _m31, _m32, _m33
从1开始的行列位置,如下:
_11, _12, _13, _14_21, _22, _23, _24_31, _32, _33, _34_41, _42, _43, _44
也可以使用数组符号访问矩阵:例如:
2.0f, 1.0f}; // row 2
float value0 = fMat[0]; // value0 is 3.0f
float value1 = fMat._m00; // value1 is 3.0f
float value2 = fMat._12 // value2 is 5.0f
float value3 = fMat[1][1] // value3 is 1.0f
float2 vec0 = fMat._21_22; // vec0 is {2.0f, 1.0f}
float2 vec1 = fMat[1]; // vec1 is {2.0f, 1.0f}