随笔 - 132  文章 - 51  trackbacks - 0
<2011年4月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

常用链接

留言簿(7)

随笔分类

随笔档案

文章分类

文章档案

cocos2d-x

OGRE

OPenGL

搜索

  •  

最新评论

阅读排行榜

评论排行榜

顶点着色器(vertex shader)是一个在图形卡的GPU上执行的程序,它替换了固定功能管线(fixed function pipeline)中的变换(transformation)和光照(lighting)阶段。(这不是百分之百的正确,因为顶点着色器可以被Direct3D运行时(Direct3D runtime)以软件模拟,如果硬件不支持顶点着色器的话)。图17.1说明了管线中顶点着色器替换的部件。

  

  从图17.1,我们知道,顶点以局部坐标输入到顶点着色器,并且必须输出齐次剪裁空间的有颜色的顶点。(经投影矩阵变换顶点后的空间称作齐次剪裁空间(homogeneous clip space)。因此,要把一个顶点从局部空间变换到齐次坐标空间,我们必须应用下列变换序列:世界变换(world transformation),视图变换(view transformation)和投影变换(projection transformation),它们分别由世界矩阵,视图矩阵和投影矩阵来完成。)对于点元(point primitive),顶点着色器也被用于操作每个顶点的顶点大小。

  由于顶点着色器是我们(在HLSL中)写的一个自定义程序,因此我们在图形效果方面获得了极大的自由性。我们不再受限于Direct3D的固定光照算法。此外,应用程序操纵顶点位置的能力也有了多样性,例如:cloth simulation,粒子系统的点大小操纵,还有顶点混合/morphing。此外,我们的顶点数据结构更自由了,并且可以在可编程管线中包含比在固定功能管线中多得多的数据。

  顶点着色器仍然是相对新的特性,并且许多图形卡不支持它们,特别是随DirectX 9发布的较新版本的顶点着色器。通过检查D3DCAPS9结构的VertexShaderVersion成员,可以测试顶点着色器的版本。下列代码段展示了这一点:

 

以下是引用片段:
 // If the device's supported version is less than version 2.0 
  if( caps.VertexShaderVersion < D3DVS VERSION(2, 0) ) 
  // Then vertex shader version 2.0 is not supported on this device.
  我们看到D3D_VERSION的两个参数分别接收主和次版本号。现在,D3DXCompileShaderFromFile函数支持顶点着色器版本1.1和2.0。

  17.1顶点声明

  我们已经使用自由顶点格式(flexible vertex format,FVF)来描述顶点结构中的各分量。但是,在可编程管线中,顶点数据包含的数据比用FVF所能表达的多很多。因此,我们通常使用更具表达性并且更强大的顶点声明(vertex declaration)。注意:如果FVF能够描述我们的顶点格式我们仍然可以在可编程管线中使用它。不管用何种方法,只是为了方便,同样FVF会在内部被转换为一个顶点声明。

  17.1.1 描述顶点声明

  我们将一个顶点声明描述为一个D3DVERTEXELEMENT9结构的数组。D3DVERTEXELEMENT9数组中的每个成员描述了一个顶点的分量。所以,如果你的顶点结构有三个分量(例如:位置、法线、颜色),那么其相应的顶点声明将描述3个D3DVERTEXELEMENT9结构的数组。这个D3DVERTEXELEMENT9结构定义如下:

  

以下是引用片段:
typedef struct _D3DVERTEXELEMENT9 { 
  BYTE Stream; 
  BYTE Offset; 
  BYTE Type; 
  BYTE Method; 
  BYTE Usage; 
  BYTE UsageIndex; 
  } D3DVERTEXELEMENT9;
  Stream——指定与顶点分量相关联的流

  ffset——偏移,按字节,相对于顶点结构成员的顶点分量的开始。例如,如果顶点结构是:

  

以下是引用片段:
struct Vertex 
  { 
  D3DXVECTOR3 pos; 
  D3DXVECTOR3 normal; 
  };
  ……pos分量的偏移是0,因为它是第一个分量;normal分量的偏移是12,因为sizeof(pos) = 12。换句话说,normal分量以Vertex的第12个字节为开始。

  Type——指定数据类型。它可以是D3DDECLTYPE枚举类型的任意成员;完整列表请参见文档。常用类型如下:

  D3DDECLTYPE_FLOAT1——浮点数值

  D3DDECLTYPE_FLOAT2——2D浮点向量

  D3DDECLTYPE_FLOAT3——3D浮点向量

  D3DDECLTYPE_FLOAT4——4D浮点向量

  D3DDECLTYPE_D3DCOLOR—D3DCOLOR类型,它扩展为RGBA浮点颜色向量(r g b a),其每一分量都是归一化到区间[0, 1]了的。

  Method——指定网格化方法。我们认为这个参数是高级的,因此我们使用默认值,标识为D3DDECLMETHOD_DEFAULT.。

  Usage——指定已计划的对顶点分量的使用。例如,它是否准备用于一个位置向量、法线向量、纹理坐标等?有效的用途标识符(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. 
  D3DDECLUSAGE_POSITIONT = 9, // Transformed position. 
  D3DDECLUSAGE_COLOR = 10, // Color. 
  D3DDECLUSAGE_FOG = 11, // Fog blend value. 
  D3DDECLUSAGE_DEPTH = 12, // Depth value. 
  D3DDECLUSAGE_SAMPLE = 13 // Sampler data. 
  } D3DDECLUSAGE;
  D3DDECLUSAGE_PSIZE类型用于指定一个顶点的大小。它用于点精灵,因此我们可以基于每个顶点控制其大小。一个D3DDECLUSAGE_POSITION成员的顶点声明意味着这个顶点已经被变换,它通知图形卡不要把这个顶点送到顶点处理阶段(变形和光照)。

  UsageIndex——用于标识多个相同用途的顶点分量。这个用途索引是位于区间[0, 15]间的一个整数。例如,假设我们有三个用途为D3DDECLUSAGE_NORMAL的顶点分量。我们可以为第一个指定用途索引为0,为第二个指定用途索引为1,并且为第三个指定用途索引为2。按这种方式,我们可以通过其用途索引标识每个特定的法线。

  顶点描述声明的例子:假设我们想要描述的顶点格式由位置向量和三个法线向量组成。顶点声明可以指定如下:

 

