首页>
技术资讯>
详情

详细介绍Vertex Shader 结构

2016-05-29 来源:CloudBest 阅读量: 1,004
关键词: 程序设计


  我们将通过下面这个Vertex Shader结构的图形模型来进入Vertex Shader的世界:
  

 

  在Vertex Shader中的所有数据都被表现为128-bit的四元数(4 x 32-bit):
  
 

  因为使用一个指令但处理一组数据,一个Vertex Shader的硬件可以被看成是一个典型的SMID(单指令多数据)处理器。Vertex Shader使用的这种数据格式非常的有用,因为大多数的转换和光线计算的进行都需要使用4 x 4的矩阵或者 四元组。
  
  Vertex Shader指令非常的简单和容易理解。因为Vertex Shader不允许任何的循环,跳转和条件分支,这意味着它仅仅是线性的执行程序,一个指令接着一个指令。Vertex Shader的程序在Directx 8.1中最长为128个指令。我们可以结合几个Vertex Shader使用, 一个计算转换,一个计算光照。但是在同一时候仅仅只有一个Verthex Shader可以被激活,并且激活的Vertex Shader必须要计算每个顶点所有需要的输出数据。
  
  一个Vertex shader使用16个输入寄存器(v0-v15,每一个寄存器都由128位的四元浮点数构成)来读取输入的数据。通过输入寄存器,Vertex shader可以非常容易的表示一个典型顶点的数据:位置坐标,法线,漫反射颜色和镜面反射颜色,雾坐标和贴图大小信息。
  
  常量寄存器在vertex shader开始执行指定程序之前被CPU加载。常量寄存器是只读的, 一般用于储存例如光源位置、材质、特殊动画所需数据等参数。常量寄存器可以通过地址寄存器a0.x来间接寻址。常量寄存器除了在vertex shader中还可以在程序中被使用,但是在每一条指令中仅仅可以引用一个常量就寄存器。如果一条指令需要引用超过一个的常量寄存器,它只能通过暂存寄存器来引用。一般的常量寄存器为c0-c95,但在ATI RADEOM 8500中是c0-c191。
  
  暂存寄存器由12个寄存器组成,是可读写的,可以用于数据的存储和读取。它们分别是r0-r11。
  
  根据具体的硬件的不同,有至少13个输出寄存器。每个输出寄存器都以o打头。输出寄存器在光栅化时可以被使用。存在输出寄存器中的最终结果是另外的一个顶点,一个转换入“同源剪裁空间”的顶点。下面的表中列出了所有可用的寄存器:
  
 

  Vertex Shader编程概览
  
  因为在同一个时候仅仅有一个Vertex shader可以被激活,为每一个基本的功能块编写一个vertex shader是一个不错的主意。一般来说在不同的vertex shader之间切换的性能消耗要比变换一个贴图的性能消耗都要小。所以如果一个物体需要一种特殊的转换或者灯光,最好就在它的任务中给它一个恰当的vertex shader。让我们看看下面的例子:
  
  你在一个外星球遇难了,身上穿着正规军的盔甲,但仅仅装备着一个锯子。当你在一个烛光照耀着的地下室穿行时,一个怪物出现了,然后你就躲到了一个在任何星球都很常见的箱子后面。在考虑你作为一个使用锯子拯救这个世界的英雄的命运同时,我们开始计算这个场景所需要的vertex shader数目。
  
  首先需要一个vertex shader作为怪物的动画需要,光照渲染和可能存在的环境反射渲染。其他的vertex shader将分配给地板,墙,箱子,视角,烛光和你的锯子。或许地板,墙,箱子和锯子可以使用同一个shader,但是烛光和视角必须要有不同的shader。这依赖于你的设计和特定图形硬件的性能。
  
  每一个vertex shader驱动的程序都必须要有下面的几个步骤:
  
  通过检查D3DCAPS8::VertexShaderVersion来确定 vertex shader有无被支持。
  
  使用D3DVSD_*宏来定义 vertex shader,使 vertex shader 的流映射到输入寄存器
  
  使用SetVertexShaderConstant() 来设定vertex shader常量寄存器
  
  使用D3DXAssembleShader*() 编译刚才所写的vertex shader(或者,你可以预编译vertex shader 使用一个shader编译器)
  
  使用CreateVertexShader() 创建一个vertex shader句柄
  
  使用SetVertexShader()将vertex shader与一个特定的物体相连
  
  使用DeleteVertexShader() 删除vertex shader
  
  
  检查Vertex Shader的支持状况
  检查如果缺少一些特殊功能的支持,程序应该使用默认的行为(例如使用T&L)或者给用户一个提示,使用户做一些使这些特殊功能得以支持的事(就是提示他们可以购买新的显卡了^_^)。下面的代码段检查vertex shader 1.1是否被支持了:
  
  if( pCaps->VertexShaderVersion < D3DVS_VERSION(1,1) )
  return E_FAIL;
  在程序启动阶段,必须通过GetDeviceCaps()函数来得到一个D3DCCAPS8的结构caps。如果你使用Directx 8.1 SDK中提供的Directx框架来搭建你的应用程序,这个会被自动完成。如果检查后发现你的硬件不支持你需要的vertex shader版本,你必须通过设置D3DCREATE_SOFTWARE_VERTEXPROCESSING 属性调用CreateDevice()来切换使用软件vertex shader。这时将由对Intel和AMD不同CPU进行优化过的软件接口来进行vertex shader执行。
  
  下面是不同版本Directx支持的vertex shader的版本:
  
 

  在1.0和1.1之间的唯一区别就是对于a0寄存器的支持。Directx 8.0和Directx 8.1对应的光栅化器(rasterizer)和Inter、AMD为他们各自CPU所写的软件模拟接口都支持1.1版本。在本文写成之时,市面上支持1.1的硬件只有GeForce3/4TI、RADEON 8500,同时要注意的是并没有只支持1.0版本的显卡,支持1.0的也肯定支持1.1,1.0只是一个过渡版本。
  
  Vertex Shader定义
  
  你必须在使用Vertex Shader前定义它。它的定义可以通过一个静态的外部接口来完成。看起来有可能是这个样子:
  
  float c[4] = {0.0f,0.5f,1.0f,2.0f};
  DWORD dwDecl0[] = {
  D3DVSD_STREAM(0),
  D3DVSD_R

热门推荐 查看更多