DirectX 9.0c遊戲開發手記之RPG編程自學日誌之10: Drawing with DirectX Graphics (用DirectX圖形繪圖)(第4節)(C)

        本文由哈利_蜘蛛俠原創,轉載請註明出處!有問題請聯繫[email protected]

 

        這一次我們繼續來講述Jim Adams老哥的RPG編程書籍第二版第二章的第4節:Getting Down to Drawing。這個超級長的節前兩次講了一多半內容,這一期我們要把它講完。

 

        再次將這一節的各小節的標題列在下面,以供大家參考:

1、Using Vertices (使用頂點)

2、Flexible Vertex Format (靈活頂點格式)

3、Using Vertex Buffers (使用頂點緩存)

4、Vertex Streams (頂點流)

5、Vertex Shaders (頂點着色器)

6、Transformations(變換)

7、The World Transformation (世界變換)

8、The View Transformation (視角變換)

9、The Projection Transformation (投影變換)

10、Materials and Colors (材質和顏色)

11、Clearing the Viewport (清除視口)

12、Beginning and Ending a Scene (開始和結束場景)

13、Rendering Polygons (渲染多邊形)

14、Presenting the Scene (展示場景)

 

        這一期要從Materials and Colors講到最後的Presenting the Scene。

 

        原文翻譯:

 

===============================================================================

 

 

2.4.10 Materials and Colors (材質和顏色)

 

        你已經看到了如何在頂點信息中聲明顏色,但是當談到多邊形的時候,它們也有賦予它們的特定的顏色屬性。你運用到一個多邊形面上的顏色稱爲材質(materials)。在運用Direct3D來繪製多邊形之前,你可以選擇給材質進行賦值以供使用(如果你選擇不使用材質,你可以使用頂點顏色,如果有頂點顏色的話)。


        每一個材質都需要一些顏色值來對其進行描述。使用Direct3D,定義材質的顏色值儲存在一個結構體中:

typedef struct_D3DMATERIAL9 {
  D3DCOLORVALUE Diffuse;    // Diffuse color component
  D3DCOLORVALUE Ambient;    // Ambient color component
  D3DCOLORVALUE Specular;   // Specular color component
  D3DCOLORVALUE Emisive;    // Emissive color component
  float            Power;   // Sharpness of specular highlights
} D3DMATERIAL9;

        在實際操作中,你只要處理一個顏色成分:Diffuse (漫反射)。你可以將Ambient 值設爲與Diffuse 相同的值,並且你可以將Specular 設爲0.0或1.0(等等!Specular不是一個3維向量嗎?)(同時將Power 設爲0.0)。我建議你嘗試給這些顏色成分賦上不同的值,以便對每個顏色成分產生的效果有一個概念。

        對於當前的目的來說,你將Diffuse 顏色運用到一個多邊形面上;材質的顏色可以取代頂點結構中的漫反射顏色成分。如果你想要將一個材質的顏色運用到一個已經使用了帶顏色的頂點的多邊形面上的話,那麼你會引起一個可以觀察到的(並且通常是你不想要的)多邊形顏色的改變。所以,最好是要麼使用材質,要麼使用頂點顏色,而不是二者同時使用。 


        在處理材質顏色成分的時候,你直接設定顏色成分,而非使用如D3DCOLOR_RGBA這樣的宏。但是不需要擔心——每個顏色成分都由它的首字母代替(r表示紅色,g表示綠色,b表示藍色,而a代表alpha 值),然後可以給它們賦上0.0到1.0之間的值。如果你想要創建一個材質來使用黃色,你可以如下建立材質結構體:

D3DMATERIAL9 d3dm;
 
// Clear out thematerial structure
ZeroMemory(&d3dm,sizeof(D3DMATERIAL9));
 
