天行健 君子当自强而不息

高级着色语言HLSL入门(5)

16.4关键字、语句和强制转换

16.4.1 关键字

为便于参考,这里给出一个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

 

下面的集合显示了被保留并且未使用但是将来可能成为关键字的标识符:

auto            break        case           catch         char          class

const_cast       continue      default         delete        dynamic cast   enum

explicit         friend         goto           long         mutable       namespace

new            operator       private         protected     public         register

reinterpret_cast   short         signed          sizeof        static_cast     switch

template         this          throw          try           typename     union

unsigned         using        virtual

16.4.2 基本程序流程

HLSL支持很多与C++相似的选择、重复、和一般程序流程语句。这些语句的语法和C++极为相似。

return语句:

return (expression);

if和if…else语句:

if( condition )

{

     statement(s);

}

 

if( condition )

{

     statement(s);

}

else

{

     statement(s);

}

 

for语句:

for(initial; condition; increment)

{

     statement(s);

}

 

while语句:

while( condition )

{

     statement(s);

}

 

do…while语句:

do

{

     statement(s);

}while( condition );

 

16.4.3 强制转换(casting)

HLSL支持一种非常自由的强制转换设计。HLSL中强制转换的语法和C程序语言中的一样。例如要把float转换到matrix,我们写:

float f = 5.0f;

matrix m = (matrix)f;

 

16.5 操作符

HLSL支持很多类似C++的操作符。除了很少一些底下注释的例外以外,他们的用法和C++里的完全一样。下表列出了HLSL的操作符:

[ ]

 

< =

> =

! =

= =

!

&&

 

?:

+

+ =

-

- =

*

*=

/

/=

%

%=

+ +

--

=

()

'

 

 

 

 

虽然操作符的行为和C++很相似,但是也有一些差异。第一,求模%运算符对整型和浮点型都起作用。为了使用求模操作符,左边的值和右边的值都必须有相同的正负号(如:左边和右边必须都是正或者负)。

第二,要注意HLSL操作是以每个分量为基础的。这是由于实际上向量和矩阵是语言内建的,并且这些类型是由若干个分量组成。通过将这些操作施加在分量级别之上,我们可以像使用数值类型一样完成诸如向量/矩阵的加法,减法和相等测试这些操作(),见下例:

注意:操作符的行为正如对数值操作一样(也就是说,按一般C++的方式)。

vector u = {1.0f, 0.0f, -3.0f, 1.0f};

vector v = {-4.0f, 2.0f, 1.0f, 0.0f};

// adds corresponding components

vector sum = u + v; // sum = (-3.0f, 2.0f, -2.0f, 1.0f)

 

增量一个向量就是增量其每个分量:

// before increment: sum = (-3.0f, 2.0f, -2.0f, 1.0f)

sum++; // after increment: sum = (-2.0f, 3.0f, -1.0f, 2.0f)

 

向量相乘也是按分量的:

vector u = {1.0f, 0.0f, -3.0f, 1.0f};

vector v = {-4.0f, 2.0f, 1.0f, 0.0f};

// multiply corresponding components

vector sum = u * v; // product = (-4.0f, 0.0f, -3.0f, 0.0f)

 

比较操作也是按分量进行的,并且返回一个每个分量都为bool类型的向量或者数组。作为结果的“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); // b = (false, true, false, true)

 

最后,我们以讨论二元操作的变量提升(promotion)作为结束:

对于二元操作,如果(操作符的)左边和右边维数不同,则维数较少的一边提升(强制转换)到具有和维数较大的一边相同的维数。例如,如果x的类型为float,而y的类型为float3,在表达式(x + y)中变量x被提升到float3,并且计算出来的表达式的值的类型也为float3。提升使用已定义的转换完成。注意,若转换未定义则提升也是未定义的。例如,我们不能转换float2到float3,因为没有定义这个转换。

对于二元操作,如果左边和右边类型不同,那么较低精度的类型(the lower type resolution)被提升(强制转换)到具有同类型的较高精度的类型(the higher type resolution)。例如,如果x类型为int,y类型为half,则表达式(x + y)中的变量x被提升到half,并且计算出来的表达式的值的类型也为half。

 

16.6 用户定义函数

HLSL中的函数有下例属性:

函数使用类似C++的语法

参数总是按值传递

递归不被支持

函数总是inline的

此外,函数还加上了一些用于其上的额外的关键字。例如,考虑一个写在HLSL中的下面这个函数:

bool foo(in const bool b,   // input bool

         out int r1,        // output int

         inout float r2)    // input/output float

{

     if( b )               // test input value

     {

          r1 = 5;          // output a value through r1

     }

     else

     {

          r1 = 1;          // output a value through r1

}

 

     // since r2 is inout we can use it as an input

     // value and also output a value through it

r2 = r2 * r2 * r2;

 

     return true;

}

 

函数几乎和C++函数是一样的,除了in,out和inout关键字:

in——指定型参(argument,特指传递给实参的变量)应该在函数开始前被拷贝给实参。传入参数不必强制指定,因为实参默认是in的。例如,下面两段是等价的:

float square(in float x)

{

     return x * x;

}

也可以不强制指定in:

float square(float x)

{

     return x * x;

}

 

out——指定实参应该在函数返回时被拷贝给型参。这样可以通过参数返回值。out关键字是必须的,因为HLSL不允许传递一个引用或一个指针。我们要注意:如果实参标记为out,在函数开始前,型参就不拷贝给实参。换句话说,out实参仅可以被用于输出数据——它不能用于输入。

void square(in float x, out float y)

{

     y = x * x;

}

这里,我们输入了要被乘方的数x,并且通过参数y返回了x的乘方。


inout——这是一个指示实参既用于输入又用于输出的快捷方法。如果要使用实参同时用作输入和输出,就指定inout。

void square(inout float x)

{

     x = x * x;

}

这里,我们输入了要被乘方的数x,同时又通过x返回了的x的乘方。


posted on 2008-04-05 17:18 lovedday 阅读(4724) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


公告

导航

统计

常用链接

随笔分类(178)

3D游戏编程相关链接

搜索

最新评论