影像處理---深入ManagedDirectX9(5)(轉)

post0發表於2007-08-12
影像處理---深入ManagedDirectX9(5)(轉)[@more@]

  使用簡單的渲染技術

  至今為止,我們的渲染工作效率都很低。每次渲染場景時,都要分配新的頂點列表,並且所有東西儲存在系統記憶體裡。現代顯示卡整合了足夠的視訊記憶體,把頂點資料存放在視訊記憶體可以獲得大幅的新能提升:存放在系統記憶體裡的資料,渲染每一幀時都要複製到顯示卡,這會帶來極大的損失。只有移除每幀時的這種分配才能幫助我們提高效能。

  使用頂點緩衝(Using Vertex Buffers)

  Direct3D已經包含了這種機制:頂點緩衝(vertex buffer)。頂點緩衝,就像他名字的意思一樣:一塊儲存頂點的記憶體。頂點緩衝的機動效能完美實現共享場景裡變經過變換的幾何體。如何讓我們在第一章編寫的三角形程式使用頂點緩衝呢?

  建立頂點緩衝同樣簡單,有三個建構函式能完成這個任務,我們依次來看看:

  public VertexBuffer( Device device, int sizeOfBufferInBytes, Usage usage, VertexFormats vertexFormat, Pool pool);

  public VertexBuffer( Type typeVertexType, int numVerts, Device device, Usage usage,VertexFormats vertexFormat, Pool pool);

  以下是各引數的意義:

  device――用來建立頂點緩衝的device,建立的頂點緩衝只能被這個device使用;

  sizeOfBufferInBytes――所建立的頂點緩衝大小,以位元組為單位。使用帶有這個引數的建構函式建立的頂點緩衝可以存放任何型別的頂點;

  typeVertexType――如果去要建立的頂點緩衝只儲存一種型別的頂點,則使用這個引數。它的值可以是CustomVertex類中的頂點結構型別,也可以是自定義的頂點型別。且這個值不能為null;

  numVert――指定了頂點緩衝的儲存型別之後,也必須指定緩衝儲存的頂點數量最大值。這個值必須大於0;

  usage――定義如何使用頂點緩衝。並不會是所有Usage型別的成員都能使用,只有一下幾個是正確的引數:

  DoNotClip,Dynamic, Npatches, Points, PTPatches, SoftwareProcessing, WriteOnly;

  vertexFormat―― 定義儲存在頂點緩衝中的頂點格式。,如果建立的為通用緩衝的話,則使用VertexFormat.None;

  pool――定位頂點緩衝使用的記憶體池位置,可以指定一下幾個記憶體池位置:

  Default, Managed, SystemMemory, Scratch。

  觀察第一章中的程式,把三角形的資料移動到頂點緩衝裡應該很容易。首先,申明頂點緩衝變數:

  private Device device = null;

  private VertexBuffer vb = null;

  接著新增建立三角形的程式碼:

  device = new (0,DeviceType.Hardware, this.CreatFlags.softwreVertexProccessing, presentParams);

  CustomVertex.positionColored[] verts = new CustomVertex. positionColored[3];

  Verts[0].SetPosition(new Vector3(0.0f,1.0f,1.0f));

  Verts[0].Color = System.Drawing.Color.Aqua.ToArgb();

  Verts[1]`````````

  Verts[2]`````````

  vb = new VertexBuffer(typeof(VustomVertex.PositionColored),2,device,Usage.Dynamic| Usage.WriteOnly, CustomVertex.PositionColored.Format, Pllo.Default);

  vb.SetData(vets,0,LockFlags.None);

  唯一的改變就是定義了三角形之後的兩行程式碼。首先,建立用來儲存三個頂點的頂點緩衝。出於效能上的考慮,建立的緩衝是動態、只讀的並且位於預設的記憶體池。接下來,我們把三角形的頂點放到緩衝內,使用簡單的SetData方法。這個方法接收任何型別的物件作為第一個引數,第二個引數是頂點緩衝中所要放置資料地址的便宜量。我們打算填充所有的頂點緩衝,所以設定為0。最後一個引數描述了當寫入資料時,如何鎖定緩衝。我們將稍後討論鎖存機制;現在,不用關心他是怎樣鎖定的。

  現在編譯程式,很自然,得到了一個編譯錯誤:因為OnPaint方法裡的DrawUserPrimitives需要獲得verts變數。需要有一個方法告訴Direct3D,我們要繪製頂點緩衝裡的內容,而不是先前所申明的陣列。呼叫device的SetStreamSource讓Direct3D繪圖的時候讀取頂點緩衝。這個方法有以下兩種過載:

  public void SetStreamSource(int streamNumber, VertexBuffer streamData, int offsetInBytes, int stride);

  public void SetStreamSource( int streamNumber, VertexBuffer streamData, int offsetInBytes);

  兩個函式的不同之處在於其中一個多了表示(資料)流步幅大小(stride size of the stream)的引數。第一個引數是這段資料所使用流的數量。現在,把它設定為0即可;我們會在下一章討論使用多個流。第二個引數是作為資料來源的頂點緩衝,第三個則是頂點緩衝裡需要DirectX繪製的資料的偏移量(以位元組為單位)。stride則是緩衝裡每一個頂點的大小。如果是用特定型別建立的頂點緩衝,則不需要這個引數。

  現在修改繪圖的方法:

  device.SetStreamSource(0, vb, 0);

  device.DrawPrimitives(PrimitiveType.TriangleLise, 0, 1);

  正如剛才所描述的,我們把頂點緩衝作為資料流0,同時把偏移量設定為0,使用所有資料。值得注意的是,我們同時也改變了真正繪圖的函式。既然所有資料都在頂點緩衝裡了,就不需要呼叫DrawUserPrimitives方法。因為DrawUserPrimitives只是用於繪製直接傳遞給它的使用者定義資料。更加通用的DrawPrimitives將會繪製來自資料流源裡的幾何體。DrawPrimitives有三個引數,第一個我們已經討論過了。第二個表示流裡的起始頂點,最後一個表示所要繪製的幾何體個數。

  就連這個僅繪製一個三角形的小樣在使用了頂點緩衝之後都帶來了10%的效能提升(基於畫面更新率,即幀頻frame rate)。我們會在稍後幾張來討論有關效能及幀頻。不幸的是,當你嘗試改變視窗大小的時候,三角形會立即消失。(注:偶在實際測試時三角形並米有消失,只是當視窗縮放為一定比例時,三角形會消失)

  有幾種情況會導致這種行為,其中的兩種我們先前已經討論過了。回想一下上一章,我們知道在改變視窗大小的時候,裝置會自動重置。但當所建立的資源位於預設的記憶體池時(比如頂點緩衝),重置裝置會釋緩衝。所以當改變視窗大小的時候,重置了device,釋放了頂點緩衝。Managed DirectX有一個極好的特新就是在重置device之後會自動的重建頂點緩衝。但是,這是頂點緩衝裡已經沒有了資料,所以沒有任何東西被繪製出來。

  我們可以捕獲頂點緩衝一個叫做“created”的事件,它會在重建頂點緩衝,準備好填充資料的時候發生。現在是使用這個事件更新我們程式的時候了,修改程式碼如下:

  private void OnVertexBufferCreate(object sender, EventArgs e)

  {

  VertexBuffer buffer = (VertexBuffer)sender;

  CustomVertex.positionColored[] verts = new CustomVertex. positionColored[3];

  Verts[0].SetPosition(new Vector3(0.0f,1.0f,1.0f));

  Verts[0].Color = System.Drawing.Color.Aqua.ToArgb();

  Verts[1]`````````

  Verts[2]`````````

  buffer.SetData(verts,0,LockFlags.None);

  }

  訂閱事件處理程式:

  vb.Created += new EventHandleer(this.OnVertexBufferCreate);

  OnVertexBufferCreate(vb,null);

  這段程式碼為頂點緩衝訂閱了事件處理程式,並且保證無論在什麼情況下建立頂點緩衝,都會呼叫OnVertexBufferCreate方法。因為第一次建立頂點緩衝的時候,還沒有訂閱過處理程式,所以需要手動呼叫一次。

  好了,透過使用video memory和頂點緩衝,我們已經把原來緩慢的小樣改變為了一個高效的程式。當然,它還是相當的枯燥。那麼,接下來讓我們創造一個盒子吧。

  

  

  (第五部分完)

  注:所有程式碼在DirectX 9.0 SDK Update (Summer 2003)下透過除錯執行,即DirectX的元件版本均為1.0.1901.0,在DirectX 9.0 SDK Update (October 2004)下需要稍做改動^_

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8225414/viewspace-951665/,如需轉載,請註明出處,否則將追究法律責任。

相關文章