你的位置:奥古多媒体 >> 资讯 >> 教程 >> 三维教程 >> 详细内容 在线投稿

关于Shader和HLSL

排行榜 收藏 打印 发给朋友 举报 来源: 奥古多媒体   发布者:media
热度370票  浏览971次 时间:2007年1月25日 08:02
写过Direct3D程序的朋友们可能还记得,在以往,大家常为如何表现更多真实的材质(如玻璃、金属等)而发愁。最新的Direct3D中,HLSL把程序员从复杂的Shader指令集中解放出来,着力于更重要的算法。奥古多媒体^8_T9X_J}
首先,什么是Shader&什么是HLSL?奥古多媒体+Yi]Bb'U
奥古多媒体'QxA@w)WQ/]~E
简要地说,Shader就是一种脚本程序,相对独立于D3D主程序,并且被编译成显卡的GPU指令序列在显示芯片上跑。(你肯定想知道更多,比如这种程序用什么来写,都要写什么,怎么让GPU跑这种程序等等,别着急慢慢来),这里有必要先了解一下:奥古多媒体 pr@/YD,Q&K6Z
AGP显卡的渲染流程:奥古多媒体.J*k SCY.O
奥古多媒体m2Yy+]| x(C(Ww B
首先来根据下面这张图粗略说明一下当前最普遍流行的AGP显卡的渲染流程,甭管是nVidia还是ATI哪一边的。奥古多媒体[pvU1h }

%Y2ZGb$pO0 每次渲染过程(例如,在一帧画面中画一个馒头的过程)都包括顶点处理(Vertex Processing)和像素处理(Pixel Processing)两个主要功能模块的执行。首先,显卡从AGP总线接收这个馒头的顶点数据。这些数据包括位置、法线、贴图坐标(如果是面包可能更需要贴图,也就是说贴图坐标不是必需的)等等,这些都是未经过任何变换,也就是在物体本地空间(Object Space)下的原始坐标。每个顶点依次被送入顶点处理单元,在这里进行坐标变换、光照计算(如果是每顶点光照)等工作,变换的结果是把每个三角形变换置屏幕空间(Screen Space)下直接可用。这里用到的变换矩阵、灯光等信息都是处理每一批顶点时一次性传给显卡的,作为显卡的资源。顶点处理圈定了三角形的范围,接下来就要逐像素地填充这个三角形了。填充哪些像素是靠对顶点屏幕坐标的线性插值来决定的。像素的其他一些必要参数,如颜色,贴图坐标等也是通过对上一步计算出来的顶点的这些属性进行插值得到的。另外每个像素还要通过深度检测和模板检测决定最终是否绘制。需要绘制的像素被送进像素处理模块,进行贴图像素取值,贴图混合等工作,必要的话每像素光照也在这里完成。这里贴图等信息也是作为显卡的资源。像素最终的处理结果被放进后备缓冲。
x(r? Y;z/{(B8Q0
&a&_ wI I0
+d#x1r[1E0 奥古多媒体8I"oC/s_DK7C
以往显卡在顶点处理和像素处理过程中执行的是一套布在硬件上的固定的程序,D3D程序员只能设置一些参数,实际上就是你调用IDirect3DDevice::SetRenderState()时做的事,而这样的程序在IDirect3DDevice::DrawPrimitive()中自动执行。那么有些事情就很难办到,如渲染一个水晶馒头。应为参数再多,其渲染所用到的光照公式也跑不出石膏这种东西。现在的显卡,确切的说是现在的Direct3D允许你写这么一段程序替代固定的顶点处理过程和像素处理过程(记住,只是这两个过程,跟插值什么的没关系)。其中替换顶点处理的就叫Vertex Shader(暂时还没有确切的中文名),替换像素处理的就叫Pixel Shader。就是开篇所说的Shader。奥古多媒体 poUz9J |1~

:Rcj4VS1A3j0 这样你应该想到Shader中大概应该写些什么了。如果还不行的话建议复习一下D3D。用什么来写呢?三。GPU自有GPU的指令集,以往的Shader就是用这种汇编式的指令集组成,例如:奥古多媒体V\q}$I0c
以往显卡在顶点处理和像素处理过程中执行的是一套布在硬件上的固定的程序,D3D程序员只能设置一些参数,实际上就是你调用IDirect3DDevice::SetRenderState()时做的事,而这样的程序在IDirect3DDevice::DrawPrimitive()中自动执行。那么有些事情就很难办到,如渲染一个水晶馒头。应为参数再多,其渲染所用到的光照公式也跑不出石膏这种东西。现在的显卡,确切的说是现在的Direct3D允许你写这么一段程序替代固定的顶点处理过程和像素处理过程(记住,只是这两个过程,跟插值什么的没关系)。其中替换顶点处理的就叫Vertex Shader(暂时还没有确切的中文名),替换像素处理的就叫Pixel Shader。就是开篇所说的Shader。
f0A1W%a!} [0
.|3k]G?i(s5{0 这样你应该想到Shader中大概应该写些什么了。如果还不行的话建议复习一下D3D。用什么来写呢?三。GPU自有GPU的指令集,以往的Shader就是用这种汇编式的指令集组成,例如:奥古多媒体!rpJk]D zQ:xwb
以往显卡在顶点处理和像素处理过程中执行的是一套布在硬件上的固定的程序,D3D程序员只能设置一些参数,实际上就是你调用IDirect3DDevice::SetRenderState()时做的事,而这样的程序在IDirect3DDevice::DrawPrimitive()中自动执行。那么有些事情就很难办到,如渲染一个水晶馒头。应为参数再多,其渲染所用到的光照公式也跑不出石膏这种东西。现在的显卡,确切的说是现在的Direct3D允许你写这么一段程序替代固定的顶点处理过程和像素处理过程(记住,只是这两个过程,跟插值什么的没关系)。其中替换顶点处理的就叫Vertex Shader(暂时还没有确切的中文名),替换像素处理的就叫Pixel Shader。就是开篇所说的Shader。
t E mw8X5O4wK0
Uh~ `I8J0 这样你应该想到Shader中大概应该写些什么了。如果还不行的话建议复习一下D3D。用什么来写呢?三。GPU自有GPU的指令集,以往的Shader就是用这种汇编式的指令集组成,例如:奥古多媒体_HO7\C/N(g
以往显卡在顶点处理和像素处理过程中执行的是一套布在硬件上的固定的程序,D3D程序员只能设置一些参数,实际上就是你调用IDirect3DDevice::SetRenderState()时做的事,而这样的程序在IDirect3DDevice::DrawPrimitive()中自动执行。那么有些事情就很难办到,如渲染一个水晶馒头。应为参数再多,其渲染所用到的光照公式也跑不出石膏这种东西。现在的显卡,确切的说是现在的Direct3D允许你写这么一段程序替代固定的顶点处理过程和像素处理过程(记住,只是这两个过程,跟插值什么的没关系)。其中替换顶点处理的就叫Vertex Shader(暂时还没有确切的中文名),替换像素处理的就叫Pixel Shader。就是开篇所说的Shader。
x1c }!h.oLhi"rqJfF} a0
e q+YA"OD2wc%e0 这样你应该想到Shader中大概应该写些什么了。如果还不行的话建议复习一下D3D。用什么来写呢?三。GPU自有GPU的指令集,以往的Shader就是用这种汇编式的指令集组成,例如:
:k1x6uC{&o {O0 vs_1_1奥古多媒体Py"Y)j[
奥古多媒体W9[?M;WhK0BIM
dcl_position v0奥古多媒体R I!N!^af1L
奥古多媒体S{$y9i8s&I%i
dcl_normal v1,r0, v0.x, c0
6a X_f m:TA0
'P6t.lGI#| u;J5w5_7z h0 mad r2, v0.y, c1, r0奥古多媒体Q C&e/h!r.s@
奥古多媒体6O|t-^.f(G"}_
就如同汇编用多了必然出现C一样,自Direct3D9.0后,一种叫HLSL(High Level Shading Language,高级渲染语言)的面向过程的Shader语言应运而生.
kwb/nR$_3Z\T%k0 奥古多媒体@2`.]e{{,jK

%X,x(n/\0kF0
2b'W+EgjP a'v0 HLSL基础
`w5|){$l t0
NU;h oT!J0 就像每一本编程语言的教材一样,介绍一门语言,首先从它的数据类型,表达式,控制流这些东西说起。HLSL的这些基本语法很像C/C++,不再赘述。有些常见问题还是要说明一下,是为了让你不会被这些牵制了全面了解Shader的脚步。奥古多媒体*{/hI;y+`-K
奥古多媒体)]#];J A/{#t6R/CJ
数据类型奥古多媒体 ev ^%A8XZ
奥古多媒体h9zw7nD}g0@1Mcg
与CPU不同,在显卡芯片中,最小的数据吞吐单元是一个由32位浮点数组成的四元组。这一点很有道理不是,想想你在渲染过程中所有涉及到的数据,最复杂的不外乎四维坐标(x,y,z,w)或颜色(r,g,b,a),这样GPU可以一次性处理一个四元组。而整数什么的在显卡中被放到四元组的一个分量里使用,而很多显卡中,整数、布尔值都不被直接支持,而是转为浮点数使用。至于矩阵,通常用4个四元组表示一个4x4矩阵(默认情况一个四元组存储一行,也可以指定按列存储)其他尺寸的以此类推。奥古多媒体5[+x(w? EK^
奥古多媒体1X8YU.IGB
反映到程序上,一个四维向量就被声明为float4,4维方矩阵被声明为float4x4等等。当然,你也可以使用任意不超过4的维度的向量或矩阵,如int3,float3x3,double1。这个double1实际上就是标量了,1可以省略不写。
WU.t/O)P nM$X K?0 奥古多媒体&C jEfq~U
纹理(Texture)&取样器(Sampler)奥古多媒体#HB1x-m^)N6`k/Jm
奥古多媒体3L)K0k(j;HOum
这俩东西可以看作特殊类型变量。纹理就是Shader中用到的贴图资源,这我想没什么好说的。来解释一下取样器:实际上每张贴图在使用的时候都要用一个取样器。取样器相当于这样一个结构,除了保存贴图本身数据之外,还包括过滤参数等取样信息。通常,读取贴图这样的指令接收的都是取样器类型的参数而并非直接接收纹理贴图。声明及使用纹理或取样器跟使用普通变量一样。这里有一些初始化取样器的方法,还是等到后面的实例中讲述吧。奥古多媒体}E`uNQ([[3d
奥古多媒体F!Z1D!@ M }
Semantic & Annotation奥古多媒体jpq9p5l%mI
奥古多媒体;i8_E$c F
任何类型的变量(包括纹理和取样器),我们都可以用Semantic或Annotation修饰来起到一些特殊作用。Semantic暂时翻译成语义;Annotation暂时翻译成注解,这是HLSL中独特的东西。下面这两行中,第一个变量冒号后面的POSITION就是Semantic,第二个变量后面用一对尖括号<>圈起来的表达式就是Annotation,一组<>中可以有很多个表达式。
^BV rOeh+|0 float3 OmniPos : POSITION;
dv'}e4s@A0 texture TexMap < string name = "test.dds"; >;奥古多媒体"RvJPEW!a
奥古多媒体 oT.[3wg{iR:u8fD
一般来讲,Semantic是告诉应用程序或D3D这个被修饰的变量是做什么用的,Annotation是告诉程序这个变量怎么用。很云山雾罩是吗,是这样,在应用程序代码中,是可以调用D3D的API认出Semantic和Annotation的。例如上面这两行,程序的逻辑就可能是这样:首先写主程序的甲和写Shader的乙约定好POSITION标识该变量代表灯泡A的位置,甲在程序里写:{灯泡A.位置 = XXX; 找到Shader中带POSITION的变量; 给该变量赋值为灯泡A.位置; return;} 那么甲可以不知道乙在Shader中给这个要用灯泡A位置的变量起了什么名,而且乙可以在好几个Shader中给用这个数据的变量起不同的名。然后,甲和乙再约定遇到Annotation中的“name”就将后面的字符串作为文件名建立贴图。于是甲的程序就从Shader中读出了一个文件名,建立了一个贴图以供这个texture变量使用。Semantic和Annotation大概就这么用,首先要约定好各个Semantic和Annotation都是什么意思,这是up to you的,然后就是通过它们的标识来给变量赋值或作其他辅助性工作了。奥古多媒体k!n(i8DA4P#jf

CuM#?.Ys0 既然都是做辅助说明的为什么还要分成Semantic和Annotation,我的想法是Semantic简单方便而Annotation能干的事更多。不说这个了,无关大局。要说的是,D3D也跟我们约定了一套Semantic,它们大体上都能顾名思义,控制流
/ud"Y| _&Ud0 奥古多媒体 g]/i;L.E
控制流,就是if…else,for,while什么的。在CPU中,这些控制流造成的实际上是指令跳转。但在GPU中指令跳转并不被广泛的支持,以往的大部分显卡只懂得按顺序一句一句执行指令。因此HLSL的编译器可能会做出诸如展开循环、遍历分支等等莽撞的事来适应显卡。所以使用时要特别小心,而且不是所有情况的控制流语句都被支持。奥古多媒体!r(~4l)a ?+B%xB#o
奥古多媒体@#y_R3B1x.i G]
函数
6J8x.P ^j$@&H"Q0
e*^(X o c"F!N\0 HLSL中提供了很多函数可供调用,在Direct3D 文档 -> DirectX Graphics -> Reference -> HLSL Shader Reference -> HLSL Intrinsic Functions中有这些函数的详细列表。也可自己写函数用,但是在较早的Shader版本中,就像内联函数一样编译时最终要将函数展开插入到函数调用处。还有一点我想你一定会想到的就是主函数会是什么。Vertex Shader和Pixel Shader各自需要一个主函数,由程序员来指定!没错,程序员在Shader外部指定。奥古多媒体3E&uDECL [PNm

A;?;n{)Q*c9o5O-Qu$z p0 更多讨论参考:http://www.aougu.net/bbs/index.php?...:flat&tid=28585
顶:26 踩:19
对本文中的事件或人物打分:
当前平均分:-0.29 (122次打分)
对本篇资讯内容的质量打分:
当前平均分:-0.14 (106次打分)
【已经有97人表态】
18票
感动
11票
路过
13票
高兴
10票
难过
11票
搞笑
12票
愤怒
13票
无聊
9票
同情
上一篇 下一篇

网络资源


音乐
嫁衣 画心 歌曲 天亮了 青花瓷 那滋味 Nobody 没有如果 不了了之 爱的华尔兹 生生世世爱 i miss you 说好的幸福呢 如果我变成回忆 在心里从此永远有个你
火苗 心碎 稻香 带我走 我知道 爱得起 我叫mt 类似爱情 明天过后 一定要爱你 等爱的玫瑰 原谅我一次 丢了幸福的猪 斯琴高丽的伤心 这一生回忆有你就足够
白狐 偏爱 犯错 下雨天 小酒窝 樱花草 此生不换 分身情人 郎的诱惑 姑娘我爱你 寂寞才说爱 关不上的窗 一个人的浪漫 即使知道要见面 不是因为寂寞才想你
拾忆 王妃 心墙 全是爱 棉花糖 最天使 少女时代 爱丫爱丫 星空物语 我要的飞翔 我们都一样 我叫小沈阳 爱我就跟我走 让我为你唱首歌 爱上你等于爱上了错