ImageVerifierCode 换一换
格式:DOCX , 页数:49 ,大小:125.42KB ,
资源ID:11535868      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/11535868.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(编程类 HLSL初级教程很详细.docx)为本站会员(b****4)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

编程类 HLSL初级教程很详细.docx

1、编程类 HLSL初级教程很详细HLSL初级教程作者:trcj前言1.HLSL入门 1.1什么是着色器 1.2什么是HLSL 1.3怎么写HLSL着色器 1.4怎么用HLSL着色器2.顶点着色器 2.1可编程数据流模型 2.2顶点声明 2.3用顶点着色器实现渐变动画3.像素着色器 3.1多纹理化 3.2多纹理效果的像素着色器 3.3应用程序4.HLSL Effect(效果框架) 4.1Effect代码结构 4.2用Effect实现多纹理化效果结语参考资料前言 本教程针对HLSL(High Level Shading Language)初学者,从应用的角度对HLSL、顶点着色器、像素着色器和Eff

2、ect效果框架进行了介绍,教程中去掉了对HLSL语法等一些细节内容的讨论,力求帮助读者尽可能快地理解HLSL编程的概念,掌握HLSL编程的方法。 教程中部分阐述直接引用了其他文档,这是因为这些文档表述之精要,已经达到了不能更改的地步,这里表示感谢。 本文档版权为作者所有,非商业用途可免费使用,转载请注明出处。1.HLSL入门1.1什么是着色器DirectX使用管道技术(pipeline)进行图形渲染,其构架如下:图1.1 Direct3D Graphics Pipeline之前我们使用管道的步骤如下:1. 设定顶点、图元、纹理等数据信息;2. 设定管道状态信息; 渲染状态通过SetRender

3、State方法设定渲染状态;另外,使用以下方法设置变换、材质和光照: SetTransform SetMaterial SetLight LightEnable 取样器状态通过SetSamplerState方法设定取样器状态; 纹理层状态通过SetTextureStageState设定纹理层状态;3. 渲染;这部分交由D3D管道按照之前的设定自行完成,这部分操作是D3D预先固定的,所以这种管道技术被称为固定功能管道(fixed function pipeline);固定功能管道给我们编程提供了一定的灵活性,但是仍有很多效果难以通过这种方式实现,比如:1. 在渲染过程中,我们要求y坐标值大于10

4、的顶点要被绘制到坐标值(0,0,0)的地方,在之前的固定功能管道中,顶点被绘制的位置是在第1步即被设定好的,不可能在渲染过程中进行改变,所以是不可行的;2. 谋顶点在纹理贴图1上映射为点A,在纹理贴图2上映射为点B,我们要求该顶点颜色由A、B共同决定,即:定点颜色 = A点色彩值*0.7 + B点色彩值*0.3 这在固定管道编程中也是不可行的。以上两个问题都可以由可编程管道(pragrammable pipeline)来解决。 可编程管线允许用户自定义一段可以在GPU上执行的程序,代替固定管道技术中的Vertex Processing和Pixel Processing阶段(参照图1.1),从而

5、在使我们在编程中达到更大的灵活性。其中替换Vertex Processing的部分叫做Vertex Shader(顶点着色器),替换Pixel Proccessing的部分叫做Pixel Shader(像素着色器),这就是我们所说的着色器Shader。1.2什么是HLSLDirect8.x中,着色器是通过低级着色汇编语言来编写的,这样的程序更像是汇编式的指令集合,由于其效率低、可读性差、版本限制等缺点,迫切要求出现一门更高级的着色语言。到了Direct3D9,HLSL(High Level Shading Language,高级渲染语言)应运而生了。HLSL的语法非常类似于C和C+,学习起来是

6、很方便的。1.3怎么写HLSL着色器我们可以直接把HLSL着色器代码作为一长串字符串编写进我们的应用程序源文件中,但是,更加方便和模块化的方法是把着色器的代码从应用程序代码中分离出来。因此,我们将着色器代码单独保存为文本格式,然后在应用程序中使用特定函数将其加载进来。下面是一个完整的HLSL着色器程序代码,我们把它保存在BasicHLSL.txt中。该着色器完成顶点的世界变换、观察变换和投影变幻,并将顶点颜色设定为指定的颜色。/ BasicHLSL.txt/ Global variable/matrix WVPMatrix;vector color;/ Structures/struct VS

7、_INPUT vector position : POSITION;struct VS_OUTPUT vector position : POSITION; vector color : COLOR;/ Functions/VS_OUTPUT SetColor(VS_INPUT input) VS_OUTPUT output = (VS_OUTPUT)0; output.position = mul(input.position, WVPMatrix); output.color = color; return output;下面就针对上述代码讲解一下HLSL着色器程序的编写:1.3.1全局变

