青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆 - 132  文章 - 51  trackbacks - 0
<2010年6月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

常用鏈接

留言簿(7)

隨筆分類

隨筆檔案

文章分類

文章檔案

cocos2d-x

OGRE

OPenGL

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

原文:http://ziouchen.blog.163.com/blog/static/179759234201117101223852/
 

空間中的物體需要使用三維坐標來描述,而顯示器是一個二維的表面,所以在屏幕上渲染一個三維場景時,首先需要將描述空間物體的三維坐標變換為二維坐標(世界坐標到屏幕坐標),這在Direct3D中稱為頂點坐標變換。頂點坐標變換通常通過矩陣來完成。可以把頂點坐標變換想象成攝像過程,三維世界的景物通過攝像機的拍攝顯示在二維的相片上,所不同的是把相片換成了屏幕。

 

頂點坐標變換和光照流水線概述

Direct3D中渲染三維對象的過程可分為兩個階段。第一階段稱為坐標變換和光照(Transforming and Lighting T&L)階段。在這個階段,每個對象的頂點被從一個抽象的、浮點坐標空間轉換到基于像素的屏幕空間(坐標變換不僅包含物體頂點位置的坐標變換,它還可能包含頂點法線、紋理坐標等的坐標變換),并根據場景中光源和物體表面的材質對物體頂點應用不同類型的光照效果。還有其他一些比較重要的任務,如裁剪和視口縮放也在第一階段進行。第二階段稱為光柵化處理階段,Direct3D將經過T&L處理的頂點組織以點、線、面為基礎的圖元,應用紋理貼圖和物體頂點的顏色屬性,根據相應渲染狀態設置(如著色模式),決定每個像素的最終顏色值,并在屏幕上顯示出來。

有時根據特殊的需要,可以跳過其中的某些步驟。如果愿意,也可以提供自己的坐標變換和光照過程,并將處理后的頂點直接傳給Direct3D光柵化處理程序,而繞過Direct3D的T&L階段。

T&L的過程在Direct3D中通常稱為頂點變換流水線,在這個過程中,未經過變換和光照的頂點從一端進入,在內部這些頂點將完成幾個連續操作,然后經過轉換和光照的頂點從另一端出來。應用程序通過指定幾個矩陣、視口以及所使用的光線來建立T&L流水線,然后應用程序將頂點送入流水線,對這些頂點進行變換、照明和裁剪,將其投影到屏幕空間,并根據視口的規定對其進行縮放。我們認為經過流水線的頂點是已經經過處理的,并且已經準備好傳送給光柵化處理程序。

下面首先介紹T&L流水線涉及到的一些基本概念:

(1)世界變換和世界坐標系:物體在三維空間的運動和變形過程稱為世界變換,如平移、旋轉、縮放等。物體在其中運動的三維空間稱為世界空間,它的三維坐標系表示稱為世界坐標系,物體頂點在世界坐標系里的坐標變換稱為世界變換。

(2)取景變換和觀察坐標系:把圖形顯示想象成攝像過程,取景變換就像攝像機中攝像機的擺放一樣,在三維圖形顯示中,需要設置一個虛擬攝像機,屏幕顯示的圖形就是虛擬攝像機拍攝在膠片上的景物。以攝像機位置為參考原點,攝像機觀察的方向為坐標軸,建立的坐標系稱為觀察坐標系,物體在觀察坐標系中的相對坐標稱為觀察坐標,頂點從世界坐標到觀察坐標的轉換稱為取景變換。

(3)投影坐標和投影坐標系:物體從世界坐標描述轉換到觀察坐標后,可將三維物體投影到二維表面上,即投影到虛擬攝像機的膠片上,這個過程就是投影變換。以膠片中心為參考原點的空間坐標系稱為投影坐標系,物體在投影坐標系中的坐標稱為投影坐標。

(4)視區變換和屏幕坐標系:物體在投影坐標系中的表示為浮點坐標,通過定義屏幕顯示區域(一般為顯示窗口大小),將浮點坐標轉化為像素坐標的過程稱為視區變換,該像素坐標值稱為屏幕坐標。例如,如果定義視區大小為寬640像素、高480像素,那么投影坐標(1.0f, 0.5f)經過視區變換后的屏幕坐標為(640, 240),如果定義視區大小為寬1024像素、高800像素,經過視區變換后的屏幕坐標為(1204, 400)。

世界空間的三維物體頂點坐標經過世界變換、取景變換、投影變換和視區變換,轉化為以像素為單位的屏幕坐標,就可以進行光柵化顯示了。在Direct3D程序中,只要定義并設置好相應的變換矩陣和視區信息,即構建好T&L流水線,剩余的各種頂點變換操作由Direct3D自動完成。

 IDirect3DDevice9::SetTransform()函數用來設置頂點變換矩陣,該函數的聲明如下:

Sets a single device transformation-related state.

HRESULT SetTransform(
D3DTRANSFORMSTATETYPE State,
CONST D3DMATRIX * pMatrix
);

Parameters

State
[in] Device-state variable that is being modified. This parameter can be any member of the D3DTRANSFORMSTATETYPE enumerated type, or the D3DTS_WORLDMATRIX macro.
pMatrix
[in] Pointer to a D3DMATRIX structure that modifies the current transformation.

Return Values

If the method succeeds, the return value is D3D_OK. D3DERR_INVALIDCALL is returned if one of the arguments is invalid.

D3DTRANSFORMSTATETYPE

Defines constants that describe transformation state values.

typedef enum D3DTRANSFORMSTATETYPE
{
D3DTS_VIEW = 2,
D3DTS_PROJECTION = 3,
D3DTS_TEXTURE0 = 16,
D3DTS_TEXTURE1 = 17,
D3DTS_TEXTURE2 = 18,
D3DTS_TEXTURE3 = 19,
D3DTS_TEXTURE4 = 20,
D3DTS_TEXTURE5 = 21,
D3DTS_TEXTURE6 = 22,
D3DTS_TEXTURE7 = 23,
D3DTS_FORCE_DWORD = 0x7fffffff,
} D3DTRANSFORMSTATETYPE, *LPD3DTRANSFORMSTATETYPE;

Constants

D3DTS_VIEW
Identifies the transformation matrix being set as the view transformation matrix. The default value is NULL (the identity matrix).
D3DTS_PROJECTION
Identifies the transformation matrix being set as the projection transformation matrix. The default value is NULL (the identity matrix).
D3DTS_TEXTURE0
Identifies the transformation matrix being set for the specified texture stage.
D3DTS_TEXTURE1
Identifies the transformation matrix being set for the specified texture stage.
D3DTS_TEXTURE2
Identifies the transformation matrix being set for the specified texture stage.
D3DTS_TEXTURE3
Identifies the transformation matrix being set for the specified texture stage.
D3DTS_TEXTURE4
Identifies the transformation matrix being set for the specified texture stage.
D3DTS_TEXTURE5
Identifies the transformation matrix being set for the specified texture stage.
D3DTS_TEXTURE6
Identifies the transformation matrix being set for the specified texture stage.
D3DTS_TEXTURE7
Identifies the transformation matrix being set for the specified texture stage.
D3DTS_FORCE_DWORD
Forces this enumeration to compile to 32 bits in size. Without this value, some compilers would allow this enumeration to compile to a size other than 32 bits. This value is not used.

Remarks

The transform states in the range 256 through 511 are reserved to store up to 256 world matrices that can be indexed using the D3DTS_WORLDMATRIX and D3DTS_WORLD macros.

