• <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>
            隨筆 - 132  文章 - 51  trackbacks - 0
            <2011年7月>
            262728293012
            3456789
            10111213141516
            17181920212223
            24252627282930
            31123456

            常用鏈接

            留言簿(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 風輕云淡 閱讀(3519) 評論(0)  編輯 收藏 引用 所屬分類: DX
            欧美激情精品久久久久| 亚洲午夜久久久影院| 国产69精品久久久久777| 亚洲精品乱码久久久久66| 国产精品久久久久久久久软件| 国产精品激情综合久久| 中文精品久久久久国产网址| 久久国产精品久久| 99久久人妻无码精品系列| 精品国际久久久久999波多野| 无码人妻精品一区二区三区久久 | 一本大道久久a久久精品综合| 久久久老熟女一区二区三区| 亚洲AV日韩精品久久久久| 久久精品国产亚洲精品2020| 久久久久久午夜成人影院| 国内精品伊人久久久久av一坑| 99久久精品国内| 久久综合九色综合精品| 久久99久久成人免费播放| 人人狠狠综合久久亚洲高清| 武侠古典久久婷婷狼人伊人| 久久人与动人物a级毛片| 无码人妻久久一区二区三区免费| 国内精品久久久久影院一蜜桃| 国产精品免费福利久久| 亚洲一本综合久久| 青青草原综合久久大伊人导航| 超级97碰碰碰碰久久久久最新| 久久综合狠狠综合久久| 狠狠色丁香久久婷婷综合五月| 亚洲精品高清国产一久久| 久久久人妻精品无码一区| 久久久国产亚洲精品| 亚洲国产一成人久久精品| 国内精品久久久久伊人av| 26uuu久久五月天| 日韩人妻无码一区二区三区久久99| 亚洲精品无码成人片久久| 亚洲天堂久久精品| 国产精品久久婷婷六月丁香|