洛下闲才子

导航

 

5. Vertex Assembly(顶点装配)与数据流

Dx8 首度引入了数据流的概念。

一个顶点有个顶点由n个数据流组成

一个数据流由m个元素组成

一个元素是[位置、颜色、法向、纹理坐标]的一个或集合

IDirect3DDevice9::SetStreamSource思路方法把多个顶点缓存Cache绑定到多个设备数据流,这样就在顶点数据和顶点数据流端口的间建立了联系,有多个数据流端口用来给图元处理输入数据,对数据流中数据真正引用只有在诸如IDirect3DDevice9::DrawPrimitive的类绘制思路方法时才发生。DrawPrimitive中的Vertex Assembly阶段会将多个数据流进行装备 变为一个完整的顶点数据。提高了变化。

问题: DrawPrimitiveUp 和 DrawIndexedPrimitiveUp 存在这个吗?

“为什么要使用数据流?”和“数据流可以解决什么问题?”

数据流最大好处是消除了原来和多重纹理有关顶点数据开销。在引入数据流的前为了处理单纹理和多重纹理情况,用户要么复制两份顶点数据每份顶点数据中都没有用不到数据;要么在每份顶点数据中包含所有数据元素但其中部分数据除了多重纹理情况以外不会被用到。

这里是个使用两份顶点数据举例份用于单纹理另份用于多重纹理

structCUSTOMVERTEX_TEX1

{

FLOATx,y,z;//未经变换顶点位置

DWORDdfColor;//顶点漫反射色

DWORDspecColor;//顶点镜面反射色

floattu_1,tv_1;//单纹理纹理坐标

};

structCUSTOMVERTEX_TEX2

{

FLOATx,y,z;//未经变换顶点位置

DWORDdfColor;//顶点漫反射色

DWORDspecColor;//顶点镜面反射色

floattu_2,tv_2;//多重纹理纹理坐标

};

另种思路方法是在个顶点元素中包含全部两组纹理坐标

structCUSTOMVERTEX_TEX2

{

FLOATx,y,z;//未经变换顶点位置

DWORDdfColor;//顶点漫反射色

DWORDspecColor;//顶点镜面反射色

floattu_1,tv_1;//单纹理纹理坐标

floattu_2,tv_2;//多重纹理纹理坐标 [Page]

};

如果使用这份顶点数据那么只要在内存中保存每份顶点和颜色数据,代价是在渲染过程中保存了全部两组纹理坐标,甚至在单纹理情况下也是如此。

多数据流主要为了解决数据冗余。

现在这其中权衡已经很清楚了。数据流为这种左右为难情况提供了种极好解决方案这里提供了套顶点定义用来支持, 3个数据流:一个数据流包含位置和颜色,一个数据流包含第组纹理坐标,另个数据流包含第 2组纹理坐标。

//多数据流顶点

//数据流0,位置,漫反射色,镜面反射色

structPOSCOLORVERTEX

{

FLOATx,y,z;

DWORDdfColor,specColor;

};

#D3DFVF_POSCOLORVERTEX(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_SPECULAR)

//数据流1,纹理坐标组0

structTEXC0VERTEX

{

FLOATtu1,tv1;

};

#D3DFVF_TEXC0VERTEX(D3DFVF_TEX1)

//数据流2,纹理坐标组1

structTEXC1VERTEX

{

FLOATtu2,tv2;

};

#D3DFVF_TEXC1VERTEX(D3DFVF_TEX0)

顶点定义为:

//多重纹理–多重数据流

D3DVERTEXELEMENT9dwDecl3=

{

{0,0,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_POSITION,0},

{0,12,D3DDECLTYPE_D3DCOLOR,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_COLOR,0},

{0,28,D3DDECLTYPE_D3DCOLOR,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_COLOR,1},

{1,0,D3DDECLTYPE_FLOAT2,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_TEXCOORD,0},

{2,0,D3DDECLTYPE_FLOAT2,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_TEXCOORD,0},

D3DDECL_END

};

现在创建顶点声明对象如下所示:

LPDIRECT3DVERTEXDECLARATION9m_pVertexDeclaration;

g_d3dDevice->CreateVertexDeclaration(dwDecl3,m_pVertexDeclaration);

组合举例

一个数据流只使用漫反射色

只用漫反射色渲染顶点声明和数据流设置看起来会如下所示:

D3DVERTEXELEMENT9dwDecl3=

{

{0,0,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_POSITION,0},

{0,12,D3DDECLTYPE_D3DCOLOR,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_COLOR,0},

{0,28,D3DDECLTYPE_D3DCOLOR,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_COLOR,1}, [Page]

D3DDECL_END

};

m_pd3dDevice->SetStreamSource(0,m_pVBVertexShader0,0,(CUSTOMVERTEX));

m_pd3dDevice->SetStreamSource(1,NULL,0,0); //第一 第二数据流设空

m_pd3dDevice->SetStreamSource(2,NULL,0,0);

