我寫過很多 DirectX 代碼,也寫過很多關於 DirectX 的文章。我甚至還編寫過關於 DirectX 的線上培訓課程。它其實並不像某些開發人員所說的那麼難以理解。學習曲線一定會有,但一旦您過了這道坎,就不難理解 DirectX 的工作方式及其為何要如此工作的原因了。不過我也承認,DirectX 系列 API 的易用性應該更高些。
幾天前,我決定著手修補一下這個缺陷。我熬了一整夜,編寫了一個小標頭檔。隨後幾晚,我又將程式碼擴充到了近 5,000 行。我的目標是提供一些可藉助 Direct2D 更方便地構建應用程式的東西,並向如今盛行的所有“C++ 很難”或“DirectX 很難”之類的論斷髮起挑戰。我並沒打算再開發一個笨重的 DirectX 封裝。實際上,我決定藉助 C++11 製作一套更簡便的 DirectX API,同時不在核心 DirectX API 之上產生任何空間和時間開銷。您可以在下面的網址找到我開發的這個庫:dx.codeplex.com。
這個庫本身只包含一個名為 dx.h 的標頭檔,CodePlex 上的其餘源檔案提供了有關該標頭檔使用方法的樣本。
在本專欄文章中,我將向您展示如何利用這個庫更方便地執行各種與 DirectX 相關的常見活動。此外,我還將介紹這個庫的設計方法,以便您瞭解 C++11 如何協助提高傳統 COM API 的易用性,而不必求助於 Microsoft .NET Framework 等會對效能產生很大影響的封裝。
顯然,我們的重點是 Direct2D。要藉助 DirectX 開發類別最為廣泛的應用程式和遊戲,Direct2D 仍是最簡單也最有效方式。許多開發人員似乎加入到了兩個對立的陣營中。他們中有 DirectX 鐵杆開發人員:他們不斷學習各種版本的 DirectX API。他們在 DirectX 多年來的發展中曆經磨練,並且樂於成為這一進入門檻極高的“貴賓俱樂部”的一員(很少有開發人員能加入該俱樂部)。而在另一陣營的開發人員聽到了 DirectX 很難的訊息,不想跟 DirectX 扯上一丁點關係。不用說,他們往往會拒絕使用 C++。
我不屬於任一陣營。我相信 C++ 和 DirectX 不必如此困難。在上月的專欄文章 (msdn.microsoft.com/magazine/dn198239) 中,我介紹了 Direct2D 1.1 和作為先決條件的 Direct3D 和 DirectX Graphic Infrastructure (DXGI) 代碼,以建立一個裝置並管理交換鏈結。該代碼利用 D3D11CreateDevice 函數建立 Direct3D 裝置,適用於 GPU 或 CPU 呈現,長度約 35 行。不過,在我提供的小標頭檔的協助下,可將其精簡為:
auto device = CreateDevice();
CreateDevice 函數返回一個 Device1 對象。 由於所有 Direct3D 定義都位於 Direct3D 命名空間內,所以也可以這樣寫(更加明確):
Direct3D::Device1 device = Direct3D::CreateDevice();
Device1 對象不過是對 ID3D11Device1 COM 介面指標(DirectX 11.1 版本引入的 Direct3D 裝置介面)的封裝。 Device1 類派生自 Device 類,後者是對原 ID3D11Device 介面的封裝。 它代表一個引用,與直接擷取該介面指標本身相比,不會帶來任何額外開銷。 請注意,Device1 及其父類 Device 是常規的 C++ 類,而不是介面。 您可以將它們看作智能指標,但這有些過於簡單化。 當然,它們能夠處理引用計數並提供“->”運算子直接調用您選擇的方法,但在開始使用 dx.h 庫提供的諸多非虛方法時,才是它們真正大放異彩之時。
例如: 通常,您可能需要 Direct3D 裝置的 DXGI 介面來傳遞其他某種方法或函數。 不怕麻煩的話,可以這樣做:
auto device = Direct3D::CreateDevice();wrl::ComPtr<IDXGIDevice2> dxdevice;HR(device->QueryInterface(dxdevice.GetAddressOf()));
這當然可行,但現在您還必須直接處理 DXGI 裝置介面。另外,您還需要牢記,IDXGIDevice2 介面是 DirectX 11.1 版本的 DXGI 裝置介面。實際上,也可簡單地調用 AsDxgi 方法:
auto device = Direct3D::CreateDevice();auto dxdevice = device.AsDxgi();
返回的 Device2 對象(此次是在 Dxgi 命名空間中定義的)封裝 IDXGIDevice2 COM 介面指標,提供自己的一組非虛方法。再舉一個例子,您可能需要使用 DirectX“物件模型”訪問 DXGI 工廠:
auto device = Direct3D::CreateDevice();auto dxdevice = device.AsDxgi();auto adapter = dxdevice.GetAdapter();auto factory = adapter.GetParent();
當然,這是一種常見模式,是 Direct3D Device 類提供 GetDxgiFactory 方法作為捷徑的一種手段:
auto d3device = Direct3D::CreateDevice();auto dxfactory = d3device.GetDxgiFactory();