使用Vertex Buffer繪製基本幾何形狀

使用Vertex Buffer繪製基本幾何形狀

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

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

接下來宣告幾項變數:

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

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

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

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設定頂點顏色。

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

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

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

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

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

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

    設定完畢以後,在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的好處。

檔案下載