// Fill Diffuse andAmbient to Yellow color
d3dm.Diffuse.r =d3dm.Ambient.r = 1.0f;  // red
d3dm.Diffuse.g =d3dm.Ambient.g = 1.0f;  // green
d3dm.Diffuse.b =d3dm.Ambient.b = 0.0f;  // blue
d3dm.Diffuse.a =d3dm.Ambient.a = 1.0f;  // alpha

 

        你如何建立材質結構體是你的選擇,但是一旦該結構體建立起來後,你需要告訴Direct3D在渲染一個多邊形之前使用該材質。這正是IDirect3DDevice9::SetMaterial 函數的工作,它只取一個指向你的材質結構體的指針作爲參數:

IDirect3DDevice9::SetMaterial(CONSTD3DMATERIAL9 *pMaterial);

        一旦被調用後,之後渲染的所有的多邊形都會使用這個材質的設定。下面是設定之前定義的黃色材質的一個例子:

g_pD3DDevice->SetMaterial(&d3dm);


2.4.11 Clearing the Viewport (清理視口)

 

        你需要將後臺緩衝區打掃乾淨以準備進行繪製,這樣就清除了也許存在於那裏的圖形。使用IDirect3DDevice9::Clear 函數的話,這就是一件簡單的例行公事了:

HRESULTIDirect3DDevice9::Clear(
  DWORD           Count,    // 0
  CONST D3DRECT *pRects,    // NULL
  DWORD           Flags,    // D3DCLEAR_TARGET
  D3DCOLOR        Color,    // Color to clear to
  float               Z,    // 1.0f
  DWORD        Stencil);    // 0

        現階段唯一要擔心的的參數是Color,它是你想要將後臺緩衝區清理成的顏色。要使用的顏色值可以使用你生來就喜歡的、典型的D3DCOLOR_RGBA或D3DCOLOR_COLRVALUE宏來進行構造。假如說你想要將後臺緩衝區清理成淺藍色:

// g_pD3DDevice =pre-initialized device object
if(FAILED(g_pD3DDevice->Clear(0,NULL, D3DCLEAR_TARGET,            \
                       D3DCOLOR_RGBA(0, 0, 192, 255), 1.0f, 0))) {
    // Error occurred
}

        注意

===============================================================================

        示例中使用的D3DCLEAR_TARGET 標記告訴Direct3D 你想要清理當前的目標(屏幕或窗口)。還有一些有用的清理標記可供使用,其中的另一個你很快就會讀到的。

===============================================================================

 

 

2.4.12 Beginning and Ending a Scene (開始和結束一個場景)

 

        在你能夠渲染任何東西之前,你必須告訴Direct3D 來自己做好準備。這就是IDirect3DDevice9::BeginScene 函數的目標(它不取參數):

HRESULTIDirect3DDevice9::BeginScene();

        當你完成渲染場景之後,你需要告知Direct3D 來使用EndScene 函數:

HRESULTIDirect3DDevice9::EndScene();

        你不需要將Clear函數的調用插入到BeginScene 和EndScene 之間;你可以在你調用BeginScene 函數之前調用Clear 函數。在開始場景和結束場景函數的調用之間唯一需要插入的東西是渲染多邊形的函數。

 

 

2.4.13 Rendering Polygons (渲染多邊形)

 

        在漫長的煎熬之後,你要開始渲染多邊形了!你的遊戲引擎的典型框架會清理後臺緩衝區、開始場景、設置要使用的材質、繪製多邊形並結束場景。你已經看到了如何來做所有的這些事,除了繪製實際的多邊形。

        你使用下面的函數來繪製一個IDirect3DVertexBuffer9 對象(當然,是在調用設置頂點源和FVF着色器的函數之後):

HRESULTIDirect3DDevice9::DrawPrimitive(
  D3DPRIMITIVETYPE  PrimitiveType,      // Primitives to draw
  UINT              StartVertex,        // Vertex to start with (0)
  UINT              PrimitiveCount);    // # of primitives to draw

 

        第一個參數PrimitiveType告訴Direct3D要繪製什麼類型的多邊形(它可以是表2.4中列出來的之一)。參數StartVertex 使得你決定從哪個頂點開始繪製(一般來說是0)。你將你想要繪製的圖元(primitives)的總數賦給參數PrimitiveCount。

 

