HLSL
GLSL
Cg HLSL
RenderMonkey
HLSL(High Level Shader Language) 高级着色语言
在本章我们描述高级着色语言(HLSL),我们使用顶点和像素覆盖三章。简要的,顶点和像素是小的自定义程序我们写的,在图形卡的GPU(图形处理单元)执行,取代固定函数管线的一部分。使用我们自定义的程序取代原来固定的部分,我们得到一饿很灵活的图形效果。我们不在受到固定的限制。
为了写着色程序,我们需要用语言来写。在Dx8.x 中,着色器使用低级着色语言写。幸运的,我们不再使用低级着色语言,在Dx9提供了高级着色语言,我们可以写着色器。使用HLSL代替同样的高级使用,像C++一样,覆盖汇编语言写应用程序 :
增加了生产力
改进了可读性
对编译器,更多不在,产生更多的比手工汇编工有效率的代码。
使用HLSL编译器,我们可而已编译我们的代码产生各种版本。使用低级着色语言我们不得不为每个版本都写一份。
HLSL也非常类似于C/C++的语言,因此非常容易学习。
最后,你将需要ReF设备来运行你的了例子,如果你的图形卡不致辞后顶点和像素着。使用REF设备运行的会非常慢,但是他们仍然可以产生正确的结果,允许我们检验我们代码的正确性。
注意:顶点着色器可以使用软件顶点处理-D3DCREATE_SOFTWARE_VERTEXPROCESSING.
目标
学习写和编译一饿HLSL着色器
学习怎样让应用程序和着色器通信
熟悉它的语法,类型和内置的函数HLSL
写一饿HLSL着色器
全局对象
首先我们定义了两个全局变量的实例:
matrix ViewProjMatrix;
vector Blue = {0.0f,0.0f,1.0f,1.0f};
第一个变量,ViewProjMatrix,是一个矩阵类型,在HLSL内部构造为4x4的矩阵烈性。这个类型存储视图和投影矩阵,它描述两个转换。这种方式我们不得不通过操作一个矩阵向量来取代两个步骤。注意我们初始化这个变量,还没有涉及到着色器的代码。这是因为我们虽然有应用程序代码-但不是着色器。着色器和应用程序的通信是非常的频繁的。
第二个变量
Blue,使用 vector来定义,是一个4D的向量。我们简单初始化为蓝色,视为一个RGBA颜色的向量。
输入和输出结构
在定义全局变量之后,我们定义两个特殊的结构,我们调用输入和输出结构。提供给顶点,这写结构定义我们着色器输入和输出的顶点数据,分别的.
16.2编译一个HLSL着色器
常量表
每个着色有一个使用存储它的变量的的常量表。
D3DX库提供给我们一股脑用程序访问着色器常量表的结构。
高级着色语言语法:
变量类型
结构
关键字
语句 ,和转换
基本流程控制
运算符
用户定义函数
内建函数
标量类型
bool类型 - 真或假值。注意HLSL提供true或false关键字
int类型 - 32bit有符号整数
half类型 - 16bit浮点数
float类型 - 32bit浮点数
double - 64bit浮点数
注意: 一些平台也许不支持int ,half,和double.如果是这种情况,这些类型被使用float模拟。
向量类型
HLSL提供下面内置的向量类型:
vector - 一个4D向量每个成员都是一个float
vector<T,n> 一个n维向量,每个都是一个标量的T.维数必须为1到4.这里举例为2Ddouble向量:
我们可以使用数组标号来访问语法。例如,设置i组件的vector vec,我们写:
vec[i] = 2.0f;
另外,我们可以我们访问每个结构,使用x,y,z,w,r,g,b和a来访问。
这个r,g,b,a提供了精确的分别的同样的组件。当描绘颜色的时候使用RGBA符号更多的符合增加的描绘的向量的颜色。
二选一的,我们可以使用这些其他的预先定义的描绘2D,3D,4D向量分别的:
float2 vec2;
float3 vec3;
float4 vec4;
考虑向量u = (Ux,Uy,Uz,Uw)和推想我们想复制u到v像v = (Ux,Uy,Uy,Uw).大部分直接的将解决个别的复制U和V为必要的。然而,HLSL提供了特殊关于的语法无序的叫做swizzles:
vector u = {1.0f,2.0f,3.0f,4.0f};
vector v = {0.0f,0.0f,5.0f,6.0};
v = u.xyyw;
当复制向量的过程,我们没有每个组件。例如,我们可以复制仅仅x和y组见,作为代码说明片段。
vector u = {1.0f,2.0f,3.0f,4.0f};
vecotr v = {0.0f,0.0f,5.0f,6.0f};
v.xy = u;
矩阵类型
HLSL有下面的内置类型:
matrix -一个 4x4矩阵,每个实体为float类型
matrix<T,m,n> - 一个mxn矩阵,每个实体是标量类型T.matrix维数m和n必须在1和4之间。这里一个2x2的例子的整数:
matrix<int,2,2> m2x2;
作为选择,我们可以定义一个mxn矩阵,m和n是在1和4之间,使用下面的语法:
floatmxn matmxn;
注意:这个类型不仅仅需要float - 我们可以使用其他的类型。例如我们可以使用整数和写为:
int2x2 i2x2;
double2x2 d2x2;
我们可以使用下标访问每个实体。例如,设置ij实体的矩阵M,我们可以写为:
M[i][j] = value;
另外,我们可以参考矩阵M作为我们访问整个成员的结构。下面的实体被定义:
M._11 = M._12 = M._13 = M._14 = 0.0f;
清0
有时我们想参考特殊的行在matrix.我们可以使用单个的数组写在下方语法。例如,参考i行向量矩阵M,我们可以写:
vector ithRow = M[i];
注意: 我们可以初始化变量在HLSL使用下面的方式:
vector u = {0.6f,0.3f,1.0f,1.0f};
vector v = {1.0f,5.0f,0.2f,1.0f};
或者,使用这样的语法构造器
vector u = vector(0.6f,0.3f,1.0f,1.0f);
vector v = vector(1.0f,4.0f,0.2f,1.0f);
一些其他的例子:
float2x2 f2x2 = float2x2(1.0f,2.0f,3.0f,4.0f);
int2x2 m = {1,2,3,4};
int n = int(5);
int a = {5};
float3 x = float3(0,0,0);
数组
我们可以定义特殊的使用C++语法:
float M[4][4];
half p[4];
vector v[12];
结构
结构在C++经常使用。然而在HLSL结构中不可以有函数成员。这里是一个HLSL结构的例子:
struct MyStruct
{
matrix T;
vector n;
float f;
int x;
bool b;
};
typedef 关键字
HLSLtypedef关键字函数像C++一样,我们可以代替同一类型vector<float,3>使用下面的语法:
typedef vector<float,3> point;
point nbt;
这里有两个例子展示了怎样使用typedef关键字使用常量类型和数组:
typedef const float CFLOAT;
typedef float point2[2];
变量前缀
下面的关键字定义为变量的前缀:
static uniform extern shared volatile const
关键字,语句和转换
基本流程控制
HLSL支持许多类似C++语句选择,循环,和一般的流程控制。语法完全是C++.
返回语句 return (expression);
If和 If...Else语句
if(condition)
{
}
if(condition)
{
}
else
{
}
for语句
for(initial;condition;increment)
{
statement(s);
}
while语句
while(condition)
{
}
do
{
}while(condition);
for while do-while完全跟c++一样。
转换
HLSL支持非常灵活的转换scheme.转换的语法类似于HLSL的C语言。例如,转换float为一个matrix,我们可以 写:
float f = 5.0f;
matrix m = (matrix)f;
例如书上例子,你将可以得出转换到语法。然而,如果你想更多支持的转换的细节,在DirectX SDK文档中,tab目录 下,看DirectX Graphics\Reference\Shader Reference\High Shading Language\Type.
运算符
HLSL支持许多C++运算符。下面的除外,他们完全和C++一样。下面HLSL有限的运算符表:
[] . > < <= >= != == ! && || ?: + += - -= * *= / /= % %= ++ -- = () ,
虽然运算符行为类似C++,但是有不同,首先,modulus %运算符工作在两个整数和浮点类型。目的使用去模运算,两左边值和右边值必须有同样的符号(e.g,必须都为正或负).
第二,观察许多HLSL运算符工作在每饿基本操作。这个赢得的实际向量和矩阵在语言构造和这些类习惯内存在许多组件。在组件级操作工作,操作像vector/matrix附加,vector/matrix减法,和vector/matrix相等的测试可以使用同样的操作符完成,我们使用标量类型。看下面的了例子。
注意:运算符使用标量(因为,通常为C++的方式).
vector u = {1.0f,0.0f,-3.0f,1.0f};
vector v = {-4.0f,2.0f,1.0f,0.0f};
增加每个组件:
sum++;
多向量乘积
vector
bool向量包含每个比较信息的结果,例如:
vector u = {1.0f,0.0f,-3.0f,1.0f};
vector v = {-4.0f,0.0f,1.0f,1.0f};
vector b = (u==v);
最后,我们推测讨论变量的提升二进制操作:
二进制操作,如果左边和右边的维数,使用小维数促进转换使用的大的维数。例如,如果 x是float和shifloat3 表达方式(x + y)变量 x是进行评价值为float3.这个promotion被使用定义转换完成。
在这种情况我们用转换标量到向量;因此,x被promoted后到float3 x = (x,x,x),作为标量到向量转换帝国仪。注意,例如,我们不可以promote float2到float3因为村子不一样的定义转换。
对于二进制操作,如果坐标和右边不同的类型,然后转换到有同样类型使用高类型解决。
例如,如果x是int 和shi half,在表达式变量x被评价为half值。
用户定义函数:
在HLSL有下面的属性
函数C++的语法
参数总是设置为值
不支持递归
函数总是内联的。
此外,HLSL添加一些扩展的关键字函数。例如,考虑写
bool foo(int const bool b,out int r1,inout float r2)
{
if(b)
}
内置函数
HLSL有丰富的内置函数供3D图形使用。下面是一个精简的表。两饿章我们将获取使用这写函数的经验。目前,先熟悉一下。
注意:更多参考看DirectX文档。下面的内容表,。