天行健 君子当自强而不息

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

新建网页 1

在我们写的程序里顶点和像素是很小的对象,它们由GPU来执行,是固定功能管线的一部分。用我们自己写的着色器程序替换一部分固定功能管线,在绘制效果上我们获得很大的灵活性。我们不再局限于预定义的"固定"操作。

为了编写着色器程序,我们需要一种高级着色器语言(High-Level Shading Language ,简称HLSL) 。 在DirectX 8中,着色器是用低级着色器汇编语言编写的。幸运的是,我们不必再用汇编语言来写着色器了,DirectX 9支持一种高级着色器语言来写。用HLSL写着色器程序与使用高级语言有同样的优势,像C++,它超越了汇编语言,即:

增加生产力用高级语言比用低级语言写程序更快、更容易。 我们可以花费更多的时间关注于算法而不是代码。

增加可读性用高级语言写的程序更易读,这意味着用高级语言编程更易于调试和维护。

大多数情况下,编译器产生的汇编代码比手写有效率。

使用HLSL 编译器,我们可以编译我们的代码到任何可用shader版本,使用汇编语言我们将不得不为每个需要的版本移植代码。

HLSL CC++语法很类似,所以缩短了学习曲线。

最后,如果你的显卡不支持顶点和像素着色器的话,为了执行着色器的例子程序你将需要转换REF设备。使用REF设备意味着着色器例子运行的会很慢,但它至少能显示结果,让我们去检查是否代码可以被执行。

提示:顶点shaders可以用软件来模拟 ―― D3DCREATE_SOFTWARE_VERTEX-PROCESSING


16.1编写HLSL 着色器

我们可以在程序源文件中用长字符串直接编写HLSL着色器代码,然而更方便、更模块化的方法是把它与程序代码分离出来。因此,我们在记事本中编写着色器并保存成一般的ASCII文本文件,然后可以用D3DXCompileShaderFromFile函数(section 16.2.2)来编译它们。

作为介绍,下面是用HLSL编写的一个简单的顶点着色器,用记事本生成并保存成文本文件“VertexShader.cxx”。顶点着色器用组合视图和投影矩阵转换顶点,并设置顶点漫射光为色。

注意:这是一个顶点着色器的例子,不必关心顶点着色器做了什么,现在的目标是熟悉HLSL编程的语法和格式。

      /************************************************************************************
      Vertex shader that transforms a vertex by the view and projection transformation, 
      and sets the vertex color to red.
     ************************************************************************************/

   
   
    // Global variable to store a combined view and projection transformation matrix,
    // we initialize this variable from the application.
   
matrix g_view_proj_matrix;
   
   
    // initialize a global blue color vector
   
const vector RED = {1.0f, 0.0f, 0.0f, 1.0f};
   
   
    // Input structure describes the vertex that is input into the shader.
    // Here the input vertex contains a position component only.
   
struct sVertexInput
    {
        vector position : POSITION;
    };
   
   
    // Output structure describes the vertex that is output from the shader.
    // Here the output vertex contains a position and color component.
   
struct sVertexOutput
    {
        vector position : POSITION;
        vector diffuse  : COLOR;
    };
   
   
    // Main Entry point, observe the main function receives a copy of the input vertex through
    // its parameter and returns a copy of the output vertex it computes.
   
sVertexOutput main(sVertexInput input)
    {
        
// zero out members of output
   
        sVertexOutput output = (sVertexOutput)0;
   
        
// transform to view space and project
   
        output.position = mul(input.position, g_view_proj_matrix);
   
        
// set vertex diffuse color to blue
   
    output.diffuse = RED;
   
        
return output;
    }

16.1.1 全局变量

首先是2个全局变量:
// Global variable to store a combined view and projection transformation matrix.
// We initialize this variable from the application.
matrix g_view_proj_matrix;

// Initialize a global blue color vector.
const vector BLUE = {0.0f, 0.0f, 1.0f, 1.0f};

1个变量g_view_proj_matrix是矩阵类型,它是一个在HLSL内创建的4×4的矩阵类型。这个变量保存视图与投影的组合矩阵,它描述两者的变换。使用这种方法我们只要做一个向量和矩阵的乘法(而不是二个)。注意,在着色器源代码的任何地方都没有初始化这个变量,因为它是我们在应用程序的源代码里设置的,而不是在着色器中。从应用程序向着色器程序通讯是常用的操作。

第二个变量BLUEbuilt-in(内建)类型的4D向量,我们简单的将它初始化成蓝色,它是个RGBA的颜色向量。

 

16.1.2 输入和输出结构

在全局变量定义之后,定义2个特殊的结构,我们调用输入和输出结构。对于顶点着色器而言,这些结构定义了顶点的数据,分别是:
// Input structure describes the vertex that is input into the shader.
// Here the input vertex contains a position component only.
struct sVertexInput
{
  vector position : POSITION;
};

// Output structure describes the vertex that is output from the shader.
// Here the output vertex contains a position and color component.
struct sVertexOutput
{
  vector position : POSITION;
  vector diffuse : COLOR;
};

 

注意:给像素着色器的结构定义输入和输出像素数据。

在例子中,INPUT 顶点着色器只包含位置成员(POSITION),OUTPUT顶点着色器包含位置和颜色成员POSITION and COLOR)。

特殊的冒号是一种语义,用于是声明变量。这与vertex结构中的自由顶点格式(FVF)相似。例如,在sVertexInput中有成员:vector position : POSITION;

": COLOR"是说顶点的漫射光是用sVertexOutput结构的COLOR成员来说明的。
注意:从底层来说,着色器变量的语义和语法同硬件寄存器是相关联的。即,input变量与input寄存器关联,output变量与output寄存器关联。例如,
sVertexInput中的position成员与顶点inputposition寄存器相关联。同样,diffuse与顶点的outputcolor寄存器关联。

 

16.1.3 函数的入口点

C++程序中,每个HLSL程序有一个入口点。在我们的着色器例子中,我们调用入口点函数main。然而名字不是强制的。入口点函数名可以是任何有效的函数名,入口点函数必须有一个input结构参数,它通过input顶点进入着色器。入口点函数必须返回一个output结构实例,在着色器中使用output操作顶点。

sVertexOutput main(sVertexInput input)
{

 注意:实际上,使用input、output结构不是强制的。例如,有时你将会看到使用类似下面的语法,特别是在像素着色器中:

float4 Main(in float2 base : TEXCOORD0,

            in float2 spot : TEXCOORD1,

            in float2 text : TEXCOORD2) : COLOR

{

...

}


例子中,输入到着色器中的参数是3个纹理坐标。着色器输出(返回)一个颜色,COLOR语句在函数的声明以后。这种定义是类似于:

 


struct INPUT

{

     float2 base : TEXCOORD0;

     float2 spot : TEXCOORD1;

     float2 text : TEXCOORD2;

};


struct OUTPUT

{

     float4 c : COLOR;

};

 

OUTPUT Main(INPUT input)

{

...

}


 

输入点函数负责根据给定的input顶点计算output顶点。例子中的着色器简单的变换input顶点到视图空间和投影空间,设置顶点颜色为色,并返回结果顶点。首先我们定义sVertexOutput的实例并初始化所有成员为0

// zero out members of output
sVertexOutput output = (sVertexOutput)0;

 

然后着色器变换input顶点位置用g_view_proj_matrix变量,使用mul函数。它是一个built-in(内建)函数,实现向量与矩阵相乘,或矩阵与矩阵相乘。我们保存结果变换的向量(在output实例的position成员中)。

// transform to view space and project
output.position = mul(input.position, g_view_proj_matrix);


然后设置output的成员diffuse的颜色为色:

// set vertex diffuse color to red
output.diffuse = RED;

 

最后返回结果向量:

return output;
}

posted on 2008-04-05 15:58 lovedday 阅读(9812) 评论(18)  编辑 收藏 引用

评论

# re: 高级着色语言HLSL入门(1)[未登录] 2008-10-19 14:00 111

你他妈的天行健 我们他妈都扫地的哦
代码不排版 注释还是英文 例子也不给小载 还不标明哪来的  回复  更多评论   

# re: 高级着色语言HLSL入门(1) 2008-10-20 15:21 浩云

吃完人家的东西说人家弄得不好吃.
人家又不收你钱.
不好吃你可以不吃.
干嘛要骂人家.
你他妈的有人性吗?  回复  更多评论   

# re: 高级着色语言HLSL入门(1) 2008-10-29 17:04 飘雪

那位说粗口的请注意你的素质.你表现出的行为不配进入这个圈子.
天兄能够辛苦分享出来这么多资料,是值得尊敬的..
不懂英文,只能说明你的基础不够(我突然想到有部分人定义变量用的拼音),至于其他你所说的一些云云,笑谈..大家权且当埋头苦学时闻此人一声狗吠.秋日一景!  回复  更多评论   

# re: 高级着色语言HLSL入门(1) 2008-11-01 08:39 看不惯那个傻插

理他干什么,他是读书人吗?根本不是!何必和一条野狗计较,直接删贴。  回复  更多评论   

# re: 高级着色语言HLSL入门(1) 2008-11-05 11:01 B1楼

1楼的是个傻逼!!!大傻逼!!!  回复  更多评论   

# re: 高级着色语言HLSL入门(1) 2008-12-18 11:41 merrykid

有一个小错误,在下面一段中。
const vector BLUE和前面的源代码不一样。
前面的是RED。
-----------------------------------
16.1.1 全局变量首先是2个全局变量:
// Global variable to store a combined view and projection transformation matrix.
// We initialize this variable from the application.
matrix g_view_proj_matrix;

// Initialize a global blue color vector.
const vector BLUE = {0.0f, 0.0f, 1.0f, 1.0f};

第二个变量BLUE是built-in(内建)类型的4D向量,我们简单的将它初始化成蓝色,它是个RGBA的颜色向量。



  回复  更多评论   

# re: 高级着色语言HLSL入门(1) 2008-12-18 11:45 merrykid

请问一下,ARGB的顺序是这样吗?我对HLSL知道的不多。
谢谢

  回复  更多评论   

# re: 高级着色语言HLSL入门(1) 2008-12-29 19:40 aq_1000

1楼,英文不行的话,我奉劝你先好好学学英文,或者直接放弃3D图形编程吧,我现在也是硬着头皮去学英文呢!  回复  更多评论   

# re: 高级着色语言HLSL入门(1) 2009-02-18 14:24 A_3D_CODER

same as 《Introduction to 3D Game Programming with DirectX 9.0》,
Just translating English to Chinese.
Thank you all the same.  回复  更多评论   

# re: 高级着色语言HLSL入门(1) 2009-02-22 16:41 lyra

1楼SX 连注释那几个单词也懒得学 连学什么3D  回复  更多评论   

# re: 高级着色语言HLSL入门(1) 2009-04-29 14:00 553768913

支持天行健!!  回复  更多评论   

# re: 高级着色语言HLSL入门(1) 2009-06-15 18:19 anony

1楼
...
...
好比是我们在求知路上碰到的一坨屎  回复  更多评论   

# re: 高级着色语言HLSL入门(1) 2010-03-21 09:42 st

@111
你个白痴,人家辛辛苦苦写了,你丫看不懂就骂,你是不是从山的那一边来的?!

作者使用的英文不难,如果你认真查一下是可以轻易看懂的,至于代码排版问题,并不影响对代码意思的理解~

不说你了,说多了影响你那点牛逼的自尊,多提高一下自身素质吧!  回复  更多评论   

# re: 高级着色语言HLSL入门(1) 2010-11-17 20:16 1L你吗

滚回你妈肚子里 天行健是你爷 你个太监  回复  更多评论   

# re: 高级着色语言HLSL入门(1) 2010-11-18 15:27 oppo

看了天兄的博文,不禁惊为天人,故特地申请了账号来膜拜天兄。  回复  更多评论   

# re: 高级着色语言HLSL入门(1) 2011-05-10 22:00 Scorpion

就会抄书.这段话的出处于 <<Directx9.0 3D游戏开发编程基础>>  回复  更多评论   

# re: 高级着色语言HLSL入门(1) 2011-05-12 16:04 耳朵

支持天行健!!!!狂顶  回复  更多评论   

# re: 高级着色语言HLSL入门(1) 2012-08-02 11:50 败坏艺术

相当一些时候,傻逼埋怨正常人的智商太高,他当然不会觉得是自己的问题——因为是傻逼嘛。人是唯一会脸红的动物,像一楼,是应该脸红的。  回复  更多评论   


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


公告

导航

统计

常用链接

随笔分类(178)

3D游戏编程相关链接

搜索

最新评论