两个数据流使用颜色和纹理

使用单纹理进行渲染顶点声明和数据流设置看起来会如下所示:

D3DVERTEXELEMENT9dwDecl3=

{

{0,0,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_POSITION,0},

{0,12,D3DDECLTYPE_D3DCOLOR,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_COLOR,0},

{0,28,D3DDECLTYPE_D3DCOLOR,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_COLOR,1},

{1,0,D3DDECLTYPE_FLOAT2,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_TEXCOORD,0},

D3DDECL_END

};

m_pd3dDevice->SetStreamSource(0,m_pVBPosColor,0,(POSCOLORVERTEX));

m_pd3dDevice->SetStreamSource(1,m_pVBTexC0,0,(TEXC0VERTEX));

m_pd3dDevice->SetStreamSource(2,NULL,0,0);

3个数据流使用颜色和两张纹理

使用两张纹理进行多重纹理渲染顶点声明和数据流设置看起来会如下所示

D3DVERTEXELEMENT9dwDecl3=

{

{0,0,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_POSITION,0},

{0,12,D3DDECLTYPE_D3DCOLOR,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_COLOR,0},

{0,28,D3DDECLTYPE_D3DCOLOR,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_COLOR,1},

{1,0,D3DDECLTYPE_FLOAT2,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_TEXCOORD,0},

{2,0,D3DDECLTYPE_FLOAT2,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_TEXCOORD,0},

D3DDECL_END

};

m_pd3dDevice->SetStreamSource(0,m_pVBPosColor,0,(POSCOLORVERTEX));

m_pd3dDevice->SetStreamSource(1,m_pVBTexC0,0,(TEXC0VERTEX));

m_pd3dDevice->SetStreamSource(2,m_pVBTexC1,0,(TEXC1VERTEX));

以上所有 3种情况都可以以下IDirect3DDevice9::DrawPrimitive [Page]

m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,0,NUM_TRIS);

这个例子显示了数据流在解决重复数据/冗余数据在总线上传输(也就是说带宽浪费)问题上灵活性。

6. 根据DWORD格式的顶点声明来生成顶点结构: (template版本) 作用不大

网上抄的。

以前方泓写过一个 ,那个是用宏来实现,因为不符合C++ stand只能在特定编译器上用(用代码替换实现模板的,我试过vc6和gcc是可以的),vc7下编译不能通过。
最[来源:GameRes.com]近研究c+模板,另外写了个可以在vc7上编译的。
这里还有个学WTL时写的fvf工具,用来自动生产struct和format的代码。可以用这个生成宏来做模板参数.

因为某些顶点格式本人并未用过,可能代码会有bug,如有问题请告知在下。

*-------------------------代码-----------------------------------*
//D3d9Fvf struct generate templates
//Author Kevinqing <qingzl@cdgwbn.com.cn>
//if you find any bugs,please let me know.

#include <d3d9.h>
//-----------posoition-------------
namespace _D3DFvf{
template <bool b>struct  pos_t;
template <> struct pos_t<true>{
union {
D3DVECTOR v;
struct{
float x,y,z;
};
};
};
//-----------RHW-------------------
template <bool b>struct rhw_t;
template <> struct rhw_t<false>{};
template <> struct rhw_t<true>{
float rhw;
};
//-----------W---------------------
template <bool b>struct w_t;
template <> struct w_t<false>{};
template <> struct w_t<true>{
DWORD w;
};
//-----------normal----------------
template <bool b>struct n_t;
template <> struct n_t<false>{};
template <> struct n_t<true>{
D3DVECTOR n;
};

//-----------psize-----------------
template <bool b>struct psize_t;
template <> struct psize_t<false>{};
template <> struct psize_t<true>{
float psize;
};
//-----------diff-------------------
template <bool b>struct diff_t;
template <> struct diff_t<false>{};
template <> struct diff_t<true>{
D3DCOLOR diff;
};

//-----------spec-------------------
template <bool b>struct spec_t;
template <> struct spec_t<false>{};
template <> struct spec_t<true>{
D3DCOLOR spec;
};

#define TestFlag(a,b,m) (bool((a&m)==b))
#define tp(a,b) TestFlag(a,b,D3DFVF_POSITION_MASK)

#define TestMask(a,b) (bool((a&b)!=0))
//----------b/i----------------------
#define IsXYZBn(a) (tp(a,D3DFVF_XYZB1)||\
tp(a,D3DFVF_XYZB2)||\
tp(a,D3DFVF_XYZB3)||\
tp(a,D3DFVF_XYZB4)||\
tp(a,D3DFVF_XYZB5))

#define XYZBn(a) (tp(a,D3DFVF_XYZB1)? 1:(\
tp(a,D3DFVF_XYZB2)? 2:(\
tp(a,D3DFVF_XYZB3)? 3:(\
tp(a,D3DFVF_XYZB4)? 4:(\
tp(a,D3DFVF_XYZB5)? 5:0)))))

