索引缓冲器:制作索引次序,并且根据这个索引次序将所有绘制的图行进行编码,这样有两个好处:
1)按照索引次序可以减少渲染顶点数目,这样可以提高性能效率。
2)索引缓冲器中的索引可以提供cache的功能,可以cache住最近用于变换和光照的顶点数据,下次使用的时候,就不用再处理了。并且在GPU里面是不知道abc, bcd里面的bc是一致的,这样除非凭借索引。一般处理的方式是尽量减少数据量,可以通过改变绘制图元的方式和顶点结构的组织格式(SetFVF,SetVertexDeclaration)。
关于绘制图元的方式(两个三角形):
1)如果是triangle list表示就是:
abcbcd
2)如果是triangle strip,就是
abcd
3)如果是index buffer + triangle list就是
abcd
012,123
4)如果是 index buffer + triangle strip就是
abcd
0123
顶点结构和索引值结构是根据绘制图元的方式来决定的,比如选择triangle strip的顶点设置跟triangle list的顶点设置就有不同.并且索引缓冲的设置是按照顺时针(DX)的形式进行编号的.
在使用图形渲染顶点的时候,如果对模型的顶点布局和顶点渲染方式有不清楚的,这样可以通过美工来获得这种信息,之前在想一架飞机的时候,都没有将模型构建起来,但是花了不少的精力在那上面,后面才想到,其实没必要将心思全部花在那里的,而可以将心思放在具体的模型导入上面,在美术那边就可以获得顶点的详细信息,这样有助于解决问题的关键,顶点布局在美术那边会得到一个比较完整的体现,而程序这边只需要知道顶点的结构就好了,比如详细的顶点结构,顶点在导入模型里面的布局等等,诸如此类的。另外还有一个点的是:其实研究顶点的话,可以将之放到模型里面去分析,这样的话,可以减少单独设计顶点带来的困扰。
摄像坐标系就是定义在摄像机的屏幕可视区域,在摄像机的坐标系中,x轴向右,z轴向前(朝向屏幕内,或者摄像机方向),y轴向上(不是世界的上方,而是摄像机的上方),
为了简化世界坐标系到物体坐标系的转换,人们引入了一种新的坐标系,称为惯性坐标系,意思是世界坐标系到物体坐标系的半途,惯性坐标系的原点跟物体坐标系的原点重合,但是惯性坐标系的轴平行于物体坐标系的轴。可以用惯性坐标系来做为物体坐标系与世界坐标系的中介:用旋转能将物体坐标系转换到惯性坐标系,用平移可以将惯性坐标系转换到物体坐标系。
物体坐标系转换成世界坐标系要经历的步骤:
1)将物体坐标顺时针45度,转换到惯性坐标系。
2)将惯性坐标系向下向右旋转到世界坐标系。
3)这样物体坐标轴顺时针45度,向下向下向右旋转到世界坐标系。
嵌套坐标系:定义了一种层次的,或者树状的坐标系.世界坐标系就是这个树的根。
对于许多向量,我们只关心它的方向而不关心她的大小,在这个情况下使用单位向量非常重要。(D3DXVec3Normalize)
一般来说,点乘描述两个向量的相似程度。点乘等于向量大小以及向量的cos值的积。
几何意义在于:a的长度与b在a上的投影长度的乘积,或者是b的长度与a在b上投影长的乘积,它是一个标量,而且可正可负,相互垂直的向量内积为0。
叉积描述的是一个向量垂直于所在的平面的两个向量(D3DXVec3Cross)。
叉积最重要的应用在于创建垂直于平面,三角形,以及多边形的向量。
p,q,r定义为x,y,z轴上面的单位向量。那么任意一个向量都可以表示为v = xp + yq + zr; 并且将,p,q,r这些称为基向量,这里基向量就是卡笛尔坐标。
一个坐标系可以用任意三个基向量表示,当然这三个基向量要线形无关。
矩阵的每一行都能解释为转换后的基向量。
可以通过想象变换后的坐标系的基向量来想象矩阵。这些基向量在2d中构成“L”形状,在3d中构架成三角架形状。
// 重新产生基向量
D3DXVec3Normalize(&vLook, &vLook); // 归一化向量,获得look方向
D3DXVec3Cross(&vRight, &vUp, &vLook); // 获得up/look法线所在平面的垂直法线
D3DXVec3Normalize(&vRight, &vRight); // 归一化向量,获得right方向
D3DXVec3Cross(&vUp, &vLook, &vRight); // 获得right/look法线所在平面的垂直法线
D3DXVec3Normalize(&vUp, &vUp);// 归一化向量,获得up方向
// Matrices for pitch, yaw and roll
// 用归一化后的向量和一个标量(角度)旋转后获得一个旋转矩阵。
D3DXMATRIX matPitch, matYaw, matRoll;
D3DXMatrixRotationAxis(&matPitch, &vRight, fPitch );
D3DXMatrixRotationAxis(&matYaw, &vUp, fYaw );
D3DXMatrixRotationAxis(&matRoll, &vLook, fRoll);
// rotate the LOOK & RIGHT Vectors about the UP Vector
// 用一个矩阵来变换一个3D向量.
D3DXVec3TransformCoord(&vLook, &vLook, &matYaw);
D3DXVec3TransformCoord(&vRight, &vRight, &matYaw);
// rotate the LOOK & UP Vectors about the RIGHT Vector
D3DXVec3TransformCoord(&vLook, &vLook, &matPitch);
D3DXVec3TransformCoord(&vUp, &vUp, &matPitch);
// rotate the RIGHT & UP Vectors about the LOOK Vector
D3DXVec3TransformCoord(&vRight, &vRight, &matRoll);
D3DXVec3TransformCoord(&vUp, &vUp, &matRoll);
D3DXVECTOR3 *WINAPI D3DXVec3TransformCoord(
D3DXVECTOR3 *pOut,
CONST D3DXVECTOR3 *pV,
CONST D3DXMATRIX *pM
);
其原理是pOut' = pV' * pM ,因为pM是4*4矩阵,这样的话,pV' = [pV 1] ,并且之后求得出来的结果向量是pOut'去掉z轴(w)得到pOut = [pOut'.x/w pOut'y/w pOut'z/w].
另外D3DXVec3TransformNormal的做法是差不多的,只是其中一项w被设置为0.
// 设置照相机矩阵,位置和方向。
static D3DXVECTOR3 vCameraLook=D3DXVECTOR3(0.0f,0.0f,1.0);
static D3DXVECTOR3 vCameraUp=D3DXVECTOR3(0.0f,1.0f,0.0f);
static D3DXVECTOR3 vCameraPos=D3DXVECTOR3(0.0f,0.0f,-5.0f);
D3DXMATRIX view;
D3DXMatrixLookAtLH (&view,&vCameraPos, // pEye = Position
&vCameraLook, // pAt
&vCameraUp); // pUp
m_pd3dDevice->SetTransform(D3DTS_VIEW, &view);
POSITION: 定义了物体的位置
LOOK: 定义了物体所指的方向
RIGHT: 定义了物体的右侧指向
UP:仅在物体会绕着LOOK向量旋转时才是必需的,表示哪个方向对于物体来说是"上"或"下"。
pitch - RIGHT
roll - LOOK
yaw - UP
LOOK移动- 改变POSITION.
m_pd3dDevice->SetTransform(D3DTS_WORLD, &m_pObjects[0].matLocal );
设置渲染纹理内容。
m_pd3dDevice->SetTexture( 0, m_pTexture );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
// Passing an FVF to IDirect3DDevice9::SetFVF specifies a legacy FVF with stream 0.
// 设置顶点格式
m_pd3dDevice->SetFVF(FVF );
// 将顶点缓冲器绑定到设备数据流。
m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(VERTEX) );
// 设置索引数据
m_pd3dDevice->SetIndices( m_pIB );
// 绘制
m_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,
0,
0,
16, // number of vertices
0,
10); // number of primitives
在旋转向量之前,必须重新归一化,因为要使向量相互垂直。
D3DXQuaternionRotationYawPitchRoll: 用给定的yaw, pitch, roll来构建四元数。
D3DXMatrixRotationQuaternion: 用四元数来构建旋转。
Qx = [cos(yaw/2) (sin(yaw/2),0,0)]
Qy = [cos(pitch/2) (0, sin(pitch/2),0)]
Qz = [cos(roll/2) (0,0,sin(roll/2))]
D3DXMatrixLookAtLH对于构建一个跟随式照相机是很有帮助的。
可以使用四元数的方式执行旋转向量:
fRoll = fPitch = fYaw = 0.0f;
D3DXVECTOR3 vPos(0.0f, 0.0f, 0.0f);
static D3DXMATRIX matView = D3DXMATRIX(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f,-5.0f, 1.0f);
// 更新位置和观察矩阵
D3DXMATRIX matR, matTemp;
// 用yaw/pitch/roll来构建四元数。
D3DXQuaternionRotationYawPitchRoll (&qR, fYaw, fPitch, fRoll);
// 用四元数来构建旋转矩阵
D3DXMatrixRotationQuaternion (&matR, &qR);
// 应用旋转矩阵
D3DXMatrixMultiply (&matView, &matR, &matView);
// 平移矩阵
D3DXMatrixTranslation (&matTemp, vPos.x, vPos.y, vPos.z);
// 应用旋转矩阵
D3DXMatrixMultiply (&matView, &matTemp, &matView);
// 为了绕任意点所做的旋转为线性的。
D3DXMatrixInverse (&matTemp, NULL, &matView);
m_pd3dDevice->SetTransform(D3DTS_VIEW, &matTemp );
一个窗口应用程序中视口的大小被定义为该窗口客户区的大小,而一个全屏应用程序中视口的大小则定义为屏幕的分辨率。
视口用法: 通过GetViewPort可获取视口数据,以视口的大小和提供给深度缓冲器的MinX,MinY来填充一个视口结构。应在DrawPrimitive*命令之前用SetViewPort来设置视口。在完成绘制后,应恢复原来的视口,以便在一次渲染中清理整个渲染目标,以及通过Direct3D框架提供的字体类来绘制文字。
渲染场景最有效的方法是仅渲染那些可以被观察者看到的像素。如果渲染了那些看不到像素,那么这种多余的操作称为覆绘。
深度缓冲器储存着显示器中每个像素的深度信息,在显示虚拟世界之前,应当清除深度缓冲器中的每个像素,将它们设置为最远可能的深度值。在光栅化时,深度缓冲算法会获取当前多边形所涉及的每个像素的深度。如果一个像素比先前存储在深度缓冲器中的像素更接近于照相机,则较近的像素被显示出来,并且这个新的深度值也将覆盖深度缓冲器中原先的内容,每次绘制多边形的像素时都执行一遍这个过程。
颜色缓冲器存储了稍后将要绘制到屏幕上的内容。深度缓冲器的每个像素通常都是16位或24位。深度精度取决于深度缓冲器的位数。
W缓冲器:减少了Z缓冲器在处理远距离物体时遇到的问题。可以通过这些获得相关支持:
m_pd3dDevice->SetRenderState(D3DRS_ZENABLE,D3DZB_USEW).
以及
if (d3dCaps.RasterCaps & D3DPRASTERPS_WBUFFER)来判断是否支持W buffer.
如何使用四元数来旋转照相机?
通过偏航,俯仰,以及横滚来构建一个四元数,然后把它转换成一个矩阵,最后求该矩阵的逆矩阵
只有正方形的矩阵(方阵)才能求逆,因此当我们说矩阵求逆,那么它就是方矩阵
并不是每个方阵都有逆矩阵。
平面其实可以用法向量n和常数d来表示。判断点和平面的关系:
假如n·p + d = 0,那么点p与平面共面。
假如n·p + d >0,那么点p在平面的前面且在平面的正半空间里。
假如n·p + d <0,那么点p在平面的背面且在平面的负半空间里。
创建平面的方法:
1)通过点和法线来创建相关的平面,D3DXPlaneFromPointNormal。
2)通过平面上面的三点,p0,p1,p2来表示,D3DXPlaneFromPoints。
http://www.cppblog.com/shadow/articles/2807.html
http://www.cppblog.com/lovedday/archive/2008/04/04/46264.html