以下是引用片段:
 D3DVERTEXELEMENT9 decl[] = 
  { 
  {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 
  {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 
  {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 1}, 
  {0, 36, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 2}, 
  D3DDECL_END() 
  };
  D3DDECL_END宏用于初始化D3DVERTEXELEMENT9数组的最后一个顶点元素。同样的,注意法向量的用途索引标签。

  17.1.2 创建顶点声明

  一旦你描述了一个顶点声明为D3DVERTEXELEMENT9数组,我们就可以使用下面的方法获得一个IDirect3DVertexDeclaration9接口指针:

  

以下是引用片段:
HRESULT IDirect3DDevice9::CreateVertexDeclaration( 
  CONST D3DVERTEXELEMENT9* pVertexElements, 
  IDirect3DVertexDeclaration9** ppDecl 
  );
  pVertexElements——D3DVERTEXELEMENT9结构数组,它描述我们想要创建的顶点声明。

  ppDecl——用于返回创建的IDirect3DVertexDeclaration9接口指针

  例子调用,其中decl是一个D3DVERTEXELEMENT9数组:

  IDirect3DVertexDeclaration9* _decl = 0;

  hr = _device->CreateVertexDeclaration(decl, &_decl);

  17.1.3 使用一个顶点声明

  回忆一下:自由顶点格式是一个方便的特性并且在内部转换成了顶点声明。因此,当直接使用顶点声明,我们不再需要调用:Device->SetFVF( fvf );

  相反,我们调用:Device->SetVertexDeclaration( _decl );

  其中,_decl是一个IDirect3DVertexDeclaration9接口指针。

  17.2顶点数据用途

  考虑这个顶点声明:

  

以下是引用片段:
D3DVERTEXELEMENT9 decl[] = 
  { 
  {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 
  {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 
  {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 1}, 
  {0, 36, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 2}, 
  D3DDECL_END() 
  };

我们需要一种方式,来定义一个顶点声明的元素到顶点着色器的Input结构的数据成员的映射。我们在Input结构中通过指定每个数据成员的语义(: usage-type [usage-index])定义这个映射。语义通过元素的用途类型和用途索引标识顶点声明中的一个元素。由数据成员的语义标识的顶点元素是得以映射到数据成员的元素。例如,对应于前面的顶点声明的输入结构是:
 

 

以下是引用片段:
 struct VS_INPUT 
  { 
  vector position : POSITION; 
  vector normal : NORMAL0; 
  vector faceNormal1 : NORMAL1; 
  vector faceNormal2 : NORMAL2; 
  };
  注意:如果我们遗漏了用途索引,就意味着用途索引为零。例如,POSITION和POSITION0是同一样东西。

  这里decl中的元素0,由用途POSITION和用途索引0标识,它映射到position。decl中的元素1,由用途NORMAL和用途索引0标识,它映射到normal。decl中的元素2,由NORMAL和用途索引1标识,它映射到faceNormal1。decl中的元素3,由用途NORMAL和用途索引2标识,它映射到faceNormal2。

  受支持的顶点着色器输入用途(input usage)是:

  POSITION [n]——位置

  BLENDWEIGHTS [n]——混合权重

  BLENDINDICES [n]——混合索引

  NORMAL [n]——法线向量

  PSIZE[n]——顶点大小

  DIFFUSE [n]——散射颜色

  SPECULAR [n]——镜面颜色

  TEXCOORD [n]——纹理坐标

  其中,n是一个位于区间[0, 15]的可选整数。

  此外,对于输出结构,我们必须指定每个成员是用来做什么的。例如,数据成员应该被作为位置向量、颜色、纹理坐标等对待吗?图形卡没主意,除非你强制的告诉它。这也需要通过语法的语义来完成:

 

以下是引用片段:
 struct VS_OUTPUT 
  { 
  vector position : POSITION; 
  vector diffuse : COLOR0; 
  vector specular : COLOR1; 
  };
  受支持的顶点着色器输出用途是:

  POSITION—位置

  PSIZE—顶点大小

  FOG—雾混合值

  COLOR [n]—顶点颜色。注意:可以有多个顶点颜色被输出,并且这些颜色可以被混合在一起以产生最终的颜色。

  TEXCOORD [n]—顶点纹理坐标。注意:多个顶点纹理坐标可以被输出。

  其中,n是一个位于区间[0, 15]的可选整数。

原文连接:http://www.cppblog.com/lovedday/category/6620.html

posted on 2012-01-05 10:45 风轻云淡 阅读(1236) 评论(0)  编辑 收藏 引用 所属分类: HLSL

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理