8、量 代码中声明了两个全局变量:matrix WVPMatrix;vector color; 变量WVPMatrix是一个矩阵类型,它包含了世界、观察、投影的合矩阵,用于对顶点进行坐标变换; 变量color是一个向量类型,它用于设定顶点颜色; 代码中并没有对全局变量进行初始化,这是因为我们对全局变量的初始化过程将在应用程序中进行,全局变量在应用程序中赋值而在着色器程序中使用,这是应用程序和着色器通信的关键所在。具体赋值过程将在后续部分讲述。1.3.2输入输出 输入输出结构程序中定义了两个输入输出结构VS_INPUT和VS_OUTPUTstruct VS_INPUT vector position

9、 : POSITION;struct VS_OUTPUT vector position : POSITION; vector color : COLOR;自定义的结构可以采用任意名称,结构不过是一种组织数据的方式,并不是强制的,你也可以不使用,而将本程序的输入改为: vector position : POSITION; 标志符用于输入输出的变量采用用一种特殊的声明方式:Type VariableName : Semantic 这个特殊的冒号语法表示一个语义,冒号后面的标志符用来指定变量的用途,如vector position : POSITION; 其中,POSITION标志符表明该变量表

10、示顶点位置,另外还有诸如COLOR、NORMAL等很多表示其他意义的标志符。本节所说的输入输出其实是指着色器代码和编译器、GPU之间的通信,和应用程序是无关的,所以这些变量不需要在应用程序中进行赋值,标志符告诉编译器各个输入输出变量的用途(顶点位置、法线、颜色等),这是着色器代码和编译器、GPU之间通信的关键。1.3.3入口函数 程序中还定义了一个函数SetColor:OUTPUT SetColor(INPUT input) VS_OUTPUT output = (VS_OUTPUT)0; output.position = mul(input.position, WVPMatrix); ou

11、tput.color = color; return output;1. 该函数以input和output类型作为输入输出;2. 使全局变量WVPMatrix和input.position相乘,以完成顶点的世界、观察、投影变换,并把结果赋值到output.position;output.position = mul(input.position, WVPMatrix);3. 将全局变量color的值赋给output.color;output.color = color;4. 在同一个着色器代码文件中,可以有多个用户自定义函数,因此在应用程序中需要指定一个入口函数,相当于windows程序的Wi

12、nMain函数,本程序只包含SetColor一个函数而且它将被做为入口函数使用。1.3.4总结 至此,一个HLSL着色器编写完毕,渲染过程中,当一个顶点被送到着色器时:1. 全局变量WVPMatrix、color将在应用程序中被赋值;2. 入口函数SetColor被调用编译器根据标志符将顶点信息填充到VS_INPUT中的各个字段;3. SetColor函数中,首先定义一个VS_OUTPUT信息,之后根据WVPMatrix和color变量完成顶点的坐标变换和颜色设定操作,最后函数返回VS_OUTPUT结构;4. 编译器将会再次根据标志符把返回的VS_OUTPUT结构中的各字段映射为顶点相应的信息

13、。5. 顶点被送往下一个流程接受进一步处理。上述过程中,全局变量在应用程序中赋值而在着色器程序中使用,这是应用程序和着色器通信的关键所在;标志符告诉编译器各个输入输出变量的用途(顶点位置、法线、颜色等),这是着色器代码和编译器、GPU之间通信的关键。个人认为这是着色器中最为精义的地方:)1.4怎么用HLSL着色器应用程序中对HLSL着色器的使用分为以下步骤:1. 加载(称为编译更为妥当)着色器代码;2. 创建(顶点/像素)着色器;3. 对着色器中的变量进行赋值,完成应用程序和着色器之间的通信。4. 把着色器设定到渲染管道中;本例使用的着色器是一个顶点着色器,因此我们将通过顶点着色器的使用来讲解

14、着色器的使用过程,像素着色器的使用过程与此大同小异,二者之间仅有些微差别。1.4.1声明全局变量IDirect3DVertexShader9* BasicShader = 0; /顶点着色器指针ID3DXConstantTable* BasicConstTable = 0; /常量表指针D3DXHANDLE WVPMatrixHandle = 0;D3DXHANDLE ColorHandle = 0;ID3DXMesh* Teapot = 0; /指向程序中D3D茶壶模型的指针1.4.2编译着色器通过D3DXCompileShaderFromFile函数从应用程序外部的文本文件BasicHLS