Macros  
D3DTS_WORLD Equivalent to D3DTS_WORLDMATRIX(0).
D3DTS_WORLDMATRIX (index) Identifies the transform matrix to set for the world matrix at index. Multiple world matrices are used only for vertex blending. Otherwise only D3DTS_WORLD is used.


IDirect3DDevice9::SetViewport()函數用來設置視區信息,該函數聲明如下:

Sets the viewport parameters for the device.

HRESULT SetViewport(
CONST D3DVIEWPORT9 * pViewport
);

Parameters

pViewport
[in] Pointer to a D3DVIEWPORT9 structure, specifying the viewport parameters to set.

Return Values

If the method succeeds, the return value is D3D_OK. If the method fails, it will return D3DERR_INVALIDCALL. This will happen if pViewport is invalid, or if pViewport describes a region that cannot exist within the render target surface.

Remarks

Direct3D sets the following default values for the viewport.

D3DVIEWPORT9 vp;
vp.X = 0;
vp.Y = 0;
vp.Width = RenderTarget.Width;
vp.Height = RenderTarget.Height;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;

IDirect3DDevice9::SetViewport can be used to draw on part of the screen. Make sure to call it before any geometry is drawn so the viewport settings will take effect.

To draw multiple views within a scene, repeat the IDirect3DDevice9::SetViewport and draw geometry sequence for each view.

矩陣類型及其操作

在Direct3D中,頂點坐標變換通常是借助于矩陣實現的,因此下面首先介紹在Direct3D中提供的各種矩陣類型和相關的矩陣運算函數。

 

1、D3DMATRIX矩陣類型

D3DMATRIX是Direct3D中最簡單的矩陣類型,其定義如下:

typedef struct _D3DMATRIX {
union {
struct {
float _11, _12, _13, _14;
float _21, _22, _23, _24;
float _31, _32, _33, _34;
float _41, _42, _43, _44;
        };
float m[4][4];
};
} D3DMATRIX;

顯然,D3DMATIX中存放的是一個4x4的二維浮點數組,可以通過_ij的格式訪問該數組中的每個元素,i表示該元素的行數,j表示該元素的列數。例如,_34表示第三行、第四列的元素。

 

2、D3DXMATRIX矩陣類型

該類型矩陣定義如下:

#ifdef __cplusplus
typedef struct D3DXMATRIX : public D3DMATRIX
{
public:
D3DXMATRIX() {};
D3DXMATRIX( CONST FLOAT * );
D3DXMATRIX( CONST D3DMATRIX& );
D3DXMATRIX( CONST D3DXFLOAT16 * );
D3DXMATRIX( FLOAT _11, FLOAT _12, FLOAT _13, FLOAT _14,
FLOAT _21, FLOAT _22, FLOAT _23, FLOAT _24,
FLOAT _31, FLOAT _32, FLOAT _33, FLOAT _34,
FLOAT _41, FLOAT _42, FLOAT _43, FLOAT _44 );
    // access grants
FLOAT& operator () ( UINT Row, UINT Col );
FLOAT operator () ( UINT Row, UINT Col ) const;
    // casting operators
operator FLOAT* ();
operator CONST FLOAT* () const;
    // assignment operators
D3DXMATRIX& operator *= ( CONST D3DXMATRIX& );
D3DXMATRIX& operator += ( CONST D3DXMATRIX& );
D3DXMATRIX& operator -= ( CONST D3DXMATRIX& );
D3DXMATRIX& operator *= ( FLOAT );
D3DXMATRIX& operator /= ( FLOAT );
    // unary operators
D3DXMATRIX operator + () const;
D3DXMATRIX operator - () const;
    // binary operators
D3DXMATRIX operator * ( CONST D3DXMATRIX& ) const;
D3DXMATRIX operator + ( CONST D3DXMATRIX& ) const;
D3DXMATRIX operator - ( CONST D3DXMATRIX& ) const;
D3DXMATRIX operator * ( FLOAT ) const;
D3DXMATRIX operator / ( FLOAT ) const;
    friend D3DXMATRIX operator * ( FLOAT, CONST D3DXMATRIX& );
    BOOL operator == ( CONST D3DXMATRIX& ) const;
BOOL operator != ( CONST D3DXMATRIX& ) const;
} D3DXMATRIX, *LPD3DXMATRIX;
#else //!__cplusplus
typedef struct _D3DMATRIX D3DXMATRIX, *LPD3DXMATRIX;
#endif //!__cplusplus

 

3、D3DXMATRIXA16矩陣類型

D3DXMATRIXA16稱為16字節對齊矩陣(16-byte aligned matrix),它是從矩陣D3DXMATRIX中繼承而來的,其定義如下:

typedef D3DX_ALIGN16 _D3DXMATRIXA16 D3DXMATRIXA16, *LPD3DXMATRIXA16;

//---------------------------------------------------------------------------
// Aligned Matrices
//
// This class helps keep matrices 16-byte aligned as preferred by P4 cpus.
// It aligns matrices on the stack and on the heap or in global scope.
// It does this using __declspec(align(16)) which works on VC7 and on VC 6
// with the processor pack. Unfortunately there is no way to detect the
// latter so this is turned on only on VC7. On other compilers this is the
// the same as D3DXMATRIX.
//
// Using this class on a compiler that does not actually do the alignment
// can be dangerous since it will not expose bugs that ignore alignment.
// E.g if an object of this class in inside a struct or class, and some code
// memcopys data in it assuming tight packing. This could break on a compiler
// that eventually start aligning the matrix.
//---------------------------------------------------------------------------
#ifdef __cplusplus
typedef struct _D3DXMATRIXA16 : public D3DXMATRIX
{
_D3DXMATRIXA16() {}
_D3DXMATRIXA16( CONST FLOAT * );
_D3DXMATRIXA16( CONST D3DMATRIX& );
_D3DXMATRIXA16( CONST D3DXFLOAT16 * );
_D3DXMATRIXA16( FLOAT _11, FLOAT _12, FLOAT _13, FLOAT _14,
FLOAT _21, FLOAT _22, FLOAT _23, FLOAT _24,
FLOAT _31, FLOAT _32, FLOAT _33, FLOAT _34,
FLOAT _41, FLOAT _42, FLOAT _43, FLOAT _44 );
    // new operators
void* operator new ( size_t );
void* operator new[] ( size_t );
    // delete operators
void operator delete ( void* ); // These are NOT virtual; Do not
void operator delete[] ( void* ); // cast to D3DXMATRIX and delete.
    // assignment operators
_D3DXMATRIXA16& operator = ( CONST D3DXMATRIX& );
} _D3DXMATRIXA16;
#else //!__cplusplus
typedef D3DXMATRIX _D3DXMATRIXA16;
#endif //!__cplusplus

當使用了Intel Pentium 4運行一個D3DX數學函數時,16字節對齊矩陣D3DXMATRIXA16為完成相應操作進行了優化。當使用VC++.net或使用安裝了processor pack的VC6++時,將開啟字節對齊功能。但不幸的是,編譯器無法探測到是否安裝了processor pack,所以字節對齊僅僅只對VC++.net默認開啟。對于其他編譯器,16字節對齊矩陣D3DXMATRIXA16將被當作D3DXMATRIX進行操作。

經過擴展后的結構體D3DXMATRIX和D3DXMATRIXA16對許多運算符進行了重載,所以可以直接進行轉換運算、賦值運算以及多種一元、二元運算,大大方便了矩陣類型變量的運算。

 

4、常見的矩陣運算函數

