Shader的使用

转自http://www.cppblog.com/palm/archive/2010/02/26/108511.html

一直比较纠结DX或者opengl中哪些函数是归cpu调用,哪些又在gpu被使用的情况下哪些cpu函数又会失效,看了这个贴有点恍然大悟的感觉,突然好想回去再学习cuda,但愿在图书馆能够成功预约到这本书。

 

    Shader Model 1.0-3.0的版本,Shader分为Vertex Shader和Pixel Shader两种。没有规定要同时使用这两种Shader,可以只使用Vertex Shader,Pixel Shader的部分使用Fixed Function Pipeline,当然反过来也可以。
Shader程序是被动的,它们不会主动加载,也不会主动运行,要有CPU来加载Shader用调用它们去运行。Direct3D中的SetVertexShader和SetPixelShader用来告诉GPU接下来运行哪一组Shader。设置好Shader后,接下来调用DrawPrimitive和DrawIndexedPrimitive等函数来绘图时,就会使用这一组Shader来处理Vertex和Pixel。
     GPU在运行Vertex Shader处理顶点时,会自动把顶点数据区Vertex Buffer中属于个别不同顶点的数据传递给Vertex Shader。Vertex Shader在运行时,只能看到单一顶点的数据,也就是它被分配到得那个顶点。要读取其他的顶点并不是不可行,但要通过一些技巧来传递数据。Vertex Shader无法随机读取Vertex Buffer,它不能把Vertex buffer 作为数组来使用。
除了从Vertex Buffer中获得数据外,Vertex Shader还可以从常量寄存器Constant Registers 的空间中读取数据。CPU要把数值放在常量寄存器中供Vertex Shader使用。常量寄存器中的数值对Vertex Shader来说是只读的数据。常量寄存器中的数值时全局的,每个顶点在运行Vertex Shader时都会读取到相同的内容。越新版本的Shader支持越多的常量寄存器。
在Direct3D中使用Shader时,Fixed Function Pipeline中设置光源、纹理和矩阵等的函数都会失效。这些数据都要通过CPU放进常量寄存器,让GPU使用。
     Shader Model 3.0的Vertex Shader还支持读取贴图的功能,虽然Vertex Shader并不能直接填充Framebuffer画面,但是读取贴图仍然有用处。2D贴图可以视为一个可以被Vertex Shader自由读取的二维数组,我们通常不会使用一张很漂亮的贴图给Vertex Shader使用,Vertex Shader所使用的贴图往往只是一堆非图片数值数据。
Vertex Shader计算好的顶点数据通常并不会、也没必要保存在内存中。这些转换后的三角形顶点数据会通过GPU的内插器Interpolator,把内插结果传递给下一步的Pixel Shader来填充三角形,画好三角形后就把这些数据丢弃。
Vertex Shader处理好顶点后,GPU会使用Pixel Shader来填充转换过后的三角形。GPU会通过转换到屏幕坐标系上的三角形的三个顶点,来判断画面上有哪些像素会落在这个三角形内部,然后对三角形内部的每个像素进行Pixel Shader来着色。
     Pixel可以读取的数据源主要是贴图和常量寄存器。Vertex Shader和Pixel Shader所使用的常量寄存器是两组不同的寄存器。Pixel Shader的常量寄存器同样是全局的,在同一个绘图指令中,每个像素运行Pixel Shader时都会看到相同的常量寄存器内容。除了贴图和常量寄存器外,Pixel Shader还可以通过GPU的内插器来获得三角形3个顶点上通过Vertex Shader计算出来的数据。最常见的就是把不同顶点间的贴图坐标内插,Pixel Shader再使用内插过后的坐标来读取贴图。
Geometry Shader是Shader Model 4.0新增的功能,它可以用来改变几何图形的输出数量和排列方法。在Shader Model 1.0-3.0中,当程序调用DrawPrimitive时,就已经决定要画几个图形了。Geometry Shader是一个新的流程,它是在运行完Vertex Shader后且还没有使用Pixel Shader来着色之前运行。它可以重新组合,过滤Vertex Shader所计算过后的顶点或自行生成顶点来穿件的几何图形。
Shader Model 4.0不再使用常量寄存器,而是使用常量缓存Constant Buffer。常量寄存器和常量缓存在使用上没什么差别,比较大的差别是,如果Vertex Shader 和 Pixel Shader使用同一块常量缓存,它们就可以读取相同的数据。
有些Direct3D9 的函数是给Fixed Function Pipeline专用的,例如设置矩阵的SetTransform、设置纹理的SetMaterial,以及设置光源的SetLight。这几个函数在使用Shader时都会无效,程序员要把这些数据改放在常量寄存器中让Shader读取。

 

posted @ 2010-12-15 21:45  数据牛仔  阅读(1914)  评论(0编辑  收藏  举报