加入BLOG ADS 寫手們來加入吧!

在前面的文章有稍微介紹了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) 人氣()


    留言列表 (11)

    發表留言
    • 請問
    • 請問從maya轉.fbx匯入的模型可改變模型的頂點嗎
    • 獃獃
    • 你想要改變的模型頂點指的是說"將模型上面的頂點位置經由XNA調整?"

      如果是這樣的話是可以的。
    • 虎
    • 請問,要如何將模型上面的頂點位置,經由XNA來做調整呢??
    • foreach (ModelMesh mesh in model.Meshes)
      {
      foreach (ModelMeshPart meshPart in mesh.MeshParts)
      {
      VertexBuffer vb = meshPart.VertexBuffer;
      float[] verticesData = new float[meshPart.NumVertices * vb.VertexDeclaration.VertexStride];
      vb.GetData(verticesData);

      for (int i = 0; i < verticesData.Length; i += vb.VertexDeclaration.VertexStride)
      {
      float[] vertex = new float[3];
      vertex[0] = verticesData[i];
      vertex[1] = verticesData[i + sizeof(float)];
      vertex[2] = verticesData[i + 2 * sizeof(float)];
      }
      }
      }

      teexit1224 於 2010/09/11 16:14 回覆

    • teexit1224
    • 你可以用我上述的方法抓取頂點位置,但是你要自己再儲存起來。

      這個CODE適用於XNA 4.0...
      3.0和4.0這部分方法不同請注意。
    • 虎
    • 謝謝,我試試看
    • 虎
    • 請問一下,如果 我匯入.fbx檔,那麼我要如何取得fbx的每一個點的座標呢??可以舉個範例嬤??
    • teexit1224
    • 你可以用上述的方法將所有的點存在一個List中。

      例子的話我晚點再寫
    • 虎
    • 好的,謝謝您了
    • 匿名
    • 請問六樓的範例哪裡可以拿到或找到?可以寄E-MAIL給我嗎?我的mail是f770510yahoo .com.tw
      謝謝你!
    • 新手
    • 不好意思,請問一下xna3.0我要如何取得maya轉.fbx檔的各個頂點座標,因為我不是適用xna4.0的,不好意思,因為是新手 所以麻煩您了...
    • 訪客
    • 您好 謝謝您的教學 讓我受益良多!!