因為矩陣的運算相對比較復雜,所以Direct3D提供了一組矩陣運算函數,例如,通過函數D3DXMatrixTranslation()構造一個平移矩陣;通過函數D3DXMatrixRotationX()、D3DXMatrixRotationY()和D3DXMatrixRotationZ()構造繞x、y和z軸轉動一定角度的矩陣;通過函數D3DXMatrixScaling()構造一個縮放矩陣;通過函數D3DXMatrxiIdentity()將一個矩陣單位化;通過函數D3DXMatrixMultiply()計算兩個矩陣的積;通過函數D3DXMatrixInverse()求原矩陣的逆矩陣;通過函數D3DXMatrixTranspose()計算原矩陣的轉置矩陣。

世界變換

世界變換就是將物體頂點坐標從模型空間轉換到世界空間。在模型空間里,頂點位置坐標依據模型的本地坐標系的原點而定,在世界空間里,所有模型的頂點共用一個原點,即世界坐標系原點。事實上,世界變換就是將一個模型從本地空間重新定位到世界空間內。從模型空間到世界空間的轉換實際上就是對模型進行平移、旋轉、縮放以及它們的任意組合變換。

使用三維模型制作軟件,例如3dmax,制作三維模型時,首先需要為模型設定一個坐標系,模型上的頂點坐標就是設定的模型自身坐標系下的坐標,這個坐標系也就是上面提到的本地坐標系或模型空間。

 

1、世界變換矩陣

在處理三維圖像的應用程序中,可使用世界變換完成一個物體(確切的說是一個坐標或一系列坐標)的平移、旋轉和縮放。當然也可以完成這三種變換的任意組合。具體的方法就是通過下式:

3D編程文章(頂點坐標轉換) - ziouchen - Paul Allens Home

將任意一點P(x, y, z)轉換到p'(x', y', z'),上式也可以表示為以下形式:

p'(x', y', z') = P(x, y, z) . Mworld

Mworld就是世界變換矩陣。也就是它實現了物體的平移、旋轉、縮放和它們的復合變換。在定義好世界變換矩陣后,調用函數IDirect3DDevice9::SetTransform()并指定第一個參數為D3DTS_WORLD,第二個參數為相應的世界變換矩陣即可。

 

2、平移

可以通過下式(也就是下面的平移變換矩陣):

3D編程文章(頂點坐標轉換) - ziouchen - Paul Allens Home

