索引緩沖器:制作索引次序,并且根據(jù)這個索引次序?qū)⑺欣L制的圖行進(jìn)行編碼,這樣有兩個好處:
1)按照索引次序可以減少渲染頂點數(shù)目,這樣可以提高性能效率。
2)索引緩沖器中的索引可以提供cache的功能,可以cache住最近用于變換和光照的頂點數(shù)據(jù),下次使用的時候,就不用再處理了。并且在GPU里面是不知道abc, bcd里面的bc是一致的,這樣除非憑借索引。一般處理的方式是盡量減少數(shù)據(jù)量,可以通過改變繪制圖元的方式和頂點結(jié)構(gòu)的組織格式(SetFVF,SetVertexDeclaration)。
關(guān)于繪制圖元的方式(兩個三角形):
1)如果是triangle list表示就是:
abcbcd
2)如果是triangle strip,就是
abcd
3)如果是index buffer + triangle list就是
abcd
012,123
4)如果是 index buffer + triangle strip就是
abcd
0123
頂點結(jié)構(gòu)和索引值結(jié)構(gòu)是根據(jù)繪制圖元的方式來決定的,比如選擇triangle strip的頂點設(shè)置跟triangle list的頂點設(shè)置就有不同.并且索引緩沖的設(shè)置是按照順時針(DX)的形式進(jìn)行編號的.
在使用圖形渲染頂點的時候,如果對模型的頂點布局和頂點渲染方式有不清楚的,這樣可以通過美工來獲得這種信息,之前在想一架飛機(jī)的時候,都沒有將模型構(gòu)建起來,但是花了不少的精力在那上面,后面才想到,其實沒必要將心思全部花在那里的,而可以將心思放在具體的模型導(dǎo)入上面,在美術(shù)那邊就可以獲得頂點的詳細(xì)信息,這樣有助于解決問題的關(guān)鍵,頂點布局在美術(shù)那邊會得到一個比較完整的體現(xiàn),而程序這邊只需要知道頂點的結(jié)構(gòu)就好了,比如詳細(xì)的頂點結(jié)構(gòu),頂點在導(dǎo)入模型里面的布局等等,諸如此類的。另外還有一個點的是:其實研究頂點的話,可以將之放到模型里面去分析,這樣的話,可以減少單獨設(shè)計頂點帶來的困擾。
攝像坐標(biāo)系就是定義在攝像機(jī)的屏幕可視區(qū)域,在攝像機(jī)的坐標(biāo)系中,x軸向右,z軸向前(朝向屏幕內(nèi),或者攝像機(jī)方向),y軸向上(不是世界的上方,而是攝像機(jī)的上方),
為了簡化世界坐標(biāo)系到物體坐標(biāo)系的轉(zhuǎn)換,人們引入了一種新的坐標(biāo)系,稱為慣性坐標(biāo)系,意思是世界坐標(biāo)系到物體坐標(biāo)系的半途,慣性坐標(biāo)系的原點跟物體坐標(biāo)系的原點重合,但是慣性坐標(biāo)系的軸平行于物體坐標(biāo)系的軸。可以用慣性坐標(biāo)系來做為物體坐標(biāo)系與世界坐標(biāo)系的中介:用旋轉(zhuǎn)能將物體坐標(biāo)系轉(zhuǎn)換到慣性坐標(biāo)系,用平移可以將慣性坐標(biāo)系轉(zhuǎn)換到物體坐標(biāo)系。
物體坐標(biāo)系轉(zhuǎn)換成世界坐標(biāo)系要經(jīng)歷的步驟:
1)將物體坐標(biāo)順時針45度,轉(zhuǎn)換到慣性坐標(biāo)系。
2)將慣性坐標(biāo)系向下向右旋轉(zhuǎn)到世界坐標(biāo)系。
3)這樣物體坐標(biāo)軸順時針45度,向下向下向右旋轉(zhuǎn)到世界坐標(biāo)系。
嵌套坐標(biāo)系:定義了一種層次的,或者樹狀的坐標(biāo)系.世界坐標(biāo)系就是這個樹的根。
對于許多向量,我們只關(guān)心它的方向而不關(guān)心她的大小,在這個情況下使用單位向量非常重要。(D3DXVec3Normalize)
一般來說,點乘描述兩個向量的相似程度。點乘等于向量大小以及向量的cos值的積。
幾何意義在于:a的長度與b在a上的投影長度的乘積,或者是b的長度與a在b上投影長的乘積,它是一個標(biāo)量,而且可正可負(fù),相互垂直的向量內(nèi)積為0。
叉積描述的是一個向量垂直于所在的平面的兩個向量(D3DXVec3Cross)。
叉積最重要的應(yīng)用在于創(chuàng)建垂直于平面,三角形,以及多邊形的向量。
p,q,r定義為x,y,z軸上面的單位向量。那么任意一個向量都可以表示為v = xp + yq + zr; 并且將,p,q,r這些稱為基向量,這里基向量就是卡笛爾坐標(biāo)。
一個坐標(biāo)系可以用任意三個基向量表示,當(dāng)然這三個基向量要線形無關(guān)。
矩陣的每一行都能解釋為轉(zhuǎn)換后的基向量。
可以通過想象變換后的坐標(biāo)系的基向量來想象矩陣。這些基向量在2d中構(gòu)成“L”形狀,在3d中構(gòu)架成三角架形狀。
// 重新產(chǎn)生基向量
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
// 用歸一化后的向量和一個標(biāo)量(角度)旋轉(zhuǎn)后獲得一個旋轉(zhuǎn)矩陣。
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] ,并且之后求得出來的結(jié)果向量是pOut'去掉z軸(w)得到pOut = [pOut'.x/w pOut'y/w pOut'z/w].
另外D3DXVec3TransformNormal的做法是差不多的,只是其中一項w被設(shè)置為0.
// 設(shè)置照相機(jī)矩陣,位置和方向。
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: 定義了物體的右側(cè)指向
UP:僅在物體會繞著LOOK向量旋轉(zhuǎn)時才是必需的,表示哪個方向?qū)τ谖矬w來說是"上"或"下"。
pitch - RIGHT
roll - LOOK
yaw - UP
LOOK移動- 改變POSITION.
m_pd3dDevice->SetTransform(D3DTS_WORLD, &m_pObjects[0].matLocal );
設(shè)置渲染紋理內(nèi)容。
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.
// 設(shè)置頂點格式
m_pd3dDevice->SetFVF(FVF );
// 將頂點緩沖器綁定到設(shè)備數(shù)據(jù)流。
m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(VERTEX) );
// 設(shè)置索引數(shù)據(jù)
m_pd3dDevice->SetIndices( m_pIB );
// 繪制
m_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,
0,
0,
16, // number of vertices
0,
10); // number of primitives
在旋轉(zhuǎn)向量之前,必須重新歸一化,因為要使向量相互垂直。
D3DXQuaternionRotationYawPitchRoll: 用給定的yaw, pitch, roll來構(gòu)建四元數(shù)。
D3DXMatrixRotationQuaternion: 用四元數(shù)來構(gòu)建旋轉(zhuǎn)。
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對于構(gòu)建一個跟隨式照相機(jī)是很有幫助的。
可以使用四元數(shù)的方式執(zhí)行旋轉(zhuǎn)向量:
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來構(gòu)建四元數(shù)。
D3DXQuaternionRotationYawPitchRoll (&qR, fYaw, fPitch, fRoll);
// 用四元數(shù)來構(gòu)建旋轉(zhuǎn)矩陣
D3DXMatrixRotationQuaternion (&matR, &qR);
// 應(yīng)用旋轉(zhuǎn)矩陣
D3DXMatrixMultiply (&matView, &matR, &matView);
// 平移矩陣
D3DXMatrixTranslation (&matTemp, vPos.x, vPos.y, vPos.z);
// 應(yīng)用旋轉(zhuǎn)矩陣
D3DXMatrixMultiply (&matView, &matTemp, &matView);
// 為了繞任意點所做的旋轉(zhuǎn)為線性的。
D3DXMatrixInverse (&matTemp, NULL, &matView);
m_pd3dDevice->SetTransform(D3DTS_VIEW, &matTemp );
一個窗口應(yīng)用程序中視口的大小被定義為該窗口客戶區(qū)的大小,而一個全屏應(yīng)用程序中視口的大小則定義為屏幕的分辨率。
視口用法: 通過GetViewPort可獲取視口數(shù)據(jù),以視口的大小和提供給深度緩沖器的MinX,MinY來填充一個視口結(jié)構(gòu)。應(yīng)在DrawPrimitive*命令之前用SetViewPort來設(shè)置視口。在完成繪制后,應(yīng)恢復(fù)原來的視口,以便在一次渲染中清理整個渲染目標(biāo),以及通過Direct3D框架提供的字體類來繪制文字。
渲染場景最有效的方法是僅渲染那些可以被觀察者看到的像素。如果渲染了那些看不到像素,那么這種多余的操作稱為覆繪。
深度緩沖器儲存著顯示器中每個像素的深度信息,在顯示虛擬世界之前,應(yīng)當(dāng)清除深度緩沖器中的每個像素,將它們設(shè)置為最遠(yuǎn)可能的深度值。在光柵化時,深度緩沖算法會獲取當(dāng)前多邊形所涉及的每個像素的深度。如果一個像素比先前存儲在深度緩沖器中的像素更接近于照相機(jī),則較近的像素被顯示出來,并且這個新的深度值也將覆蓋深度緩沖器中原先的內(nèi)容,每次繪制多邊形的像素時都執(zhí)行一遍這個過程。
顏色緩沖器存儲了稍后將要繪制到屏幕上的內(nèi)容。深度緩沖器的每個像素通常都是16位或24位。深度精度取決于深度緩沖器的位數(shù)。
W緩沖器:減少了Z緩沖器在處理遠(yuǎn)距離物體時遇到的問題??梢酝ㄟ^這些獲得相關(guān)支持:
m_pd3dDevice->SetRenderState(D3DRS_ZENABLE,D3DZB_USEW).
以及
if (d3dCaps.RasterCaps & D3DPRASTERPS_WBUFFER)來判斷是否支持W buffer.
如何使用四元數(shù)來旋轉(zhuǎn)照相機(jī)?
通過偏航,俯仰,以及橫滾來構(gòu)建一個四元數(shù),然后把它轉(zhuǎn)換成一個矩陣,最后求該矩陣的逆矩陣
只有正方形的矩陣(方陣)才能求逆,因此當(dāng)我們說矩陣求逆,那么它就是方矩陣
并不是每個方陣都有逆矩陣。
平面其實可以用法向量n和常數(shù)d來表示。判斷點和平面的關(guān)系:
假如n·p + d = 0,那么點p與平面共面。
假如n·p + d >0,那么點p在平面的前面且在平面的正半空間里。
假如n·p + d <0,那么點p在平面的背面且在平面的負(fù)半空間里。
創(chuàng)建平面的方法:
1)通過點和法線來創(chuàng)建相關(guān)的平面,D3DXPlaneFromPointNormal。
2)通過平面上面的三點,p0,p1,p2來表示,D3DXPlaneFromPoints。
http://www.shnenglu.com/shadow/articles/2807.html
http://www.shnenglu.com/lovedday/archive/2008/04/04/46264.html