在前面的文章有稍微介紹了XNA的XNA Rendering Pipeline

現在,讓我們開始從頭了解吧!!

(也許有人會好奇,怎麼會要講這個...因為這個部分是很重要的,所以我才特別在往回寫,熟悉Vertex buffer與index buffer,在後面處理一些模型的幾何會很有幫助)

使用環境:

Visual Studio C# 2008任意版本

XNA 3.1

新增完畢XNA GS(game studio,以後簡稱CS) 3.1的專案以後,開啟Game1.cs的程式碼

在rendering pipeline中,我們知到頂點的資訊(包含position、normal、texture coordniate等),都是被儲存在Vertex Buffer中,然後再送進Vertex Processing處理一些轉換(包含將Local Coordniate轉換到World Coordniate等)。

而我們第一步就是要建立Vertex Buffer!!

宣告一個變數Vertex Buffer:

VertexBuffer mVertexBuffer;

(這邊建議讀者命名方式使用"匈牙利命名法則")

接下來宣告幾項變數:

    1. VertexDeclaration mDeclaration;
  1. 說明: 我們需要告知Pipeline現在我們的頂點包含哪些資料。(像是包含位置跟顏色等)

    1. VertexPositionColor[] mVertex;
    2. 說明: 宣告頂點,而頂點結構的內容指包含位置和顏色。這邊有多個選擇頂點的結構,像是VertexPositionColor、VertexPositionColorTexture、VertexPositionNormalTexture和VertexPositionTexture四種。

    3. VertexPositionColor: 可以宣告頂點位置和頂點顏色。

    4. VertexPositionColorTexture: 可以宣告頂點位置、顏色和貼圖座標。

    5. VertexPositionNormalTexture: 可以宣告頂點位置、法像量和貼圖座標。

    6. VertexPositionTexture: 可以宣告頂點位置和貼圖座標。

    7. BasicEffect basicEffect;
    8. 說明: 使用基本的特效,包含一些打光和一些矩陣(View matrix、projection matrix等)

    設定完變數以後,接下來就可以設定頂點的資料

    在建構子當中,建立頂點資訊,如下

    mVertex = new VertexPositionColor[4];

    mVertex[0].Position = new Vector3(-1, 1, 0);
    mVertex[0].Color = Color.Blue;

    mVertex[1].Position = new Vector3(-1, -1, 0);
    mVertex[1].Color = Color.Red;

    mVertex[2].Position = new Vector3(1, -1, 0);
    mVertex[2].Color = Color.Orange;

    mVertex[3].Position = new Vector3(1, 1, 0);
    mVertex[3].Color = Color.MediumPurple;

    這邊我們宣告的四個頂點,VertexPositionColor.Position設定頂點位置,是一個三維的座標。

    VertexPositionColor.Color設定頂點顏色。
      設定完畢以後,在Initialize函數中,初始化一些變數和設定一些相關的矩陣。

    mDeclaration = new VertexDeclaration(GraphicsDevice, VertexPositionColor.VertexElements);
    說明: 告知Pipeline現在的頂點結構,第一個參數傳入現在的GraphicsDevice,第二個參數傳入結構的型態,在面所說的四個頂典型態都會有一個VertexElements的成員,將它設定為那個即可。

    mVertexBuffer = new VertexBuffer(GraphicsDevice, VertexPositionColor.SizeInBytes * mVertex.Length, BufferUsage.None);
    說明: 建立VertexBuffer,第一個參數為GraphicsDevice,第二個參數設定就是現在Vertex Buffer的大小(取得頂點結構的大小以後,在乘上頂點數量),第三個參數設定Buffer的存取模式。
    mVertexBuffer.SetData<VertexPositionColor>(mVertex);
    說明: 設定VertexBuffer的頂點資料。

    Matrix view = Matrix.CreateLookAt(new Vector3(0, 0, 1), Vector3.Zero, Vector3.Up);
    說明: 設定View matrix,第一個參數為Camera的位置,第二個參數為Camera觀察的點,第三個參數為向上的方向,第三個參數用來告知,現在哪邊為上方,如果設定錯誤,可能會看到不是預期想看到的結果。)
    Matrix project = Matrix.CreateOrthographic(5, 5, 0, 1);
    說明: 設定投影矩陣,這邊使用平行投影。

    basicEffect = new BasicEffect(GraphicsDevice, null);
    說明: 建立一個BasicEffect的物件。
    basicEffect.VertexColorEnabled = true;
    說明: 開起頂點顏色
    basicEffect.World = Matrix.Identity;
    說明: 設定世界矩陣(包含旋轉、平移、縮放,這些稱為世界矩陣)
    basicEffect.View = view;
    說明: 設定視野矩陣(一般可能會看到一個詞,叫做ModelView matrix,這是因為world matrix可以直接跟view matrix相乘,這結果是相同的)
    basicEffect.Projection = project;
    說明: 設定投影矩陣。

    設定完以上參數以後,接下來我們就可以準備畫出結果了

    在Draw的函數中,打入下面程式碼

    GraphicsDevice.VertexDeclaration = mDeclaration;
    說明: 設定頂點結構

    GraphicsDevice.RenderState.PointSize = 10;
    說明: 設定頂點的點大小。

    GraphicsDevice.RenderState.CullMode = CullMode.None;
    說明: 設定Culling Mode,在Rendering pipeline中,先剃除掉看不到的面,這邊是指不開啟Culling,因為每個人設定頂點的方式不同,像是順時鐘設定或是逆時鐘設定等等(像這個範例我就是使用逆時鐘設定頂點),XNA預設是順時鐘為front face,所以我用逆時鐘的方式設定的話,是看不到結果的。

    basicEffect.Begin();
    basicEffect.CurrentTechnique.Passes[0].Begin();
    GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleFan, mVertex, 0, 2);
    說明: 將幾何圖形畫出,第一個參數為設定幾何模型的型態,像是點、線、三角形等,第二個參數為頂點的資料,第三個參數起始位置,第四個參數是說現在要畫幾個,第四個參數比較值得注意就是,你需要知道現在你要畫幾個,如果設定錯誤程式就會crush掉。
    basicEffect.CurrentTechnique.Passes[0].End();
    basicEffect.End();

    執行結果如下

    image

    使用triangle fan建立的結果

    image

    使用Line list結果(GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineList, mVertex, 0, 2))

    image

    使用Line Strip結果(GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineStrip, mVertex, 0, 3))

    上面三個結果請注意第四個參數

    最後跟大家補充一個填塞的方式,以第一張圖片來說,我們可以看到明明就是指有設定四個頂點,為什麼其他地方沒有設定的他也會有顏色那些!?

    原因是因為預設的參數中,填寫模式(Fill mode)為solid所以他會將顏色和點頂內插,當然我們也可以不指定。

    只要打入一行指令即可
    GraphicsDevice.RenderState.FillMode = FillMode.Point;

    FillMode一共有三個選擇
    1. 點
    2. 網格
    3. 填滿

    結果如下(使用triangle fan的連結方式)

    image

    image

    網格

    image

    填滿

    使用VertexBuffer來繪製簡單的幾何形狀的說明就到此結束..

    這邊各位可能會發現我沒有使用到Index Buffer來建立。

    沒有使用Index buffer的壞處就是我需要大量的點頂來描述現在的3D物件,而那些頂點,很多都是有可能重複到的!!

    image

    像1.4和2.6這兩個點根本就是重複的點,如果我知道連接的方式是怎麼樣的話,那我就可以自己指定連結,就不會使用XNA預設的方式填寫。而這就是Index Buffer的好處。

    檔案下載

    創作者介紹
    創作者 teexit1224 的頭像
    teexit1224

    StreamWhite

    teexit1224 發表在 痞客邦 留言(11) 人氣()