將點(x, y, z)沿x、y和z軸分別移動Tx、Ty、Tz,到另一點(x',y',z')。很顯然,只要得到了這個平移矩陣,平移工作就可以完成。

為方便起見,D3DX擴展函數庫d3dx9.lib提供了函數D3DXMatrixTranslation(),用它可以很方便地生成一個平移世界矩陣。該函數的聲明如下:

Builds a matrix using the specified offsets.

D3DXMATRIX * D3DXMatrixTranslation(
D3DXMATRIX * pOut,
FLOAT x,
FLOAT y,
FLOAT z
);


Parameters

pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
x
[in] X-coordinate offset.
y
[in] Y-coordinate offset.
z
[in] Z-coordinate offset.


Return Values

Pointer to a D3DXMATRIX structure that contains a translated transformation matrix.


Remarks

The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMATRIXTranslation can be used as a parameter for another function.

 

3、旋轉

與平移類似,使用下面的四階矩陣可以將點(x, y, z)繞x軸旋轉θ角,到新點(x', y', z'):

3D編程文章(頂點坐標轉換) - ziouchen - Paul Allens Home

繞y軸旋轉θ角時的矩陣為:

3D編程文章(頂點坐標轉換) - ziouchen - Paul Allens Home

繞z軸旋轉θ角時的矩陣為:

3D編程文章(頂點坐標轉換) - ziouchen - Paul Allens Home

θ指旋轉角度,單位是弧度,具體是指沿著旋轉軸的指向(即正方向)向坐標原點看去順指針旋轉過的角度。

同樣可以使用D3DX擴展函數庫d3dx9.lib提供的函數D3DXMatrixRotationX()、D3DXMatrixRotationY()和D3DXMatrixRotationZ()方便地創建旋轉矩陣,這三個函數的聲明如下,因聲明類似,只列出D3DXMatrixRotationX()的使用說明:

Builds a matrix that rotates around the x-axis.

D3DXMATRIX * D3DXMatrixRotationX(
D3DXMATRIX * pOut,
FLOAT Angle
);


Parameters

pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
Angle
[in] Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin.


Return Values

Pointer to a D3DXMATRIX structure rotated around the x-axis.


Remarks

The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixRotationX function can be used as a parameter for another function.

 

4、縮放

使用下面的四階矩陣可以將點(x, y, z)在x、y、z軸上各縮放Sx、Sy、Sz,到另一點(x', y', z')。

3D編程文章(頂點坐標轉換) - ziouchen - Paul Allens Home

同樣,可以使用Direct3D擴展實用庫中的函數D3DXMatrixScaling()來生成縮放矩陣,該函數的聲明如下:

Builds a matrix that scales along the x-axis, the y-axis, and the z-axis.

D3DXMATRIX * D3DXMatrixScaling(
D3DXMATRIX * pOut,
FLOAT sx,
FLOAT sy,
FLOAT sz
);


Parameters

pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
sx
[in] Scaling factor that is applied along the x-axis.
sy
[in] Scaling factor that is applied along the y-axis.
sz
[in] Scaling factor that is applied along the z-axis.


Return Values

Pointer to the scaling transformation D3DXMATRIX.


Remarks

The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixScaling function can be used as a parameter for another function.

 

5、矩陣連接與復合變換

在大多數情況下,Direct3D中的物體需要進行的世界變換不止一個,而往往是多個世界變換的組合,這時可以使用矩陣連接來實現這種復合變換。因為矩陣的一個優點是通過矩陣的相乘,將兩個或更多矩陣的作用合并在一起實現。為了先后實現一個模型的旋轉和移動,不需要使用兩個矩陣,可以將旋轉矩陣和平移矩陣相乘得到一個復合矩陣以實現所有功能。這個過程叫做矩陣連接(matrix concatention),可以用下面的公式表示:

C = M1 * M2 * ... * Mn-1 * Mn

在這個公式里,C是實現復合變換的復合矩陣,從M1到Mn是只能實現某一種世界變換的單獨矩陣(individual matrices)。大多數情況下是兩到三個矩陣連接,但這個數量沒有限制。

使用函數D3DXMatrixMultiply() 可完成矩陣的乘法,該函數的說明如下:

Determines the product of two matrices.

D3DXMATRIX * D3DXMatrixMultiply(
D3DXMATRIX * pOut,
CONST D3DXMATRIX * pM1,
CONST D3DXMATRIX * pM2
);


Parameters

pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
pM1
[in] Pointer to a source D3DXMATRIX structure.
pM2
[in] Pointer to a source D3DXMATRIX structure.


Return Values

Pointer to a D3DXMATRIX structure that is the product of two matrices.


Remarks

The result represents the transformation M1 followed by the transformation M2 (Out = M1 * M2).

The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixMultiply function can be used as a parameter for another function.

矩陣pOut表示最終的復合變換,也就是先進行矩陣pM1表示的變換,然后又進行矩陣pM2表示的變換。

在矩陣的乘法中,順序是很關鍵的。無論要創建什么樣的世界變換矩陣,記住從左到右的原則才能確保實現想要的效果,也就是說,一個復合矩陣的視覺效果是按從左到右的順序各單獨矩陣視覺效果的組合。假設一個物體先繞y軸旋轉,然后把它移動到場景內的另一個位置。為實現這個效果,首先創建一個旋轉矩陣Ry,然后乘以一個平移矩陣Tw:

W = Ry * Tw

在這個公式里,Ry表示繞y軸的旋轉矩陣,Tw實現世界坐標系內的一次平移。矩陣的乘法不滿足交換律。如果將這兩個矩陣以相反的順序相乘,效果是先平移,然后旋轉。

取景變換

取景變換(也稱觀察變換)是在世界空間下架設一個攝像機,把各個頂點坐標從世界空間變換到攝影空間(觀察空間)。在攝影空間里,攝像機或者說觀察點位于原點,向著z軸正方向。因為Direct3D采用左手坐標系,所以z軸正方向指向屏幕里面。設三維頂點在世界坐標系的坐標為Pworld,在攝影空間內的坐標為Pview,則:

Pview = Pworld * Mview

矩陣Mview稱為觀察矩陣。觀察矩陣根據攝像機在世界空間中的位置(即攝影空間的原點在世界坐標系中的相對位置)和攝像機的觀察方向在世界空間中的方向,將世界坐標系下的對象重新定位。在Direct3D中設置觀察矩陣非常簡單,首先調用Direct3D擴展實用庫提供的函數D3DXMatrixLookAtLH(),生成一個基于左手坐標系的觀察矩陣,該函數聲明如下:

Builds a left-handed, look-at matrix.

D3DXMATRIX * D3DXMatrixLookAtLH(
D3DXMATRIX * pOut,
CONST D3DXVECTOR3 * pEye,
CONST D3DXVECTOR3 * pAt,
CONST D3DXVECTOR3 * pUp
);

Parameters

pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
pEye
[in] Pointer to the D3DXVECTOR3 structure that defines the eye point. This value is used in translation.
pAt
[in] Pointer to the D3DXVECTOR3 structure that defines the camera look-at target.
pUp
[in] Pointer to the D3DXVECTOR3 structure that defines the current world's up, usually [0, 1, 0].

Return Values

Pointer to a D3DXMATRIX structure that is a left-handed, look-at matrix.

Remarks

The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixLookAtLH function can be used as a parameter for another function.

This function uses the following formula to compute the returned matrix.

zaxis = normal(At - Eye)
xaxis = normal(cross(Up, zaxis))
yaxis = cross(zaxis, xaxis)

xaxis.x yaxis.x zaxis.x 0
xaxis.y yaxis.y zaxis.y 0
xaxis.z yaxis.z zaxis.z 0
-dot(xaxis, eye) -dot(yaxis, eye) -dot(zaxis, eye) 1

然后調用函數IDirect3DDevice9::SetTransform(D3DTS_VIEW, &mat_view)設置觀察矩陣,其中mat_view為函數D3DXMatrixLookAtLH()生成的觀察矩陣。

當然,也可以使用函數D3DXMatrixLookAtRH()建立一個基于右手坐標系的觀察矩陣,但因為Direct3D采用左手坐標系,所以通常不使用此函數。

創建并設置一個觀察矩陣的方法很容易,但真正理解構造觀察矩陣原理卻不像理解構造世界變換矩陣那么容易。有多種方法可以建立觀察矩陣,但無論對于哪種情況,攝像機都有自己在世界空間下的邏輯位置和方向。觀察矩陣的任務就是完成對象的平移和旋轉,從而把它們定位在攝影空間里,而此時攝像機位于攝影空間的原點。所以,一種創建觀察矩陣的方法是用一個平移矩陣以及各個軸的旋轉矩陣來實現。下面以這種方法為例較簡單介紹構造觀察矩陣的原理。這種方法使用下面的矩陣運算公式:

V = T * Rz * Ry * Rx

在這個公式里,V是將要創建的觀察矩陣,T是世界坐標系下的一個平移矩陣,Rx、Ry和Rz是繞x、y和z軸的旋轉矩陣。這些平移矩陣和旋轉矩陣以世界空間下攝影機的邏輯位置和方向為基礎。所以,如果一個攝影機在世界空間下的邏輯位置是(10, 20, 100),平移矩陣的作用是將對象沿x軸移動10個單位,沿y軸移動20個單位,沿z軸移動100個單位。公式中的旋轉矩陣以攝像機的方向為基礎,表示攝影空間里的坐標軸相對于世界空間坐標軸應該旋轉多少度。例如,如果攝像機的方向垂直向下時,攝影空間的z軸偏離世界空間z軸90度。那么就需要用公式中的旋轉矩陣對場景里的所有對象繞x軸旋轉負90度,也就是說,這時的旋轉是與偏離程度是等大反向的。把前面的平移矩陣和這個旋轉矩陣連接起來,就創建了一個觀察矩陣V。用它來調整場景里對象的位置和方向,使得它們的頂部沖著攝影機的鏡頭,就好像攝像機從對象的頂部向下拍攝一樣。

投影變換

將攝影空間中的三維物體投影到二維膠片上,也就是Direct3D中的屏幕,這種三維到二維的變換過程就是投影變換,即從取景空間到攝影空間的變換。設三維物體在觀察空間中的坐標為Pview,投影矩陣為Mproj,則頂點在投影空間中的坐標為:

Pproj = Pview * Mproj

下面分別介紹兩種基本的投影變換:正交投影和透視投影,以及它們在Direct3D中的實現。

 

1、正交投影

正交投影中,投影向量和觀察平面垂直,物體坐標沿觀察坐標系的z軸平行投影到觀察平面上,觀察點和觀察平面間的距離不會影響物體的投影大小。

工程設計中的頂視圖、前視圖和側視圖就是典型的正交投影。與世界變換、取景變換類似,只需先生成一個投影矩陣mat_proj,然后調用下面的代碼就可以設置投影矩陣:

g_device->SetTransform(D3DTS_PROJECTION, &mat_proj);

下面來看看正交投影矩陣的生成。對于正交投影來說,它的取景范圍是一個長方體,只有在這個長方體中的景物才會被繪制出來。

Direct3D擴展實用庫提供了函數D3DXMatrixOrthoLH(),用于創建一個正交投影矩陣,函數D3DXMatrixOrthoLH()的聲明如下:

Builds a left-handed orthographic projection matrix.

D3DXMATRIX * D3DXMatrixOrthoLH(
D3DXMATRIX * pOut,
FLOAT w,
FLOAT h,
FLOAT zn,
FLOAT zf
);


Parameters

pOut
[in, out] Pointer to the resulting D3DXMATRIX.
w
[in] Width of the view volume.
h
[in] Height of the view volume.
zn
[in] Minimum z-value of the view volume which is referred to as z-near.
zf
[in] Maximum z-value of the view volume which is referred to as z-far.


Return Values

Pointer to the resulting D3DXMATRIX.


Remarks

All the parameters of the D3DXMatrixOrthoLH function are distances in camera space. The parameters describe the dimensions of the view volume.

The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixOrthoLH function can be used as a parameter for another function.

This function uses the following formula to compute the returned matrix.

2/w  0    0           0
0 2/h 0 0
0 0 1/(zf-zn) 0
0 0 -zn/(zf-zn) 1
 

2、透視投影

透視投影實現的是一個縮放、透視的投影。透視投影的特點是,距離攝像機越遠的物體在投影平面上的成像越小,透視投影的取景范圍是一個截頭體(四棱臺)。這個截頭體稱為取景截頭體(viewing frustum),攝像機位于四棱錐的頂點。這個四棱錐被截頭體的遠平面和近平面分割,遠近裁剪面中間的部分就是取景截頭體,只有這個空間里的對象才是可見的。

透視投影矩陣的作用就是將取景截頭體內的景物投影到攝像機的二維膠片上,可以利用Direct3D功能擴展庫提供的D3DXMatrixPerspectiveFovLH(),構建一個透視投影矩陣:

Builds a left-handed perspective projection matrix based on a field of view.

D3DXMATRIX * D3DXMatrixPerspectiveFovLH(
D3DXMATRIX * pOut,
FLOAT fovy,
FLOAT Aspect,
FLOAT zn,
FLOAT zf
);


Parameters

pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
fovy
[in] Field of view in the y direction, in radians.
Aspect
[in] Aspect ratio, defined as view space width divided by height.
zn
[in] Z-value of the near view-plane.
zf
[in] Z-value of the far view-plane.


Return Values

Pointer to a D3DXMATRIX structure that is a left-handed perspective projection matrix.


Remarks

The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixPerspectiveFovLH function can be used as a parameter for another function.

This function computes the returned matrix as shown:

xScale     0          0               0
0 yScale 0 0
0 0 zf/(zf-zn) 1
0 0 -zn*zf/(zf-zn) 0
where:
yScale = cot(fovY/2)
xScale = yScale / aspect ratio

透視投影矩陣的作用是將一個取景截頭體轉換成一個立方體。因為截頭體的近端比遠端小,所以靠近攝像機的對象將被放大,而對象距離攝像機越遠,其成像越小,這就是場景的透視原理。透視變換把一個取景截頭體轉換成一個新的坐標空間,注意,該截頭體變成了一個立方體,同時,原點從場景的右上角移動到了立方體的中心。在透視變換中,x軸和z軸方向的極限都是-1和1,z軸方向對于前平面的極限是0,對后平面的極限是1。

另外,D3DX還提供了下列函數供程序員創建透視投影變換矩陣:


D3DXMatrixPerspectiveLH

Builds a left-handed perspective projection matrix

D3DXMATRIX * D3DXMatrixPerspectiveLH(
D3DXMATRIX * pOut,
FLOAT w,
FLOAT h,
FLOAT zn,
FLOAT zf
);


Parameters

pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
w
[in] Width of the view volume at the near view-plane.
h
[in] Height of the view volume at the near view-plane.
zn
[in] Z-value of the near view-plane.
zf
[in] Z-value of the far view-plane.


Return Values

Pointer to a D3DXMATRIX structure that is a left-handed perspective projection matrix.


Remarks

All the parameters of the D3DXMatrixPerspectiveLH function are distances in camera space. The parameters describe the dimensions of the view volume.

The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixPerspectiveLH function can be used as a parameter for another function.

This function uses the following formula to compute the returned matrix.

2*zn/w  0       0              0
0 2*zn/h 0 0
0 0 zf/(zf-zn) 1
0 0 zn*zf/(zn-zf) 0
 


D3DXMatrixPerspectiveRH

Builds a right-handed perspective projection matrix.

D3DXMATRIX * D3DXMatrixPerspectiveRH(
D3DXMATRIX * pOut,
FLOAT w,
FLOAT h,
FLOAT zn,
FLOAT zf
);


Parameters

pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
w
[in] Width of the view volume at the near view-plane.
h
[in] Height of the view volume at the near view-plane.
zn
[in] Z-value of the near view-plane.
zf
[in] Z-value of the far view-plane.


Return Values

Pointer to a D3DXMATRIX structure that is a right-handed perspective projection matrix.


Remarks

All the parameters of the D3DXMatrixPerspectiveRH function are distances in camera space. The parameters describe the dimensions of the view volume.

The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixPerspectiveRH function can be used as a parameter for another function.

This function uses the following formula to compute the returned matrix.

2*zn/w  0       0              0
0 2*zn/h 0 0
0 0 zf/(zn-zf) -1
0 0 zn*zf/(zn-zf) 0

 


D3DXMatrixPerspectiveFovRH

Builds a right-handed perspective projection matrix based on a field of view.

D3DXMATRIX * D3DXMatrixPerspectiveFovRH(
D3DXMATRIX * pOut,
FLOAT fovy,
FLOAT Aspect,
FLOAT zn,
FLOAT zf
);


Parameters

pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
fovy
[in] Field of view in the y direction, in radians.
Aspect
[in] Aspect ratio, defined as view space width divided by height.
zn
[in] Z-value of the near view-plane.
zf
[in] Z-value of the far view-plane.


Return Values

Pointer to a D3DXMATRIX structure that is a right-handed perspective projection matrix.


Remarks

The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixPerspectiveFovRH function can be used as a parameter for another function.

This function computes the returned matrix as shown.

xScale     0          0              0
0 yScale 0 0
0 0 zf/(zn-zf) -1
0 0 zn*zf/(zn-zf) 0
where:
yScale = cot(fovY/2)
xScale = yScale / aspect ratio

 


D3DXMatrixPerspectiveOffCenterLH

Builds a customized, left-handed perspective projection matrix.

D3DXMATRIX * D3DXMatrixPerspectiveOffCenterLH(
D3DXMATRIX * pOut,
FLOAT l,
FLOAT r,
FLOAT b,
FLOAT t,
FLOAT zn,
FLOAT zf
);


Parameters

pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
l
[in] Minimum x-value of the view volume.
r
[in] Maximum x-value of the view volume.
b
[in] Minimum y-value of the view volume.
t
[in] Maximum y-value of the view volume.
zn
[in] Minimum z-value of the view volume.
zf
[in] Maximum z-value of the view volume.


Return Values

Pointer to a D3DXMATRIX structure that is a customized, left-handed perspective projection matrix.


Remarks

All the parameters of the D3DXMatrixPerspectiveOffCenterLH function are distances in camera space. The parameters describe the dimensions of the view volume.

The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixPerspectiveOffCenterLH function can be used as a parameter for another function.

This function uses the following formula to compute the returned matrix.

2*zn/(r-l)   0            0              0
0 2*zn/(t-b) 0 0
(l+r)/(l-r) (t+b)/(b-t) zf/(zf-zn) 1
0 0 zn*zf/(zn-zf) 0


D3DXMatrixPerspectiveOffCenterRH

Builds a customized, right-handed perspective projection matrix.

D3DXMATRIX * D3DXMatrixPerspectiveOffCenterRH(
D3DXMATRIX * pOut,
FLOAT l,
FLOAT r,
FLOAT b,
FLOAT t,
FLOAT zn,
FLOAT zf
);


Parameters

pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
l
[in] Minimum x-value of the view volume.
r
[in] Maximum x-value of the view volume.
b
[in] Minimum y-value of the view volume.
t
[in] Maximum y-value of the view volume.
zn
[in] Minimum z-value of the view volume.
zf
[in] Maximum z-value of the view volume.


Return Values

Pointer to a D3DXMATRIX structure that is a customized, right-handed perspective projection matrix.


Remarks

All the parameters of the D3DXMatrixPerspectiveOffCenterRH function are distances in camera space. The parameters describe the dimensions of the view volume.

The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixPerspectiveOffCenterRH function can be used as a parameter for another function.

This function uses the following formula to compute the returned matrix.

2*zn/(r-l)   0            0                0
0 2*zn/(t-b) 0 0
(l+r)/(r-l) (t+b)/(t-b) zf/(zn-zf) -1
0 0 zn*zf/(zn-zf) 0

3、w友好投影矩陣

經過頂點坐標變換后,每個頂點坐標將具有4個元素(x, y, z, w)。Direct3D使用這個w坐標在深度緩沖區和霧化效果中執行一些深度相關的運算。為了能夠使用這個w坐標進行深度相關運算,要求投影矩陣必須是w友好投影矩陣(w-friendly projection matrix,也稱作兼容矩陣),即投影矩陣第三行第四列的元素必須是1,以使w坐標與世界空間中頂點的z坐標相當。如果投影變換矩陣第三行第四列的元素不是1,必須將所有的矩陣元素除以投影矩陣第三行第四列元素的值,將投影矩陣變換為w友好投影矩陣。如果沒有提供一個w友好投影矩陣,基于深度的霧化效果和深度緩沖就不能正確實現。

下面給出的就是從一個非w友好投影矩陣到w友好投影矩陣的轉換。

3D編程文章(頂點坐標轉換) - ziouchen - Paul Allens Home

Direct3D在進行以w為基礎的深度計算中,需要使用w友好投影矩陣,因此即使應用程序不需要進行頂點坐標變換,也需要設置一個w友好投影矩陣。通過實用庫函數D3DXMatrixPerspectiveFovLH()得到的投影矩陣通常都是w友好投影矩陣,所以通常不需要關心這個問題。

視區變換

視區(視口)變換是Direct3D頂點變換流水線的最后一步,它通過定義視區信息(屏幕顯示區域的實際寬和高等參數),完成頂點裁剪以及將頂點坐標從投影坐標變換為最終顯示的以像素為單位的屏幕坐標等操作。裁剪過程保證不渲染完全在觀察平截面以外的對象,還確保對于與觀察平截面相交的對象,可以如下方式進行渲染:即在視口指定范圍以外的部分不繪制像素。

 從概念上講,視區是一個二維矩形,三維場景被投影到這個矩形中。在Microsoft® Direct3D®中,這個矩形以Direct3D表面內的坐標的形式存在,該表面被系統用作渲染目標。投影變換把頂點轉換到視區所使用的坐標系統



1、定義視區

視區結構D3DVIEWPORT9定義了Direct3D用以進行視區變換的各項參數:

Defines the window dimensions of a render-target surface onto which a 3D volume projects.

typedef struct D3DVIEWPORT9 {
DWORD X;
DWORD Y;
DWORD Width;
DWORD Height;
float MinZ;
float MaxZ;
} D3DVIEWPORT9, *LPD3DVIEWPORT9;

Members

X
Pixel coordinate of the upper-left corner of the viewport on the render-target surface. Unless you want to render to a subset of the surface, this member can be set to 0.
Y
Pixel coordinate of the upper-left corner of the viewport on the render-target surface. Unless you want to render to a subset of the surface, this member can be set to 0.
Width
Width dimension of the clip volume, in pixels. Unless you are rendering only to a subset of the surface, this member should be set to the width dimension of the render-target surface.
Height
Height dimension of the clip volume, in pixels. Unless you are rendering only to a subset of the surface, this member should be set to the height dimension of the render-target surface.
MinZ
Together with MaxZ, value describing the range of depth values into which a scene is to be rendered, the minimum and maximum values of the clip volume. Most applications set this value to 0.0. Clipping is performed after applying the projection matrix.
MaxZ
Together with MinZ, value describing the range of depth values into which a scene is to be rendered, the minimum and maximum values of the clip volume. Most applications set this value to 1.0. Clipping is performed after applying the projection matrix.

Remarks

The X, Y, Width, and Height members describe the position and dimensions of the viewport on the render-target surface. Usually, applications render to the entire target surface; when rendering on a 640 x 480 surface, these members should be 0, 0, 640, and 480, respectively. The MinZ and MaxZ are typically set to 0.0 and 1.0 but can be set to other values to achieve specific effects. For example, you might set them both to 0.0 to force the system to render objects to the foreground of a scene, or both to 1.0 to force the objects into the background.

When the viewport parameters for a device change (because of a call to the IDirect3DDevice9::SetViewport method), the driver builds a new transformation matrix.

 

2、視區設置

使用函數IDirect3DDevice9::SetViewport()設置Direct3D的視區,其聲明如下:

HRESULT SetViewport(
CONST D3DVIEWPORT9 * pViewport
);

SetViewport()的作用相當于把投影空間的頂點P(x, y, z, 1)乘以下面的矩陣:

3D編程文章(頂點坐標轉換) - ziouchen - Paul Allens Home

因此,屏幕上的二維坐標P'(x', y')的坐標等于:

x' = x * width/2 + startx + width/2

y' = y * (-height/2) + starty + height/2

z' = z * (maxz - minz) + minz

這些坐標被Direct3D用來進行裁剪。

與SetViewport()相對應,可以通過函數IDirect3DDevice9::GetViewport()獲得當前視區的相關信息,該函數聲明如下:

Retrieves the viewport parameters currently set for the device.

HRESULT GetViewport(
D3DVIEWPORT9 * pViewport
);

Parameters

pViewport
[out] Pointer to a D3DVIEWPORT9 structure, representing the returned viewport parameters.

Return Values

If the method succeeds, the return value is D3D_OK. D3DERR_INVALIDCALL is returned if the pViewport parameter is invalid.

Remarks

Typically, methods that return state will not work on a device that is created using D3DCREATE_PUREDEVICE. This method however, will work even on a pure device.

 

3、清空視區

一般情況下,在繪制每一幀圖形前都要先清空視區,即清空渲染目標表面上的視區矩形的內容:顏色緩沖區、深度緩沖區或者模板緩沖區。使用函數IDirect3DDevice9::Clear()來清空視區,該函數聲明如下:

Clears one or more surfaces such as a render target, multiple render targets, a stencil buffer, and a depth buffer.

HRESULT Clear(
DWORD Count,
CONST D3DRECT * pRects,
DWORD Flags,
D3DCOLOR Color,
float Z,
DWORD Stencil
);

Parameters

Count
[in] Number of rectangles in the array at pRects. Must be set to 0 if pRects is NULL. May not be 0 if pRects is a valid pointer.
pRects
[in] Pointer to an array of D3DRECT structures that describe the rectangles to clear. Set a rectangle to the dimensions of the rendering target to clear the entire surface. Each rectangle uses screen coordinates that correspond to points on the render target. Coordinates are clipped to the bounds of the viewport rectangle. To indicate that the entire viewport rectangle is to be cleared, set this parameter to NULL and Count to 0.
Flags
[in] Combination of one or more D3DCLEAR flags that specify the surface(s) that will be cleared.
Color
[in] Clear a render target to this ARGB color.
Z
[in] Clear the depth buffer to this new z value which ranges from 0 to 1. See remarks.
Stencil
[in] Clear the stencil buffer to this new value which ranges from 0 to 2n - 1 (n is the bit depth of the stencil buffer). See remarks.

Return Values

If the method succeeds, the return value is D3D_OK. If the method fails, the return value can be: D3DERR_INVALIDCALL.

Remarks

Use this method to clear a surface including: a render target, all render targets in an MRT, a stencil buffer, or a depth buffer. Flags determines how many surfaces are cleared. Use pRects to clear a subset of a surface defined by an array of rectangles.

IDirect3DDevice9::Clear will fail if you:

  • Try to clear either the depth buffer or the stencil buffer of a render target that does not have an attached depth buffer.
  • Try to clear the stencil buffer when the depth buffer does not contain stencil data.

D3DCLEAR

These flags identify a surface to reset when calling IDirect3DDevice9::Clear.

#define Description
D3DCLEAR_STENCIL Clear the stencil buffer.
D3DCLEAR_TARGET Clear a render target, or all targets in a multiple render target. See Multiple Render Targets (Direct3D 9).
D3DCLEAR_ZBUFFER Clear the depth buffer.

 

獲取Direct3D坐標變換矩陣

在Direct3D中,可以通過IDirect3DDevice9::GetTransform()獲取當前的世界變換矩陣、觀察變換矩陣以及投影變換矩陣,該函數聲明如下:

Retrieves a matrix describing a transformation state.

HRESULT GetTransform(
D3DTRANSFORMSTATETYPE State,
D3DMATRIX * pMatrix
);

Parameters

State
[in] Device state variable that is being modified. This parameter can be any member of the D3DTRANSFORMSTATETYPE enumerated type, or the D3DTS_WORLDMATRIX macro.
pMatrix
[out] Pointer to a D3DMATRIX structure, describing the returned transformation state.

Return Values

If the method succeeds, the return value is D3D_OK. D3DERR_INVALIDCALL if one of the arguments is invalid.

Remarks

This method will not return device state for a device that is created using D3DCREATE_PUREDEVICE. If you want to use this method, you must create your device with any of the other flag values in D3DCREATE.

示例程序

運行截圖:

3D編程文章(頂點坐標轉換) - ziouchen - Paul Allens Home

為了讓物體運動起來,需要不斷改變相應的世界矩陣,而投影矩陣和觀察矩陣通常不變,特別是投影矩陣在設置好之后基本上不需要重新設置。

在默認情況下,對于窗口顯示模式的應用程序,視口的大小就是當前窗口的客戶區的大小,對于全屏模式的應用程序,視口的大小就是屏幕的分辨率。除非特殊需要,絕大多數程序都采用這一默認設置,所以在以后的示例程序中都將略過視口設置,而采用其默認設置。

Direct3D中的一個面有前面和背面兩部分,默認情況下,在渲染時只畫前面,而剔除背面,而在本例中,因為圓筒在不斷地旋轉,剔除背面會使得圓筒表面不可見,所以需要指定不剔除背面。

 

完整源程序:

#include <d3dx9.h>

#define CLASS_NAME    "GameApp"

#define release_com(p)    do { if(p) { (p)->Release(); (p) = NULL; } } while(0)

IDirect3D9
*                g_d3d;
IDirect3DDevice9
*        g_device;
IDirect3DVertexBuffer9
* g_vertex_buffer;
HWND                    g_hwnd;

struct sCustomVertex
{
    D3DXVECTOR3    position;
    DWORD        color;
};

#define D3DFVF_CUSTOM_VERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE) 

void setup_world_matrix()
{
    
// build a world matrix which rotated around x-axis

    DWORD time  
= timeGetTime() % 1000;
    
float angle    = time * (2.0f * D3DX_PI) / 1000.0f;

    D3DXMATRIX mat_world;
    D3DXMatrixIdentity(
&mat_world);
    D3DXMatrixRotationX(
&mat_world, angle);

    g_device
->SetTransform(D3DTS_WORLD, &mat_world);
}

void setup_view_proj_matrix()
{
    D3DXVECTOR3 eye(
0.0f3.0f-5.0f);
    D3DXVECTOR3 at(
0.0f0.0f0.0f);
    D3DXVECTOR3 up(
0.0f1.0f0.0f);

    D3DXMATRIX mat_view;
    D3DXMatrixLookAtLH(
&mat_view, &eye, &at, &up);
    g_device
->SetTransform(D3DTS_VIEW, &mat_view);

    D3DXMATRIX mat_proj;
    D3DXMatrixPerspectiveFovLH(
&mat_proj, D3DX_PI/41.0f1.0f100.0f);
    g_device
->SetTransform(D3DTS_PROJECTION, &mat_proj);
}

void setup_viewport()
{
    RECT rect;
    GetClientRect(g_hwnd, 
&rect);

    D3DVIEWPORT9 viewport;

    viewport.X        
= 0;
    viewport.Y        
= 0;
    viewport.Width    
= rect.right;
    viewport.Height 
= rect.bottom;
    viewport.MinZ    
= 0.0f;
    viewport.MaxZ    
= 1.0f;

    g_device
->SetViewport(&viewport);
}

void init_geometry()
{    
    g_device
->CreateVertexBuffer(50 * 2 * sizeof(sCustomVertex), 0, D3DFVF_CUSTOM_VERTEX, D3DPOOL_DEFAULT, 
                                 
&g_vertex_buffer, NULL);

    sCustomVertex
* vertices;

    g_vertex_buffer
->Lock(00, (void**)&vertices, 0);

    
for(int i = 0; i < 50; i++)
    {
        
float theta = (2 * D3DX_PI * i) / (50 - 1);

        vertices[
2 * i + 0].position = D3DXVECTOR3(sin(theta), -1.0f, cos(theta));
        vertices[
2 * i + 0].color    = 0xffffffff;
        vertices[
2 * i + 1].position = D3DXVECTOR3(sin(theta),  1.0f, cos(theta));
        vertices[
2 * i + 1].color    = 0xff888888;
    }
    
    g_vertex_buffer
->Unlock();
}

bool init_d3d(HWND hwnd)
{
    g_d3d 
= Direct3DCreate9(D3D_SDK_VERSION);

    
if(g_d3d == NULL)
        
return false;

    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory(
&d3dpp, sizeof(d3dpp));

    d3dpp.Windowed            
= TRUE;
    d3dpp.SwapEffect        
= D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat    
= D3DFMT_UNKNOWN;

    
if(FAILED(g_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                  
&d3dpp, &g_device)))
    {
        
return false;
    }

    init_geometry();

    g_device
->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
    g_device
->SetRenderState(D3DRS_LIGHTING, FALSE);    // disable light, light default state is enable.

    setup_view_proj_matrix();
    setup_viewport();
    
    
return true;
}

void cleanup()
{
    release_com(g_vertex_buffer);
    release_com(g_device);
    release_com(g_d3d);
}

void render()
{
    g_device
->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(555), 1.0f0);

    g_device
->BeginScene();

    setup_world_matrix();

    g_device
->SetStreamSource(0, g_vertex_buffer, 0sizeof(sCustomVertex));
    g_device
->SetFVF(D3DFVF_CUSTOM_VERTEX);
    g_device
->DrawPrimitive(D3DPT_TRIANGLESTRIP, 02 * 50 - 2);

    g_device
->EndScene();

    g_device
->Present(NULL, NULL, NULL, NULL);
}

LRESULT WINAPI WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    
switch(msg)
    {
    
case WM_KEYDOWN:
        
if(wParam == VK_ESCAPE)
            DestroyWindow(hwnd);
        
break;

    
case WM_DESTROY:        
        PostQuitMessage(
0);
        
return 0;
    }

    
return DefWindowProc(hwnd, msg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE inst, HINSTANCE, LPSTR, INT)
{
    WNDCLASSEX wc;

    wc.cbSize            
= sizeof(WNDCLASSEX);
    wc.style            
= CS_CLASSDC;
    wc.lpfnWndProc        
= WinProc;
    wc.cbClsExtra        
= 0;
    wc.cbWndExtra        
= 0;
    wc.hInstance        
= inst;
    wc.hIcon            
= NULL;
    wc.hCursor            
= NULL;
    wc.hbrBackground    
= NULL;
    wc.lpszMenuName        
= NULL;
    wc.lpszClassName    
= CLASS_NAME;
    wc.hIconSm            
= NULL;

    
if(! RegisterClassEx(&wc))
        
return -1;

    HWND hwnd 
= CreateWindow(CLASS_NAME, "Direct3D App", WS_OVERLAPPEDWINDOW, 200100600500,
                             NULL, NULL, wc.hInstance, NULL);    

    
if(hwnd == NULL)
        
return -1;

    g_hwnd 
= hwnd;

    
if(init_d3d(hwnd))
    {
        ShowWindow(hwnd, SW_SHOWDEFAULT);
        UpdateWindow(hwnd);

        MSG msg;
        ZeroMemory(
&msg, sizeof(msg));

        
while(msg.message != WM_QUIT)
        {
            
if(PeekMessage(&msg, NULL, 00, PM_REMOVE))
            {
                TranslateMessage(
&msg);
                DispatchMessage(
&msg);
            }
                
            render();
        }
    }

    cleanup();
    UnregisterClass(CLASS_NAME, wc.hInstance);    

    
return 0;
}
posted on 2011-08-19 09:59 風輕云淡 閱讀(3551) 評論(0)  編輯 收藏 引用 所屬分類: DX
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            99国产成+人+综合+亚洲欧美| 久久久亚洲一区| 欧美在线精品一区| 亚洲一区二区三区乱码aⅴ| 一区二区精品在线| 中国亚洲黄色| 午夜精品999| 久久狠狠亚洲综合| 老巨人导航500精品| 欧美成人伊人久久综合网| 亚洲国产精品成人一区二区| 91久久久在线| 在线中文字幕日韩| 欧美在线一二三区| 欧美激情国产高清| 国产九色精品成人porny| 亚洲国产精品久久91精品| 日韩亚洲欧美在线观看| 欧美一区三区三区高中清蜜桃| 久热这里只精品99re8久| 亚洲夫妻自拍| 午夜精品久久久久久99热| 欧美激情第五页| 国产婷婷色一区二区三区在线| 91久久在线播放| 亚洲欧美日韩一区二区三区在线| 久热精品在线视频| 亚洲视频导航| 欧美激情a∨在线视频播放| 国产日韩欧美三级| 一区二区电影免费观看| 久久躁日日躁aaaaxxxx| 亚洲视频精选在线| 欧美精品成人在线| 一区二区在线视频播放| 亚洲深夜福利| 欧美一级二区| 欧美.com| 国产又爽又黄的激情精品视频| 亚洲伦理中文字幕| 久久女同互慰一区二区三区| 亚洲午夜电影| 国产精品videossex久久发布| 亚洲人成在线免费观看| 久久久精品国产一区二区三区| 一区二区三区日韩欧美精品| 欧美激情视频免费观看| 亚洲国产精品va在线看黑人 | 日韩视频一区二区| 亚洲六月丁香色婷婷综合久久| 午夜精品久久久| 9久草视频在线视频精品| 欧美阿v一级看视频| 亚洲高清网站| 欧美 日韩 国产在线| 欧美一区二区三区免费视| 国产麻豆成人精品| 亚洲一区二区在线| 日韩网站在线看片你懂的| 欧美日产国产成人免费图片| 欧美国产日韩在线观看| 亚洲午夜一区二区三区| 亚洲一区二区在线| 亚洲男人av电影| 一本色道久久综合狠狠躁篇的优点 | 另类亚洲自拍| 亚洲国产欧美日韩| 欧美高清hd18日本| 欧美1区2区视频| 亚洲欧洲精品一区二区三区不卡 | 国产精品丝袜白浆摸在线| 制服诱惑一区二区| 一区二区欧美视频| 国产精品欧美激情| 久久精品国产一区二区三| 欧美一级一区| 亚洲国产天堂网精品网站| 亚洲激情自拍| 国产精品老牛| 欧美1区视频| 国产色视频一区| 久久久久亚洲综合| 久久青青草综合| 99精品视频免费在线观看| 在线视频欧美日韩精品| 国产在线国偷精品产拍免费yy| 欧美二区乱c少妇| 欧美日韩一区二区三区在线看 | 欧美日韩视频免费播放| 欧美一区成人| 欧美成人免费在线视频| 亚洲欧美日本国产有色| 久久久水蜜桃| 亚洲男人天堂2024| 老色鬼精品视频在线观看播放| 亚洲私拍自拍| 久久一区激情| 欧美中文字幕在线| 欧美激情视频在线免费观看 欧美视频免费一 | 欧美在线视频免费播放| 久久一二三国产| 久久岛国电影| 欧美日韩第一区日日骚| 久久这里只有精品视频首页| 欧美日韩国产丝袜另类| 男同欧美伦乱| 国产精品综合色区在线观看| 亚洲区免费影片| 极品少妇一区二区三区| 宅男精品视频| 一本一本久久a久久精品综合麻豆 一本一本久久a久久精品牛牛影视 | 一区二区免费在线视频| 欧美一区午夜精品| 亚洲欧美视频在线观看| 欧美成人精品激情在线观看 | 亚洲在线观看视频| 欧美成人福利视频| 免费不卡在线观看av| 国产女同一区二区| 亚洲婷婷在线| 亚洲一区欧美| 欧美日韩性生活视频| 亚洲精品123区| 亚洲国产日韩精品| 久久免费精品日本久久中文字幕| 久久国产黑丝| 国产一区美女| 久久精品91| 久久精品日产第一区二区| 国产精品嫩草久久久久| 在线视频欧美一区| 午夜精品福利在线| 国产精品一区久久久久| 亚洲免费一区二区| 国产农村妇女毛片精品久久麻豆| 一区二区三区四区国产| 亚洲精品国精品久久99热一| 亚洲国产成人高清精品| 欧美在线三区| 久久久夜精品| 黄色亚洲大片免费在线观看| 欧美一区二区三区在线视频| 久久av老司机精品网站导航 | 亚洲每日在线| 欧美1级日本1级| 亚洲国产日韩欧美在线图片| 日韩一级视频免费观看在线| 欧美日韩第一页| 这里只有视频精品| 亚洲欧美中文在线视频| 国产区在线观看成人精品| 欧美在线日韩在线| 亚洲国产成人在线播放| 一区二区三欧美| 国产精品亚洲美女av网站| 久久成人亚洲| 亚洲国产欧美日韩| 亚洲砖区区免费| 极品尤物一区二区三区| 欧美激情亚洲自拍| 亚洲欧美大片| 欧美好吊妞视频| 亚洲专区在线| 亚洲电影免费| 国产精品久久久久秋霞鲁丝 | 日韩午夜高潮| 性色一区二区三区| 韩国免费一区| 欧美日韩精品在线视频| 欧美一区二区三区在线观看| 亚洲电影免费观看高清完整版在线 | 久久久精品国产99久久精品芒果| 欧美 日韩 国产在线| 亚洲视频第一页| 国产一区欧美日韩| 欧美理论电影网| 亚洲欧美日韩一区在线| 欧美国产精品一区| 欧美伊人久久大香线蕉综合69| 亚洲成色777777女色窝| 欧美日韩精品综合在线| 久久久亚洲国产天美传媒修理工| 日韩亚洲欧美中文三级| 久久久久国内| 亚洲影院色在线观看免费| 亚洲国产精品热久久| 国产日韩精品一区二区三区| 欧美精品18videos性欧美| 午夜在线精品偷拍| 亚洲欧洲视频| 免费日韩视频| 久久久另类综合| 欧美亚洲日本网站| 宅男66日本亚洲欧美视频| 亚洲欧洲一区二区在线观看| 一本大道久久a久久综合婷婷 | 国产精品久久久久久久免费软件| 久久久一区二区| 亚洲综合欧美| 国产精品99久久久久久久vr|