利器:HLSL起步教程-完整篇(5)

2019-05-27 21:23

矢量和矩阵类型

矢量和矩阵是把标量组织为1维或2为数组的标准方式。它们通常用来表示3D数据,比如法线和变换矩阵。

矢量是HLSL标准所定义的,由特定标量类型组成的一维数组。默认情况下,一个矢量由4个浮点值组成。如表2-2所示,可以手动定义任何类型的矢量。

表 2 -2 HLSL矢量类型 矢量类型 值

vector

vector

一个包含四个浮点分量的矢量 包含size个type类型的矢量

另外,为了简便,HLSL语言预定义了一组标准矢量类型,方便开发者使用。下面就是这些预定义的矢量类型

typedef vector VECTOR; typedef vector bool# ; typedef vector int# ; typedef vector half# ; typedef vector float# ; typedef vector double# ; (译注:“#”表示分量个数。)

你可能还记得我之前提到过图形硬件是基于矢量的。你看,这里所定义的矢量数据类型恰好与硬件相对应,编译器将把这些数据直接映射为矢量。当你使用少于四个分量的矢量时,编译器将在空闲分量中添加其他变量,以便压缩数据。

简要讨论了矢量之后,你可能想知道如何才能单独访问矢量中的某个分量。有许多方式允许我们单独访问矢量中的分量。下面列出了访问数组分量的几种不同方式。注意对多于四个分量的数组来说,额外的分量只能通过索引访问。

? 使用分量符访问:vector.x , vector.y , vector.z , vector.w ? 使用颜色符访问:vector.r , vector.g , vector.b , vector.a ? 使用索引访问:vector[0], vector[1], vector[2], vector[3]

接下来看看矩阵类型。矩阵是HLSL标准所定义的,由特定标量类型组成的二维数组。默认情况下

分量访问和重组

如前所述,可以像访问结构成员一样来访问矢量和矩阵中的单个分量。这里对矢量和矩阵的访问方式做个小结。

注意,所有下标都必须来自于同一下标集,(比如xyzw,rgba,或者_11到_44),不同下标集之间的元素不能进行混

合,比如不能出现xyrg这样的组合。同一个分量可以出现多次。但对赋值目标来说,则不允许分量重复出现。

tempMatrix._m00_11 = worldMatrix._m00_m11; tempmatrix._11_22_33 = worldMatrix._24_23_22; temp = fMatrix._m00_m11; temp = fMatrix._11_22; 对矩阵来说也是如此。 bgr, yyzw, _12_22_32_42

此外,通过把二到四个分量名串连到一起作为下标来使用,还可以让矢量只包含某几个指定分量,HLSL把这门技术称

为重组。这里就是一些有效的重组实例:

_11, x, r _21 _31 _41

_12, y, g _22 _32 _42

_13, z, b _23 _33 _43

_14, w, a _24 _34 _44

注意

并不是所有硬件都支持所有类型的重组操作。对像素着色器1.x的某些版本来说,部分重组操作是不允许的。编译器可以通过模拟来补偿这些限制,但将带来一定性能损失。

对象类型

? 采样器 ? 纹理 ? 结构体

? 顶点和像素着色器 ? 字符串

字符串指使用ASCII码定义的字符串,它们除了用作注解以外,用处不是太多,这里也不对它进行详细讨论。采样器,

着色器和纹理才是我们所关心的重点部分。

结构的内容将在下一节关于自定义类型的部分详细讨论。

HLSL还定义了一系列范围广泛的对象数据类型。这些类型通常用来呈现非数字数据与复合类型的句柄,典型的例子就

是纹理和结构体。以下是HLSL中所定义的对象类型:

采样器和纹理

HLSL定义了两种数据类型用于在shader中获取纹理信息。纹理本质上就是一个指向硬盘上一系列物理像素信息的句柄。

采样器则是一组纹理采样参数的组合,比如warp mode或者mipmap属性等。

顶点和像素着色器

HLSL定义了两种数据类型用来保存顶点和像素着色器,它们分别是vertexshader和pixelshader。如果使用asm关键字以汇编方式来编写着色程序,则可以把这些程序直接分配给着色器:

vertexshader vs = {

vs_2_0 };

如果使用HLSL,那么则必须通过函数来定义着色器。下面就是使用高级指令定义像素着色器的例子: pixelshader ps = compile ps_2_0 psmain(); decl_position v0 mov oPos, v0

结构及自定义类型

除了前面看到的大量预定义数据类型以外,HLSL也允许开发者创建新类型。自定义类型通常都是结构,它们是由一组

其他(内置或自定义)数据类型,或基于现有类型声明的新类型,组成的对象。

使用关键字struct来定义结构。结构是复合类型,用来把多个数据组合为一个整体。用下面的语法来定义结构: struct [ ID ] { members }

这里是创建结构的一个例子:

struct Circle { };

数组后缀可以跟随在ID之后,允许把数组作为新类型。当声明了一个类型之后,就可以通过ID来对它进行引用。注意array_suffix由一个或多个literal_integer_expression组成,用来表示数组维度。

