注明:摘自七星重剑的BLOG
纹理(Texture)&取样器(Sampler) 这
俩东西可以看作特殊类型变量。纹理就是Shader中用到的贴图资源,这我想没什么好说的。来解释一下取样器:实际上每张贴图在使用的时候都要用一个取样
器。取样器相当于这样一个结构,除了保存贴图本身数据之外,还包括过滤参数等取样信息。通常,读取贴图这样的指令接收的都是取样器类型的参数而并非直接接
收纹理贴图。声明及使用纹理或取样器跟使用普通变量一样。这里有一些初始化取样器的方法,还是等到后面的实例中讲述吧。
Semantic & Annotation
任
何类型的变量(包括纹理和取样器),我们都可以用Semantic或Annotation修饰来起到一些特殊作用。Semantic暂时翻译成语义;
Annotation暂时翻译成注解,这是HLSL中独特的东西。下面这两行中,第一个变量冒号后面的POSITION就是Semantic,第二个变量
后面用一对尖括号<>圈起来的表达式就是Annotation,一组<>中可以有很多个表达式。
float3 OmniPos : POSITION;
texture TexMap < string name = "test.dds"; >;
一般来讲,
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的,然后就是通过它们的标识来给变量赋值或作其他辅助性工作了。
既然都是做辅助说明的为什么还要分成Semantic和Annotation,我的想法是Semantic简单方便而Annotation能干的事更多。不说这个了,无关大局。要说的是,D3D也跟我们约定了一套Semantic,它们大体上都能顾名思义,控制流
控
制流,就是if…else,for,while什么的。在CPU中,这些控制流造成的实际上是指令跳转。但在GPU中指令跳转并不被广泛的支持,以往的大
部分显卡只懂得按顺序一句一句执行指令。因此HLSL的编译器可能会做出诸如展开循环、遍历分支等等莽撞的事来适应显卡。所以使用时要特别小心,而且不是
所有情况的控制流语句都被支持。
函数 HLSL
中提供了很多函数可供调用,在Direct3D 文档 -> DirectX Graphics -> Reference ->
HLSL Shader Reference -> HLSL Intrinsic
Functions中有这些函数的详细列表。也可自己写函数用,但是在较早的Shader版本中,就像内联函数一样编译时最终要将函数展开插入到函数调用
处。还有一点我想你一定会想到的就是主函数会是什么。Vertex Shader和Pixel
Shader各自需要一个主函数,由程序员来指定!没错,程序员在Shader外部指定。