表2.4  DrawPrimitive的圖元類型

類型

描述

D3DPT_POINTLISH

將所有的頂點以像素進行繪製。

D3DPT_LINELIST

繪製一列孤立的線條,這些線條每個使用兩個頂點。

D3DPT_LINESTRIP

繪製一列相互連接的線條。

D3DPT_TRIANGLELIST

繪製一些每個使用三個頂點的多邊形。

D3DPT_TRIANGLESTRIP

繪製一個多邊形帶,第一個多邊形使用三個頂點,而後面的每個多邊形每個使用一個額外的頂點。

D3DPT_TRIANGLEFAN

以扇形繪製一些多邊形,且第一個頂點作爲把手(所有的多邊形都與之相連)。

 

        你使用的圖元類型取決於你如何將頂點數據填充進頂點緩存之中。如果你對每個多邊形使用3個頂點,你使用D3DPT_TRIANGLELIST類型。如果你使用更加高效的類型,例如三角形帶,那麼就使用D3DPT_TRIANGLESTRIP類型。

        現在唯一需要記住的事情就是你必須在渲染多邊形之前使用IDirect3DDevice9::BeginScene 函數來開始場景;否則,DrawPrimitive 函數的調用是失敗。

        假如說你已經創建了一個包含6個頂點的頂點緩存,它構造了兩個三角形並形成了一個正方形。渲染它們的步驟(當然還有BeginScene 和EndScene 函數,還要設定頂點源和FVF着色器)看起來如下所示:

// g_pD3DDevice =pre-initialized device object
// pD3DVB =pre-initialized vertex buffer
// sVertex =pre-constructed vertex structure
// VertexFVF =pre-constructed FVF descriptor
 
// Set the vertexstream and shader
g_pD3DDevice->SetStreamSource(0,pD3DVB, 0, sizeof(sVertex));
g_pD3DDevice->SetFVF(VertexFVF);
 
if(SUCCEEDED(g_pD3DDevice->BeginScene())){
 
  // Render the polygons
 if(FAILED(g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,    \
                                                     0, 2))) {
    // Error occurred
  }
// End the scene
g_pD3DDevice->EndScene();
}
 

 

2.4.14 Presenting the Scene (顯示場景)

 

        在經過了漫長的煎熬之後(At long last)(怎麼又是這句話?),你可以準備將後臺緩衝區翻轉到視口,然後向用戶展示你的圖形了,而你是通過下列函數來實現的:

HRESULTIDirect3DDevice9::Present(
  CONST RECT   *pSourceRect,
  CONST RECT   *pDestRect,
  HWND          hDestWindowOverride,
  CONST RGNDATA *pDirtyRegion);

        你可以安全地將IDirect3DDevice9::Present 函數的所有參數都設爲NULL,這告訴Direct3D 將整個顯示屏進行更新(因爲這個函數可以一次只顯示一部分),如下列代碼所示:

// g_pD3DDevice =pre-initialized device object
if(FAILED(g_pD3DDevice->Present(NULL,NULL, NULL, NULL))) {
    // Error occurred
}

 

        就是這樣了!爲了創建更多的逼真的場景,你使用很多不同的頂點緩存來在你的世界中繪製各種各樣的3-D物體。另外一種提高你的圖形的真實性的方式是使用紋理映射。

 

===============================================================================

 

        好啦,我們終於將這超級長的第2章第4節給搞定了!希望大家能夠理解。如果不理解的話也沒關係,可以去參考“龍書”第二版的第4章和第6章的內容,那裏講述得比較詳細,也不難理解(但是會有一些顯著的區別)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章