另外,HLSL还允许使用typedef关键字,为现有类型声明一个新名称。它的语法如下: typedef [ const ] type id [ array_suffix ] [ , id…];

float4 Position; float Radius;

类型转换

在程序设计中,术语类型转换表示把一种数据转变为另一种数据的能力。HLSL支持多种内置类型间的转换。表2-4总结

了内置数据间可能的转换。

表 2 -4 HLSL中的类型转换

转换类型 描述

标量——标量 标量——矢量 标量——矩阵 标量——对象 标量——结构 矢量——标量 矢量——矢量 矢量——矩阵 矢量——对象 矢量——结构

这类转换总是有效的。当把布尔值转换为整型或浮点类型时,false值表示0,true表示1。同样,当把整型或浮点类型转换为布尔值时,0表示false。当把浮点类型转换为整型时,将四舍五入为最接近的整数。 这类转换总是有效的。转换将把标量复制并填充到矢量中。 这类转换总是有效的。转换将把标量复制并填充到矩阵中。 这类转换是是无效的。

这类转换仅当结构中的成员都为数字时才是有效的。转换将把标量复制并填充到结构中。 这类转换总是有效的。转换将复制矢量中的第一个分量,并填充到标量中。

目标矢量容量不大于源矢量时才是有效的。转换只保留最左边(left-most)的分量,截去剩下的分量。 只有当矢量和矩阵一样大时,转换才是有效的。 这类转换总是无效的。

这类转换只有当结构容量不大于矢量,且所有成员都为数字时才是有效的。

矩阵——标量 矩阵——矢量 矩阵——矩阵 矩阵——对象 矩阵——结构 对象——标量 对象——矢量 对象——矩阵 对象——对象 对象——结构 结构——标量 结构——矢量 结构——矩阵 结构——结构

这类转换总是有效的。转换将把矩阵左上角的值填充到标量中。 只有当矢量和矩阵一样大时转换才是有效的。

只有当目标矩阵维度不大于源矩阵时,转换才是有效的。转换将把源矩阵填充到目标矩阵的左上部分,并且丢弃余下数据。 这类转换总是无效的。

只有当结构容量和矩阵一样大,且所有成员都为数字时,转换才是有效的。 这类转换总是无效的。 这类转换总是无效的。 这类转换总是无效的。

只有当两个对象都是同一类型时,转换才是有效的。

只有当结构包含一个以上的成员时,转换才是有效的。结构中成员的类型必须和对象的类型一样。 只有当结构包含一个以上的成员时,转换才是有效的。这个成员必须为数字。

只有当结构容量不小于矢量时,转换才是有效的。它的第一个成员必须为数字,并且等于矢量的大小。 只有当结构容量不小于矩阵时,转换才是有效的。它的第一个成员必须是数字,并且等于矩阵大小。 只有当目标结构容量不大于源结构容量时,转换才是有效的。目标结构和源结构间各自成员的转换也必须是有效的。

定义变量

从语法定义规范可以看出,对变量可以使用多个变量关键字前缀,来告诉编译器如何对待变量。表2-5列出了不同前缀所表示的含义。

HLSL允许把变量定义为常量,输入,输出和临时变量。变量的标准定义语法如下: [static uniform vloatile extern shared ] [ const ] type id [ array_suffix ] [ :semantics ] [ = initializers ] [ annotations ] [ , id …];

表 2 – 5 变量前缀

前缀 描述

static uniform extern volatile shared const

static用于全局变量,表示值为一个内部变量,仅能被当前shader中的代码访问。用于局部变量则表示这个值将在多次调用间驻留。静态变量只能进行一次初始化操作,如果没有使用特定值进行初始化,则默认为0。 使用uniform声明的全局变量表示对整个shader来说,它是一个统一的输入值,即不能在shader运行期间改变。所有非静态全局变量都被认为是统一的。

使用extern声明的全局变量表示对shader来说,它是一个外部输入的值。所有非静态全局变量都被认为是外部的。

这个关键字提示编译器变量将频繁改变。

这个关键字用来修饰非全局变量,告诉编译器这个值将被多个effect共享。 声明为const的变量表示在初始化之后,就不能改变它的值。

声明变量的语法中,需要注意的是semantics部分。语义(semantixs)对HLSL语言来说并没有什么特别含义,它是用来定义

如何把shader中的变量及变量的含义映射到effect framewrok中的。

语义通常用于顶点和像素程序的输入和输出变量,把他们映射为特定含义,比如顶点位置或纹理坐标。举例来说,COLOR0

语义用来告诉编译器,指定变量表示第一种漫反射颜色,并且在大多数shader版本中,将把它放到d0寄存器中。

如语法定义规范所示,允许全局变量包含一个注解(annotation)。注解以 { member_list }的形式出现。Member_list是一个

程序声明的集合,其中每个成员都被初始化为指定字面值。注解只能用来为effect传递元数据,不能在程序中对它进行引用。

我们将在第六章详细讨论语义和注解。

语句和表达式


利器:HLSL起步教程-完整篇(5).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:人教版PEP六年级毕业考试英语模拟试题(2)有答案

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: