转载自:
http://hi.baidu.com/lovebirds/blog/item/33d450af4a2f19f3fbed509b.htmlD3DFVF浅谈
有些新手不知道什么是D3DFVF ,这里做个简单介绍,和一些应用。但关于D3DFVF 最官方的资料还是看SDK(但它是英文的)。
D3DFVF_XYZ——顶点的三维坐标,表示有位置,而且会又Direct3D进行矩阵变换;
D3DFVF_XYZRHW——即平时所说rhw,它说明顶点有位置,而且经过了矩阵变换,不用在由Direct3D对它进行变换,通常用于做UI(用户界面);
D3DFVF_DIFFUSE——表示顶点格式中有漫反射颜色;
D3DFVF_NORMAL——表示顶点有法线向量;
D3DFVF_TEX^——表示顶点有纹理坐标,^可以是1至8,表示有多少套纹理坐标;
以上是最常用的D3DFVF了,如果还要更详细,请看SDK(一半以上的够用了)。
还有一些应用方法:
1、在创建VB时,pd3dDevice->CreateVertexBuffer(3*sizeof(Vertex),D3DUSAGE_WRITEONLE,FVF,D3DPOOL_MANAGED,&先前声明的VB,NULL);
在此之前还要先定义FVF:
#define FVF (D3DFVF_XYZ|D3DFVF_DIFFUSE)//这里随自己需要
还要定义自己的顶点结构,这个FVF,顶点结构可以这样:
struct Vertex
{
float x,y,z;//对应D3DFVF_XYZ
DWORD diffuse;//对应D3DFVF_DIFFUSE
};
2、我们很多时候要用到ID3DXMesh,但它的顶点用矩阵变换还不够,不能满足骨骼动画的需求,所以只能用Vertex Shader和ID3DXMesh::LockVertexBuffer()了,这里重点说LockVertexBuffer()。
首先,我们不知到Mesh的格式,如果贸然用LockVertexBuffer()会出错,所以先统一Mesh的顶点格式:
ID3DXMesh Mesh;
..........
Mesh->CloneMeshFVF (D3DXMESH_MANAGED,D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE|D3DXFVF_TEX1),pdev,&Mesh);
重新定义结构Vertex:
struct Vertex
{
float x,y,z;//对应D3DFVF_XYZ
float nx,ny,nz;//对应D3DFVF_NORMAL
DWORD diffuse;//对应D3DFVF_DIFFUSE
float u,v;//对应D3DFVF_TEX1
};
之后就可以Lock了:
Vertex *v;
int numV=Mesh->GetNumVertices();//Mesh的顶点数量
Mesh->LockVertexBuffer(NULL,(void**)&v);
for(int i=0;i<count;i++)
{
v[i].x+=5;//这里就是实现,可以任意把v[i]的数据调整
}
Mesh->UnlockVertexBuffer();//解Lock
http://bbs.gameres.com/showthread.asp?threadid=29618
D3DFVF_XYZ 和 D3DFVF_XYZRHW 的区别
学习D3D9的时候遇到灵活顶点格式(FVF)中D3DFVF_XYZRHW和D3DFVF_XYZ之间差异而引起的问题。
参看了同是C++博客的一篇博文,其分析如下:
在顶点结构体中没有RHW时,Direct3D将执行视、投影、世界等变换以及进行光线计算,之后你才能在窗口中得到你所绘制的物体。当顶点结构体中有RHW时,就像上面那段英文所述,告知Direct3D使用的顶点已经在屏幕坐标系中了,不再执行视图、投影、世界等变换和光线计算,因为D3DFVF_XYZRHW标志告诉它顶点已经经过了这些处理,并直接将顶点进行光栅操作,任何用SetTransform进行的转换都对其无效。不过这时的原点就在客户区的左上角了,其中x向右为正,y向下为正,而z的意义已经变为z-buffer的象素深度。
值得注意的是D3DFVF_XYZRHW和D3DFVF_XYZ、D3DFVF_NORMAL不能共存,因为后两个标志与前一个矛盾。在使用这种顶点时,系统需要顶点的位置已经经过变换了,也就是说x、y必须在屏幕坐标系中,z必须是z-buffer中的象素深度,取值范围:0.0-1.0,离观察者最近的地方为0.0,观察范围内最远可见的地方为1.0。
---------------------------------------------------------------------------------------------------------------------------------------------------------------
结合我自己的试验,有一些发现,记录下来以备忘。
D3DFVF_XYZ默认的用户区中心坐标是(0,0),而D3DFVF_XYZRHW是左上角为(0,0)
用D3DFVF_XYZ默认的为非光照的,而D3DFVF_XYZRHW是高洛德光照。
当使用D3DFVF_XYZ时,要设置渲染状态:
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING,FALSE)
而且要设置观察矩阵和投影矩阵,例如:
D3DXMATRIX matProj;
D3DXMATRIX matView;
// Create and set the projection matrix
D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4.0f, 1.33333f, 1.0f, 1000.0f);
g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);
// Create and set the view matrix
D3DXMatrixLookAtLH(&matView, \
&D3DXVECTOR3(0.0f, 0.0f, -500.0f), \
&D3DXVECTOR3(0.0f, 0.0f, 0.0f), \
&D3DXVECTOR3(0.0f, 1.0f, 0.0f));
g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView);
否则没有渲染结果。
另外一个帖子:http://bbs.gameres.com/showthread.asp?threadid=121111
Re:D3DFVF_XYZRHW 中的W跟Z分别表示什么
D3DFVF_XYZRHW的格式是(x,y,z,1/w),RHW是指W的倒数。
使用这个格式的顶点是不通过顶点变换的,也就是直接对应窗口设备坐标系,这个坐标系下Z的范围是[0,1]
(x,y,z)的形式是仿射坐标,(x,y,z,w)的形式是齐次坐标,详细的可以去看数学参考书。在这里由于已经是设备坐标系了,所以一般情况下w只用1.0。但如果是自己做的三维空间变换得到的坐标,那么w就很重要,因为它要用于纹理的透视矫正。
最后一个帖子:http://hi.baidu.com/microsoftxiao/blog/item/4108ce58fab4ed87800a18f8.html
D3DFVF_XYZ D3DFVF_XYZRHW区别
D3DFVF_XYZ - 顶点格式包括未变换的顶点位置。这个标记不能和D3DFVF_XYZRHW一起使用。
D3DFVF_XYZRHW - 顶点格式包括变换后的顶点位置。这个标记不能和D3DFVF_XYZ或D3DFVF_NORMAL
一起使用。
[注意] 使用D3DFVF_XYZRHW时,RHW分量应设置为>=1.0f,只有这样才表明该顶点为变换后的。
一定要了解DirectX SDK里DX90SDK\Samples\C++\Direct3D\Tutorials\Tut02_Vertices下的例子,
了解到D3DFVF_XYZ D3DFVF_XYZRHW的区别。