15、L.txt中编译一个着色器:/编译后的着色器代码将被放在一个buffer中,可以通过ID3DXBuffer接口对其进行访问,之后的着色器将从这里创建 ID3DXBuffer* shaderBuffer = 0; /用于接受错误信息 ID3DXBuffer* errorBuffer = 0; /编译着色器代码 D3DXCompileShaderFromFile(BasicHLSL.txt, /着色器代码文件名 0, 0, SetColor, /入口函数名称 vs_1_1, /顶点着色器版本号 D3DXSHADER_DEBUG,/ Debug模式编译 &shaderBuffer, /指向编译后的着

16、色器代码的指针 &errorBuffer, &BasicConstTable); /常量表指针1.4.3创建着色器 应用程序通过CreateVertexShader创建一个顶点着色器,注意使用了上一步得到的shaderBuffer: g_pd3dDevice-CreateVertexShader(DWORD*)shaderBuffer-GetBufferPointer(), &BasicShader);1.4.3对着色器中的变量进行赋值1.3.4节说到着色器的全局变量在应用程序中赋值而在着色器程序中使用,这是应用程序和着色器通信的关键所在,这里就具体说明赋值过程。着色器中的全局变量在编译后都被

17、放在一个叫常量表的结构中,我们可以使用ID3DXConstantTable接口对其进行访问,参照1.4.1中编译着色器函数D3DXCompileShaderFromFile的最后一个参数,该参数即返回了指向常量表的指针。对一个着色器中变量进行赋值的步骤如下:1. 通过变量名称得到指向着色器变量的句柄;还记得在BasicHLSL.x着色器文件中我们声明的两个全局变量吗: matrix WVPMatrix;vector color; 我们在应用程序中相应的声明两个句柄:D3DXHANDLE WVPMatrixHandle = 0; D3DXHANDLE ColorHandle = 0; 然后通过变

18、量名得到分别得到对应的两个句柄: WVPMatrixHandle = BasicConstTable-GetConstantByName(0, WVPMatrix); ColorHandle = BasicConstTable-GetConstantByName(0, color);2. 通过句柄对着色器变量进行赋值;我们可以先设置各变量为默认值: BasicConstTable-SetDefaults(g_pd3dDevice);之后,可以使用ID3DXConstantTable:SetXXX函数对各个变量进行赋值:HRESULT SetXXX( LPDIRECT3DDEVICE9 pDev

19、ice, D3DXHANDLE hConstant, XXX value);其中XXX代表变量类型,例如Matrix类型的变量就要使用SetMatrix函数赋值,而Vector类型的则要使用SetVector来赋值。1.4.4把着色器设定到渲染管道中 这里我们使用SetVertexShader方法把顶点着色器设定到渲染管道中: g_pd3dDevice-SetVertexShader(BasicShader);1.4.5整个渲染过程如下在渲染过程中,我们设定顶点的变换坐标和颜色值,渲染代码如下: g_pd3dDevice-Clear( 0, NULL, D3DCLEAR_TARGET | D3

20、DCLEAR_ZBUFFER, D3DCOLOR_XRGB(153,153,153), 1.0f, 0 ); /开始渲染 g_pd3dDevice-BeginScene(); /得到世界矩阵、观察矩阵和投影矩阵 D3DXMATRIX matWorld, matView, matProj; g_pd3dDevice-GetTransform(D3DTS_WORLD, &matWorld); g_pd3dDevice-GetTransform(D3DTS_VIEW, &matView); g_pd3dDevice-GetTransform(D3DTS_PROJECTION, &matProj);

21、D3DXMATRIX matWVP = matWorld * matView * matProj; /通过句柄对着色器中的WVPMatrix变量进行赋值 BasicConstTable-SetMatrix(g_pd3dDevice, WVPMatrixHandle, &matWVP); D3DXVECTOR4 color(1.0f, 1.0f, 0.0f, 1.0f); /通过句柄对着色器中的color变量进行赋值,这里我们赋值为黄色 BasicConstTable-SetVector(g_pd3dDevice, ColorHandle, &color); /把顶点着色器设定到渲染管道中 g_

22、pd3dDevice-SetVertexShader(BasicShader); /绘制模型子集 Teapot-DrawSubset(0); /渲染完毕 g_pd3dDevice-EndScene(); g_pd3dDevice-Present(NULL, NULL, NULL, NULL); 编译运行程序,运行效果如图1.2所示,这里我们将顶点颜色设置为黄色,如果读者在渲染过程中不断变换对着色器变量color的赋值,你将会得到一个色彩不断变幻的D3D茶壶。D3DXVECTOR4 color(1.0f, 1.0f, 0.0f, 1.0f); /读者可以尝试改变颜色值BasicConstTabl

23、e-SetVector(g_pd3dDevice, ColorHandle, &color);图1.2 着色器效果2.顶点着色器顶点着色器(vertex shader)是一个在显卡的GPU上执行的程序,它替换了固定功能管道(fixed function pipeline)中的变换(transformation)和光照(lighting)阶段(这不是百分之百的正确,因为顶点着色器可以被Direct3D运行时(Direct3D runtime)以软件模拟,如果硬件不支持顶点着色器的话)。图2.1说明了管线中顶点着色器替换的部件。图2.1由于顶点着色器是我们(在HLSL中)写的一个自定义程序,因此我