template <bool b,int i>struct b_t;
template <int i>struct b_t<false,i>{};
template <>struct b_t<true,1>{
union{
float b;
DWORD i;
};
};
template <>struct b_t<true,2>{
union{
float b[2];
DWORD i[2];
};
};
template <>struct b_t<true,3>{
union{
float b[3];
DWORD i[3];
};
};
template <>struct b_t<true,4>{
union{
float b[4];
DWORD i[4];
};
};
template <>struct b_t<true,5>{
union{
float b[5];
DWORD i[5];
};
};

//--------------TEX-----------
#define TEXn(a) ((a&D3DFVF_TEXCOUNT_MASK)>>D3DFVF_TEXCOUNT_SHIFT)
#define _D3DFVF_TEXFMT(a,l) ((a>>(l*2+16))&3)
#define TEX_CORDn(a,l) ((_D3DFVF_TEXFMT(a,l)==D3DFVF_TEXTUREFORMAT1) ?1:(\
(_D3DFVF_TEXFMT(a,l)==D3DFVF_TEXTUREFORMAT2) ?2:(\
(_D3DFVF_TEXFMT(a,l)==D3DFVF_TEXTUREFORMAT3) ?3:4)))

#define DECL_TEXCORD_T(N) \
template <bool b,int n>struct texcord ## N ##_t;\
template <int n>struct texcord##N##_t<false,n>{};\
template <>struct texcord##N##_t<true,1>{\
float tu##N;\
};\
template <>struct texcord##N##_t<true,2>{\
float tu##N;\
float tv##N;\
};\
template <>struct texcord##N##_t<true,3>{\
float tu##N;\
float tv##N;\
float ta##N;\
};\
template <>struct texcord##N##_t<true,4>{\
float tu##N;\
float tv##N;\
float ta##N;\
float tb##N;\
};

DECL_TEXCORD_T(0)
DECL_TEXCORD_T(1)
DECL_TEXCORD_T(2)
DECL_TEXCORD_T(3)
DECL_TEXCORD_T(4)
DECL_TEXCORD_T(5)
DECL_TEXCORD_T(6)
DECL_TEXCORD_T(7)
template <const DWORD flag>
struct tex_t: public texcord0_t<(TEXn(flag)>0),TEX_CORDn(flag,0)>,
public texcord1_t<(TEXn(flag)>1),TEX_CORDn(flag,1)>,
public texcord2_t<(TEXn(flag)>2),TEX_CORDn(flag,2)>,
public texcord3_t<(TEXn(flag)>3),TEX_CORDn(flag,3)>,
public texcord4_t<(TEXn(flag)>4),TEX_CORDn(flag,4)>,
public texcord5_t<(TEXn(flag)>5),TEX_CORDn(flag,5)>,
public texcord6_t<(TEXn(flag)>6),TEX_CORDn(flag,6)>,
public texcord7_t<(TEXn(flag)>7),TEX_CORDn(flag,7)>
{

};

};//end of _D3DFvf

template <const DWORD Flags>
struct D3DFvf: public _D3DFvf::pos_t<TestMask(Flags,D3DFVF_POSITION_MASK)>,
public _D3DFvf::rhw_t<tp(Flags,D3DFVF_XYZRHW)>,
public _D3DFvf::w_t<tp(Flags,D3DFVF_XYZW)>,
public _D3DFvf::b_t<IsXYZBn(Flags),XYZBn(Flags)>,
public _D3DFvf::n_t<TestMask(Flags,D3DFVF_NORMAL)>,
public _D3DFvf::psize_t<TestMask(Flags,D3DFVF_PSIZE)>,
public _D3DFvf::diff_t<TestMask(Flags,D3DFVF_DIFFUSE)>,
public _D3DFvf::spec_t<TestMask(Flags,D3DFVF_SPECULAR)>,
public _D3DFvf::tex_t<Flags>

{

};
#undef TestFlag
#undef TestMask
#undef tp
#undef XYZBn
#undef IsXYZBn
#undef TEXn
#undef _D3DFVF_TEXFMT
#undef TEX_CORDn
#undef DECL_TEXCORD_T

const DWORD myFvfFmt=D3DFVF_....|....;
typedef D3DFVf<myFvfFmt> MY_FVFFMT;
typedef D3DFVf<myFvfFmt> *PMY_FVFFMT;

7. 世界变换。

顶点从自身坐标系向世界坐标系的转换。通常会对模型格式各样的转换结合成一个矩阵,用来设置世界变换矩阵。

SetTramsfrom(D3DTS_WORLD,…)来设置。

固定管线设置在一次设置后,会在下次进行沿用,一定要渲染注意各方面设置,通常设置完成后,重新将其设置回来。

8.世界变换的对象是顶点坐标和顶点法线

clip_image002

世界变换后的法线是世界坐标系下的,这是相对固定管线的说的。

 

今天不想写了,全部粘贴

posted on 2010-07-16 20:08  洛下闲才子  阅读(514)  评论(0)    收藏  举报