Managed DirectX +C# 開發(入門篇)第四章 入門程式一、建立裝置本節介紹的樣本為DirectX SDK內建的樣本,在這裡將其解釋一下,本樣本什麼也不做,只是顯示一個空白表單。現在先看程式啟動並執行主函數:static void Main() {//建立一個表單執行個體; using (CreateDevice frm = new CreateDevice()) {//如果表單執行個體建立成功,那麼對Direct3D進行初始化 if (!frm.InitializeGraphics()) {//如果未能進行初始化,則顯示一個錯誤訊息,並返回退出程式; MessageBox.Show("Could not initialize Direct3D. This tutorial will exit."); return; }//如果成功進行初始化,則顯示表單; frm.Show();// 如果表單處於運行狀態,則一直執行frm.Render(); while(frm.Created) { frm.Render(); Application.DoEvents(); } } }因為這個程式主要是為建立一個介面,因此主要的函數為frm.InitializeGraphics(),下面看它的代碼:public bool InitializeGraphics() { try { PresentParameters presentParams = new PresentParameters(); presentParams.Windowed=true; presentParams.SwapEffect = SwapEffect.Discard; device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams); return true; } catch (DirectXException) { return false; } } 注意,程式事先已定義了一個全域變數device,它是在DirectX裡的Device類,是所有繪圖操作所必須的,相當於我們機器裡的圖形卡,繪圖物件都依賴於所定義的這個類,其實,可以設定多個device。代碼PresentParameters presentParams = new PresentParameters();是一組參數,用來設定裝置把資料呈現在顯示器的方式。比如,接下來的下面語句的設定 presentParams.Windowed=true;表示我們的程式是全螢幕顯示還是視窗顯示。下面的參數設定用於控制緩衝交換的行為。在這裡選取的這個選項表示,如果緩衝沒能準備好顯示,那麼就丟棄緩衝區中的資料;另外一外有用的選項是SwapEffect.Flip,如果選擇了這個選項,那麼在運行時會建立一個額外的緩衝區,並且在顯示把緩衝區的內容拷貝到前景中。 presentParams.SwapEffect = SwapEffect.Discard;接下來的代碼是構造device:device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams);建構函式的第一個參數表示將使用哪個物理圖形卡,通常個人機器內只裝有一個圖形卡,但對於專業人員則就不一定了。這樣如果機器內有兩塊圖形卡,就可以用0或1來區分開是用哪塊圖形卡,預設的顯卡表示為0的圖形卡;第二個參數,為裝置的類型,現在選用的是建立一個硬體裝置,但如果有時我們的顯卡不支援某種功能時,可以選擇DeviceType.Reference;第三個參數是表示把裝置綁定到哪個對象上,可以是整個表單,或者是表單上的一個控制項,在這裡選擇是整個表單。第四個參數描述的是建立之後的行為。這些枚舉成員可以組合起來使用,使裝置具有多種行為。在本程式中使用的適合於所有頂點處理都用CPU計算。顯然,比所有頂點都用GPU計算要慢一些。第五個參數表示把資料顯示出來的方式,前面已經說過了。至此,圖形的初始化工作完成,接下來當程式運行時,當介面發生變化時,會執行OnPaint()函數。protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) { this.Render(); } 在這裡面,執行this.Render();現在再來看看這個函數都做了哪些工作。private void Render() {//如果裝置沒有建立成功,則返回 if (device == null) return; //使用蘭色填充背景 device.Clear(ClearFlags.Target, System.Drawing.Color.Blue, 1.0f, 0); //開始繪圖。 device.BeginScene(); //以後我們的繪圖工作都在這裡完成; device.EndScene(); device.Present(); }
二、建立一個三角形接下來,我們往情境是添加一個三角形,此樣本的完整代碼也可以在SDK中找到。繪一個三角形很簡單,只需三個點就可以了,為什麼是三角形而不是四邊形、五邊形的原因是,大家都知道,“不在同一直線上的三點決定一個平面”,因此利用大量三角形可以組合成3D世界裡的芸芸眾生。當然也可以使用四邊形來做,但處理的工作量顯然加大了。為了儲存點資料,在這裡使用Direct3D名稱空間的CustomVertex類,來儲存頂點座標,代碼是:CustomVertex.TransformedColored[] verts = new CustomVertex.TransformedColored[3]; verts[0].X=150;verts[0].Y=50;verts[0].Z=0.5f; verts[0].Rhw=1; verts[0].Color = System.Drawing.Color.Aqua.ToArgb(); verts[1].X=250;verts[1].Y=250;verts[1].Z=0.5f; verts[1].Rhw=1; verts[1].Color = System.Drawing.Color.Brown.ToArgb(); verts[2].X=50;verts[2].Y=250;verts[2].Z=0.5f; verts[2].Rhw=1; verts[2].Color = System.Drawing.Color.LightPink.ToArgb();在這裡定義了一個含有三個元素的數組,CustomVertex.TransformedColored[],這種頂點類型為帶有顏色無變換的頂點類型,帶有顏色很好理解,無變換後面會介紹到它。程式另外一部分代碼是建立頂點緩衝區,後面會介紹到它。在Render()函數中:device.VertexFormat = CustomVertex.TransformedColored.Format; device.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);表示我們會繪製一系列三角形,頂點為頂點緩衝區中從0開始,第三個參數1表示只繪製一個三角形;
三、建立其它圖形在繪三角形時,使用的是device.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);如果給出6個頂點,可以繪2個三角形,分別用頂點(0,1,2),(3,4,5);繪一個三角形,其實還可以繪製其它各種圖形;首先將程式中頂點個數設定為4個,CustomVertex.TransformedColored[] verts = new CustomVertex.TransformedColored[4]; verts[0].X=150;verts[0].Y=50;verts[0].Z=0.5f; verts[0].Rhw=1; verts[0].Color = System.Drawing.Color.Aqua.ToArgb(); verts[1].X=250;verts[1].Y=250;verts[1].Z=0.5f; verts[1].Rhw=1; verts[1].Color = System.Drawing.Color.Brown.ToArgb(); verts[2].X=50;verts[2].Y=250;verts[2].Z=0.5f; verts[2].Rhw=1; verts[2].Color = System.Drawing.Color.LightPink.ToArgb(); verts[3].X=10;verts[3].Y=200;verts[3].Z=0.5f; verts[3].Rhw=1; verts[3].Color = System.Drawing.Color.Aqua.ToArgb(); stm.Write(verts);同時頂點緩衝區也更改為4:vertexBuffer = new VertexBuffer(typeof(CustomVertex.TransformedColored), 4, dev, 0, CustomVertex.TransformedColored.Format, Pool.Default);將繪製圖元的代碼更改為:device.DrawPrimitives(PrimitiveType.TriangleStrip, 0,2);三角形連環是一系列相連的三角形,每兩個相鄰的三角形共用兩個頂點。剔除模式會自動翻轉所有偶數個三角形,因為相鄰的三角形共用兩個頂點,它們會被翻到反方向。這也是複雜的3D對象使用的最多的圖元類型。執行結果為:也就是說,如果給定一系列點,繪製三角形採用的頂點是(0,1,2)、(1,2,3)……注意:在初始化圖形函數中加入以下代碼:device.RenderState.CullMode = Cull.None; 如果代碼是:device.DrawPrimitives(PrimitiveType.TriangleFan, 0,2);執行結果為:這種方法三角形共用一個頂點,也就是說,如果給定一系列點,繪製三角形採用的頂點是(0,1,2)、(0,2,3)、(0,3,4)……如果代碼是:device.DrawPrimitives(PrimitiveType.LineList, 0,2);執行結果是:把每一對點作為單獨的直線來繪製。使用時至少需要有兩個頂點。