24、们在图形效果方面获得了极大的自由性。我们不再受限于Direct3D的固定光照算法。此外,应用程序操纵顶点位置的能力也有了多样性,例如:布料仿真,粒子系统的点大小操纵,还有顶点混合/变形。此外,我们的顶点数据结构更自由了,并且可以在可编程管线中包含比在固定功能管线中多的多的数据。正如作者所在群的公告所说,“拍照不在于你对相机使用的熟练程度,而是在于你对艺术的把握。”之前的介绍使读者对着色器的编写和使用都有了一定的了解,下面我们将把重心从介绍如何使用着色器转到如何实现更高级的渲染效果上来。2.1可编程数据流模型DirectX 8.0引入了数据流的概念,可以这样理解数据流(图2.2):图2.2 一个

25、顶点由n个数据流组成。 一个数据流由m个元素组成。 一个元素是位置、颜色、法向、纹理坐标。程序中使用IDirect3DDevice9:SetStreamSource方法把一个顶点缓存绑定到一个设备数据流。2.2顶点声明该小节对顶点声明的描述绝大多数都取自翁云兵的着色器和效果,该文对顶点声明的描述是我所见到最详尽最透彻的,这里向作者表示敬意:)到现在为止,我们已经使用自由顶点格式(flexible vertex format,FVF)来描述顶点结构中的各分量。但是,在可编程管线中,我们的顶点数据可以包含比用FVF所能表达的多的多的数据。因此,我们通常使用更具表达性的并且更强有力的顶点声明(ver

26、tex declaration)。注意:我们仍然可以在可编程管线中使用FVF如果我们的顶点格式可以这样描述。不管怎样,这只是为了方便,因为FVF会在内部被转换为一个顶点声明。2.2.1 描述顶点声明我们将一个顶点声明描述为一个D3DVERTEXELEMENT9结构的数组。D3DVERTEXELEMENT9数组中的每个元素描述了一个顶点的分量。所以,如果你的顶点结构有三个分量(例如:位置、法线、颜色),那么其相应的顶点声明将会被一个含3个元素的D3DVERTEXELEMENT9结构数组描述。D3DVERTEXELEMENT9结构定义如下:typedef struct _D3DVERTEXELEM

27、ENT9 BYTE Stream; BYTE Offset; BYTE Type; BYTE Method; BYTE Usage; BYTE UsageIndex; D3DVERTEXELEMENT9; Stream指定关联到顶点分量的流; Offset偏移,按字节,相对于顶点结构成员的顶点分量的开始。例如,如果顶点结构是:struct Vertex D3DXVECTOR3 pos; D3DXVECTOR3 normal;pos分量的偏移是0,因为它是第一个分量;normal分量的偏移是12,因为sizeof(pos) = 12。换句话说,normal分量以Vertex的第12个字节为开始。

28、 Type指定数据类型。它可以是D3DDECLTYPE枚举类型的任意成员;完整列表请参见文档。常用类型如下:D3DDECLTYPE_FLOAT1浮点数值D3DDECLTYPE_FLOAT22D浮点向量D3DDECLTYPE_FLOAT33D浮点向量D3DDECLTYPE_FLOAT44D浮点向量D3DDECLTYPE_D3DCOLORD3DCOLOR类型,它扩展为RGBA浮点颜色向量(r, g, b, a),其每一分量都是归一化到区间0, 1了的。 Method指定网格化方法。我们认为这个参数是高级的,因此我们使用默认值,标识为D3DDECLMETHOD_DEFAULT。 Usage指定已计划

29、的对顶点分量的使用。例如,它是否准备用于一个位置向量、法线向量、纹理坐标等,有效的用途标识符(usage identifier)是D3DDECLUSAGE枚举类型的:typedef enum _D3DDECLUSAGE D3DDECLUSAGE_POSITION = 0, / Position. D3DDECLUSAGE_BLENDWEIGHTS = 1, / Blending weights. D3DDECLUSAGE_BLENDINDICES = 2, / Blending indices. D3DDECLUSAGE_NORMAL = 3, / Normal vector. D3DDECLUSAGE_PSIZE = 4, / Vertex point size. D3DDECLUSAGE_TEXCOORD = 5, / Texture coordinates. D3DDECLUSAGE_TANGENT = 6, / Tangent vector. D3DDECLUSAGE_BINORMAL = 7, / Binormal vector. D3DDECLUSAGE_TESSFACTOR = 8, / Tessellation factor. D3DDECLUSAG

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1